sensing_scouter.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import numpy as np
  2. from pathfinding.core.diagonal_movement import DiagonalMovement
  3. from pathfinding.core.grid import Grid
  4. from pathfinding.finder.a_star import AStarFinder
  5. from simulation.board import Board
  6. from simulation.logic.dumb_scouter import DumbScouter
  7. class SensingScouter(DumbScouter):
  8. def __init__(self, board, knowledge, x, y, use_diagonal=False, sightline=-1, light_compute=True):
  9. DumbScouter.__init__(self, board, knowledge, x, y)
  10. self.use_diagonal = use_diagonal
  11. self.sight_see = sightline if sightline > 0 else 1
  12. self.light_compute = light_compute
  13. self.goal = None
  14. self.path = []
  15. def get_matrix(self, x0, y0, x1, y1):
  16. width = x1 - x0
  17. height = y1 - y0
  18. matrix = np.zeros((width, height))
  19. for y in range(height):
  20. for x in range(width):
  21. if self.board.get_blob(x0 + x, y0 + y) > 0:
  22. matrix[x, y] = (1 + Board.MAX_BLOB - self.board.get_blob(x0 + x, y0 + y)) * 1.5
  23. elif self.board.is_touched(x0 + x, y0 + y):
  24. matrix[x, y] = Board.MAX_BLOB * 2
  25. else:
  26. matrix[x, y] = 1
  27. return np.transpose(matrix)
  28. def choose_goal(self):
  29. x0, y0 = max(0, self.x - self.sight_see), max(0, self.y - self.sight_see)
  30. x1, y1 = min(self.board.width, self.x + self.sight_see + 1), min(self.board.height, self.y + self.sight_see + 1)
  31. mask = np.zeros((x1 - x0, y1 - y0), dtype=bool)
  32. mask[self.x - x0, self.y - y0] = True
  33. see = np.ma.masked_where(mask, self.board.dropped_blob[x0:x1, y0:y1])
  34. min_indices = np.ma.where(see == np.min(see))
  35. if len(min_indices[0]) == 0:
  36. return None
  37. else:
  38. i = np.random.randint(len(min_indices[0]))
  39. return min_indices[0][i] + x0, min_indices[1][i] + y0
  40. def best_way_to(self):
  41. if self.sight_see > 0:
  42. x0, y0 = max(0, self.x - self.sight_see), max(0, self.y - self.sight_see)
  43. x1, y1 = min(self.board.width, self.x + self.sight_see + 1), min(self.board.height,
  44. self.y + self.sight_see + 1)
  45. else:
  46. x0, y0 = 0, 0
  47. x1, y1 = self.board.width, self.board.height
  48. grid = Grid(matrix=self.get_matrix(x0, y0, x1, y1))
  49. start = grid.node(self.x - x0, self.y - y0)
  50. end = grid.node(self.goal[0] - x0, self.goal[1] - y0)
  51. if self.use_diagonal:
  52. finder = AStarFinder(diagonal_movement=DiagonalMovement.always)
  53. else:
  54. finder = AStarFinder(diagonal_movement=DiagonalMovement.never)
  55. self.path, runs = finder.find_path(start, end, grid)
  56. self.path = self.path[1:]
  57. for i, step in enumerate(self.path):
  58. self.path[i] = (step[0] + x0, step[1] + y0)
  59. def reached(self, goal):
  60. return goal is not None and self.x == goal[0] and self.y == goal[1]
  61. def move(self):
  62. # Scouter has no more goal
  63. if self.goal is None: # or self.board.get_blob(self.goal[0], self.goal[1]) != 0:
  64. self.goal = self.choose_goal()
  65. if self.goal[0] == self.x and self.goal[1] == self.y:
  66. print("Shouldn't happen")
  67. self.path = []
  68. # No goal
  69. if self.goal is None:
  70. return
  71. # Scouter has no more path to goal
  72. if len(self.path) == 0 or not self.light_compute:
  73. self.best_way_to()
  74. # No path found, search another goal next time
  75. if len(self.path) == 0:
  76. self.goal = None
  77. return
  78. new_pos = self.path[0]
  79. self.path = self.path[1:]
  80. self.x = new_pos[0]
  81. self.y = new_pos[1]
  82. # Scouter reached goal
  83. if self.reached(self.goal):
  84. self.goal = None
  85. self.path = []
  86. def reset(self):
  87. self.goal = None
  88. self.path = []
  89. self.x = 0
  90. self.y = 0