A simple actor-based simulation of tag, implemented in rust.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
2.2 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. pub type Distance = isize;
  2. pub struct Position {
  3. pub x: Distance,
  4. pub y: Distance,
  5. }
  6. impl From<(Distance, Distance)> for Position {
  7. fn from((x, y): (Distance, Distance)) -> Self {
  8. Self { x, y }
  9. }
  10. }
  11. #[derive(Debug)]
  12. pub struct Direction {
  13. pub x: Distance,
  14. pub y: Distance,
  15. }
  16. impl From<(Distance, Distance)> for Direction {
  17. fn from((x, y): (Distance, Distance)) -> Self {
  18. Self { x, y }
  19. }
  20. }
  21. pub type AgentId = usize;
  22. pub struct WorldView {
  23. pub self_id: AgentId,
  24. pub tagged: AgentId,
  25. pub tagged_by: Option<AgentId>,
  26. pub bounds_distance: (Distance, Distance, Distance, Distance),
  27. pub other_agents: Vec<(Direction, AgentId)>,
  28. }
  29. #[derive(Debug)]
  30. pub enum Move {
  31. Noop, // Why not an Option?
  32. TryTag(AgentId),
  33. TryMove(Direction),
  34. }
  35. pub trait Agent {
  36. fn next_move(&self, view: WorldView) -> Move;
  37. }
  38. pub struct NullAgent;
  39. impl Agent for NullAgent {
  40. fn next_move(&self, _view: WorldView) -> Move {
  41. Move::Noop
  42. }
  43. }
  44. use std::cell::RefCell;
  45. pub struct ScriptedAgent {
  46. moves: RefCell<Vec<Move>>,
  47. }
  48. impl ScriptedAgent {
  49. pub fn new(mut moves: Vec<Move>) -> Self {
  50. moves.reverse();
  51. Self {
  52. moves: RefCell::new(moves),
  53. }
  54. }
  55. }
  56. impl Agent for ScriptedAgent {
  57. fn next_move(&self, _view: WorldView) -> Move {
  58. self
  59. .moves
  60. .borrow_mut()
  61. .pop()
  62. .expect("ScriptedAgent has no moves left to make")
  63. }
  64. }
  65. pub struct SimpleAgent;
  66. fn rand(exclusive_upper_bound: u32) -> u32 {
  67. std::time::SystemTime::now()
  68. .duration_since(std::time::UNIX_EPOCH)
  69. .unwrap()
  70. .subsec_micros()
  71. % exclusive_upper_bound
  72. }
  73. fn random_move() -> Move {
  74. Move::TryMove(
  75. match rand(8) {
  76. 0 => (-1, -1),
  77. 1 => (0, -1),
  78. 2 => (1, -1),
  79. 3 => (1, 0),
  80. 4 => (1, 1),
  81. 5 => (0, 1),
  82. 6 => (-1, 1),
  83. 7 => (-1, 0),
  84. _ => unreachable!(),
  85. }
  86. .into(),
  87. )
  88. }
  89. impl Agent for SimpleAgent {
  90. fn next_move(&self, view: WorldView) -> Move {
  91. if view.self_id == view.tagged {
  92. match view
  93. .other_agents
  94. .iter()
  95. .find(|(dist, id)| dist.x.abs() <= 1 && dist.y.abs() <= 1 && Some(*id) != view.tagged_by)
  96. {
  97. Some((_, other)) => Move::TryTag(*other),
  98. None => random_move(),
  99. }
  100. } else {
  101. random_move()
  102. }
  103. }
  104. }