def _next_spaces(self, current, used): current_neighbors = self.game.neighbor_pieces(current) for index_direction, (dx, dy) in enumerate(HiveGame.NEIGHBORS_DIRECTION): new_x, new_y = target_position(current, (dx, dy)) if self.game.get_top_piece((new_x, new_y)) is not None: continue neighbor_pieces = { x for x in self.game.neighbor_pieces((new_x, new_y)) if x != self.moving_piece } if len(neighbor_pieces) == 0 or len( current_neighbors.intersection(neighbor_pieces)) == 0: continue if (new_x, new_y) in used: continue prev_direction = HiveGame.NEIGHBORS_DIRECTION[ (index_direction - 1) % len(HiveGame.NEIGHBORS_DIRECTION)] next_direction = HiveGame.NEIGHBORS_DIRECTION[ (index_direction + 1) % len(HiveGame.NEIGHBORS_DIRECTION)] if (self.game.get_top_piece( target_position(current, prev_direction)) is not None and self.game.get_top_piece( target_position(current, next_direction)) is not None): continue yield new_x, new_y
def set_top_piece(self, position, piece): old_piece = self.get_top_piece(position) self._pieces[position].append(piece) self._top_pieces[position] = piece for relative_position in HiveGame.NEIGHBORS_DIRECTION: new_position = target_position(position, relative_position) self._neighbors[new_position].add(piece) if old_piece is not None: self._neighbors[new_position].remove(old_piece)
def _is_available(self, common_data=None): if not super()._is_available(common_data): return False # Can't go on top like beetle new_position = target_position(self.moving_piece.position, self.relative_direction) if self.game.get_top_piece(new_position) is not None: return False return True
def _simulate_jump(self): jumped_over = [] current_position = self.moving_piece.position while True: current_position = target_position(current_position, self.relative_direction) jumped_over_piece = self.game.get_top_piece(current_position) if jumped_over_piece is None: break jumped_over.append(jumped_over_piece) return current_position, jumped_over
def drop_top_piece(self, position): old_piece = self.get_top_piece(position) self._pieces[position] = self._pieces[position][:-1] piece = self._pieces[position][-1] if len( self._pieces[position]) > 0 else None self._top_pieces[position] = piece for relative_position in HiveGame.NEIGHBORS_DIRECTION: new_position = target_position(position, relative_position) if piece is not None: self._neighbors[new_position].add(piece) self._neighbors[new_position].remove(old_piece)
def set_random_state(self, seed=None): np.random.seed(seed) self.reset() units_to_deploy = np.random.normal(HiveGame.TOTAL_PIECES_COUNT // 2, HiveGame.TOTAL_PIECES_COUNT // 4) units_to_deploy = int( np.clip(units_to_deploy, 0, HiveGame.TOTAL_PIECES_COUNT)) not_deployed_units = [] free_positions = {(0, 0)} occupied_positions = set() other_color = self.to_play for color in range(2): for piece_type, count in GamePieceType.PIECE_COUNT.items(): not_deployed_units.extend([(color, piece_type)] * count) for _ in range(units_to_deploy): forced_queen0 = (len(self._pieces_by_id[0].values()) == 3 and self.get_piece(0, 0) is None) forced_queen1 = (len(self._pieces_by_id[1].values()) == 3 and self.get_piece(1, 0) is None) forced_queens = [forced_queen0, forced_queen1] to_deploy = [ x for x in not_deployed_units if not forced_queens[x[0]] or x[1] == GamePieceType.QUEEN_BEE ] if self.get_piece(other_color, 0) is None: to_deploy = [x for x in to_deploy if x[0] == other_color] color, piece_type = to_deploy[np.random.randint(0, len(to_deploy))] not_deployed_units.remove((color, piece_type)) if len(occupied_positions) == 0: position = (0, 0) elif len(occupied_positions) == 1: position = (1, 0) else: to_deploy_positions = free_positions.copy() if piece_type == GamePieceType.BEETLE and self.get_piece( color, 0) is not None: to_deploy_positions.update(occupied_positions) position = list(to_deploy_positions)[np.random.randint( 0, len(to_deploy_positions))] self.deploy_piece(position, piece_type, force_color=color) occupied_positions.add(position) if position in free_positions: free_positions.remove(position) for relative_position in HiveGame.NEIGHBORS_DIRECTION: new_position = target_position(position, relative_position) if new_position not in occupied_positions: free_positions.add(new_position) last_color = color other_color = (last_color + 1) % 2 self.to_play = other_color if self.get_winner() is not None: self.set_random_state(seed + 1 if seed is not None else None)
def _is_available(self, common_data=None): if not super()._is_available(common_data): return False new_position = target_position(self.moving_piece.position, self.relative_direction) target_neighbor_pieces = { x for x in self.game.neighbor_pieces(new_position) if x != self.moving_piece } neighbor_pieces = { x for x in self.game.neighbor_pieces(self.moving_piece.position) } # No running away from hive and slide on pieces if len(target_neighbor_pieces) == 0 or len( neighbor_pieces.intersection(target_neighbor_pieces)) == 0: return False # Freedom to move rule for beetles beetle_stack_size = len(self.game.get_stack( self.moving_piece.position)) - 1 target_stack_size = len(self.game.get_stack(new_position)) index_direction = HiveGame.NEIGHBORS_DIRECTION.index( self.relative_direction) prev_direction = HiveGame.NEIGHBORS_DIRECTION[ (index_direction - 1) % len(HiveGame.NEIGHBORS_DIRECTION)] next_direction = HiveGame.NEIGHBORS_DIRECTION[ (index_direction + 1) % len(HiveGame.NEIGHBORS_DIRECTION)] gate1_size = len( self.game.get_stack( target_position(self.moving_piece.position, prev_direction))) gate2_size = len( self.game.get_stack( target_position(self.moving_piece.position, next_direction))) if (beetle_stack_size < gate1_size and beetle_stack_size < gate2_size and target_stack_size < gate1_size and target_stack_size < gate2_size): return False return True
def _get_real_position(self): neighbor = self.game.get_piece(self.game.to_play, self.next_to_id) return target_position(neighbor.position, self.relative_direction)
def end_position(self): return target_position(self.end_neighbor().position, self.relative_direction)
def end_position(self): return target_position(self.moving_piece.position, self.relative_direction)