def __init__(self, game): self.environment = None self.game = game self.dim = cfg.environment()['dim'] self.resolution = cfg.qlearing()['resolution'] self.alpha = cfg.qlearing()['alpha'] self.epsilon = cfg.qlearing()['epsilon'] self.gamma = cfg.qlearing()['gamma'] self.LEARNING = cfg.qlearing()['learning'] self.NEW_QTABLE = cfg.qlearing()['new_qtable'] self.number_of_directions = cfg.qlearing()['number_of_directions'] self.qtable = self.load_qtable() self.frames = 0 self.epoch = 0 self.max_epochs = cfg.qlearing()['max_epochs'] self.max_frames = cfg.qlearing()['max_ticks'] # Debug self.grid = cfg.qlearing()['print_grid'] self.arrows = cfg.qlearing()['print_vectors'] self.QDEBUG_LAYER = 0 self.AGENT_INDEX_DEBUG = 0 if self.arrows: self.ARROW_FISH_SPRITE, self.ARROW_PREDATOR_SPRITE = self.arrow_sprite( ) self.stat_filename = None if self.LEARNING: self.setup_stat_file()
def kill_all_emigrants(self): tolerance = cfg.environment()['border_tolerance'] emigrants = [] self.fish_qtree.set_mask(gen_border('top', tolerance=tolerance)) [ emigrants.append(emigrant) for emigrant in [element[2] for element in self.fish_qtree.elements()] ] self.fish_qtree.set_mask(gen_border('right', tolerance=tolerance)) [ emigrants.append(emigrant) for emigrant in [element[2] for element in self.fish_qtree.elements()] ] self.fish_qtree.set_mask(gen_border('bottom', tolerance=tolerance)) [ emigrants.append(emigrant) for emigrant in [element[2] for element in self.fish_qtree.elements()] ] self.fish_qtree.set_mask(gen_border('left', tolerance=tolerance)) [ emigrants.append(emigrant) for emigrant in [element[2] for element in self.fish_qtree.elements()] ] if cfg.qlearing()['predators_learning']: self.predator_qtree.set_mask(gen_border('top', tolerance=tolerance)) [ emigrants.append(emigrant) for emigrant in [element[2] for element in self.predator_qtree.elements()] ] self.predator_qtree.set_mask( gen_border('right', tolerance=tolerance)) [ emigrants.append(emigrant) for emigrant in [element[2] for element in self.predator_qtree.elements()] ] self.predator_qtree.set_mask( gen_border('bottom', tolerance=tolerance)) [ emigrants.append(emigrant) for emigrant in [element[2] for element in self.predator_qtree.elements()] ] self.predator_qtree.set_mask( gen_border('left', tolerance=tolerance)) [ emigrants.append(emigrant) for emigrant in [element[2] for element in self.predator_qtree.elements()] ] [emigrant.die() for emigrant in emigrants]
def gen_border(*args, **kwargs): w, h = cfg.environment()['dim'] tolerance = kwargs['tolerance'] if 'top' in args: return np.array([[-tolerance, -tolerance], [w + tolerance, -tolerance], [w + tolerance, tolerance], [-tolerance, tolerance]]) elif 'right' in args: return np.array([[w - tolerance, -tolerance], [w + tolerance, -tolerance], [w + tolerance, h + tolerance], [w - tolerance, h + tolerance]]) elif 'bottom' in args: return np.array([[-tolerance, -tolerance + h], [w + tolerance, -tolerance + h], [w + tolerance, tolerance + h], [-tolerance, tolerance + h]]) elif 'left': return np.array([[-tolerance, -tolerance], [tolerance, -tolerance], [tolerance, h + tolerance], [-tolerance, h + tolerance]]) else: raise NotImplemented()
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") def resize(image: np.ndarray): '''Resizes boid view to fit neural network input size''' r = cfg.dqn_vision()['view_size'] b_size = int(round(image.shape[0] / r)) return block_reduce(image, block_size=(b_size, b_size), func=np.mean) def rgb_to_normalized_gray(rgb): '''Normalizes and maps 3 rgb channels to 1 channel grayscale''' return np.dot(rgb[..., :3] / 255, [0.2989, 0.5870, 0.1140]) screen_width, screen_height = cfg.environment()['dim'] def extract_boid_view(vision_area: np.ndarray, position: np.ndarray) -> torch.Tensor: '''Computes downsampled boid view image state''' vision_poly = boid_vision_poly(vision_area, position) return downsample_image(vision_poly) def boid_vision_poly(vision_area: np.ndarray, position: np.ndarray) -> torch.Tensor: '''Cutting boid reaction area from game screen''' screen = pg.display.get_surface() for point in vision_area:
def random_position(): borders = cfg.borders() tolerance = cfg.environment()['border_tolerance'] return pg.Vector2( scale(np.random.rand(), [0, 1], [tolerance, borders[0] - tolerance]), scale(np.random.rand(), [0, 1], [tolerance, borders[1] - tolerance]))
def random_velocity(magnitude): angle = scale(np.random.rand(), [0, 1], [0, 360]) vec = pg.Vector2() vec.from_polar((magnitude, angle)) return vec def scale(value, old, new): return ((value - old[0]) / (old[1] - old[0])) * (new[1] - new[0]) + new[0] X_AXIS_VEC = pg.Vector2(1, 0) Y_AXIS_VEC = pg.Vector2(0, 1) DEBUG_POSITION_COLOR = pg.Color('green') SCREEN_WIDTH, SCREEN_HEIGHT = cfg.environment()['dim'] class Agent: def __init__(self, sprite: pg.Surface, position: pg.Vector2, velocity: pg.Vector2, reaction_radius: float): self.original_sprite = sprite self.showable_sprite = None self.hitbox = None self.position = position self.velocity = velocity self.acceleration = pg.Vector2(0, 0) self.alive = True self.closest_target = None self.last_observation = None self.current_observation = None
return np.array([[-tolerance, -tolerance + h], [w + tolerance, -tolerance + h], [w + tolerance, tolerance + h], [-tolerance, tolerance + h]]) elif 'left': return np.array([[-tolerance, -tolerance], [tolerance, -tolerance], [tolerance, h + tolerance], [-tolerance, h + tolerance]]) else: raise NotImplemented() BORDERS_NAMES = ['top', 'right', 'bottom', 'left'] TURNING_BORDERS: List[Polygon] = [ Polygon( gen_border(border, tolerance=cfg.environment()['turning_tolerance'])) for border in BORDERS_NAMES ] SCREEN_WIDTH, SCREEN_HEIGHT = cfg.environment()['dim'] class Environment: def __init__(self): self.fishes = [Fish() for _ in range(cfg.fish_amount())] self.all_fishes = self.fishes self.predators = [Predator() for _ in range(cfg.predator_amount())] self.all_predators = self.predators self.fish_qtree = None self.predator_qtree = None self.last_states = { 'all_fishes': self.fishes,