sensing_scouter.py 4.0 KB

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