123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- import random
- import numpy as np
- from pathfinding.core.diagonal_movement import DiagonalMovement
- from pathfinding.core.grid import Grid
- from pathfinding.finder.a_star import AStarFinder
- from simulation.board import Board
- from simulation.logic.dumb_scouter import DumbScouter
- class Gatherer(DumbScouter):
- def __init__(self, board, knowledge, x, y, use_diagonal=True, sight_see=-1, light_compute=True):
- DumbScouter.__init__(self, board, knowledge, x, y)
- self.use_diagonal = use_diagonal
- self.light_compute = light_compute
- self.sight_see = sight_see if sight_see > 0 else max(self.board.width, self.board.height)
- self.goal = None
- self.path = []
- def get_matrix(self, x0, y0, x1, y1):
- width = x1 - x0
- height = y1 - y0
- matrix = np.zeros((width, height))
- for y in range(height):
- for x in range(width):
- if self.board.get_blob(x0 + x, y0 + y) > 0:
- matrix[x, y] = 1 + (Board.MAX_BLOB - self.board.get_blob(x0 + x, y0 + y))
- else:
- if self.board.is_touched(x0 + x, y0 + y):
- matrix[x, y] = Board.MAX_BLOB * 2
- else:
- matrix[x, y] = 0
- return np.transpose(matrix)
- def compute_sight_see_goal(self, x0, y0, x1, y1):
- if x0 <= self.goal[0] < x1 and y0 <= self.goal[1] < y1:
- # Goal in sight_see
- return self.goal[0] - x0, self.goal[1] - y0
- delta_x = self.x - self.goal[0]
- delta_y = self.y - self.goal[1]
- t_x = None
- if delta_x != 0:
- x_collision = x0 if delta_x > 0 else x1 - 1
- t_x = (x_collision - self.goal[0]) / delta_x
- t_y = None
- if delta_y != 0:
- y_collision = y0 if delta_y >= 0 else y1 - 1
- t_y = (y_collision - self.goal[1]) / delta_y
- if t_x is None or not (0 <= t_x <= 1):
- t = t_y
- elif t_y is None or not (0 <= t_y <= 1):
- t = t_x
- else:
- t = min(t_x, t_y)
- symb_goal = (int(self.goal[0] + t * delta_x), int(self.goal[1] + t * delta_y))
- found = self.board.is_touched(symb_goal[0], symb_goal[1])
- while not found and t <= 1:
- inc = 1 / (self.board.width + self.board.height)
- t += inc
- symb_goal = (int(self.goal[0] + t * delta_x), int(self.goal[1] + t * delta_y))
- found = self.board.is_touched(symb_goal[0], symb_goal[1])
- return symb_goal[0] - x0, symb_goal[1] - y0
- def best_way_to(self):
- x0, y0 = max(0, self.x - self.sight_see), max(0, self.y - self.sight_see)
- x1, y1 = min(self.board.width, self.x + self.sight_see + 1), min(self.board.height, self.y + self.sight_see + 1)
- grid = Grid(matrix=self.get_matrix(x0, y0, x1, y1))
- x_goal, y_goal = self.compute_sight_see_goal(x0, y0, x1, y1)
- start = grid.node(self.x - x0, self.y - y0)
- end = grid.node(x_goal, y_goal)
- if self.use_diagonal:
- finder = AStarFinder(diagonal_movement=DiagonalMovement.always)
- else:
- finder = AStarFinder(diagonal_movement=DiagonalMovement.never)
- self.path, runs = finder.find_path(start, end, grid)
- self.path = self.path[1:]
- for i, step in enumerate(self.path):
- self.path[i] = (step[0] + x0, step[1] + y0)
- def reached(self, goal):
- return goal is not None and self.x == goal[0] and self.y == goal[1]
- def choose_goal(self):
- if len(self.knowledge['food']) == 0:
- return None
- elif len(self.knowledge['food']) == 1:
- if self.reached(self.knowledge['food'][0]):
- return None
- else:
- return self.knowledge['food'][0]
- else:
- i = random.randrange(len(self.knowledge['food']))
- while self.reached(self.knowledge['food'][i]):
- i = random.randrange(len(self.knowledge['food']))
- return self.knowledge['food'][i]
- def reset(self):
- self.goal = None
- self.path = []
- self.x = 0
- self.y = 0
- def move(self):
- # Scouter has no more goal
- if self.goal is None or self.goal not in self.knowledge['food']:
- self.goal = self.choose_goal()
- self.path = []
- # No goal
- if self.goal is None:
- return
- # Scouter has no more path to goal
- if len(self.path) == 0 or not self.light_compute:
- self.best_way_to()
- # No path found, search another goal next time
- if len(self.path) == 0:
- self.goal = None
- return
- new_pos = self.path[0]
- self.path = self.path[1:]
- self.x = new_pos[0]
- self.y = new_pos[1]
- # Scouter reached goal
- if self.reached(self.goal):
- self.goal = None
- self.path = []
|