def test_foods(self): game_state = create_test_game_state() self.assertEqual(28, len(game_state.game_turns[0].foods)) self.assertEqual(5, len(game_state.game_turns[101].foods)) self.assertEqual( Position(7, 5), game_state.game_turns[0].foods[Position(7, 5)].position)
def test_create_ants_turn0(self): game_state = create_test_game_state() turn0 = game_state.game_turns[0] self.assertEqual(8, len(turn0.ants)) self.assertEqual(Position(1, 19), turn0.ants[Position(1, 19)].position) self.assertEqual('lazarant', turn0.ants[Position(1, 19)].bot.bot_type) self.assertEqual('pkmiec', turn0.ants[Position(41, 19)].bot.bot_type)
def map_hill_turn(row): row_num, col_num, bot_index, capture_turn = row is_alive = turn_number < capture_turn return Position(row_num, col_num), HillTurn(turn_number, bots[bot_index], Position(row_num, col_num), is_alive)
def test_calculate_adjacent_position_south(self): game_map = self.get_test_map() self.assertEqual(TerrainType.LAND, game_map.get_terrain(Position(1, 5))) self.assertEqual( Position(2, 5), game_map.adjacent_movement_position(Position(1, 5), Direction.SOUTH))
def test_hills(self): game_state = create_test_game_state() self.assertEqual(8, len(game_state.game_turns[0].hills)) self.assertEqual( Position(1, 19), game_state.game_turns[0].hills[Position(1, 19)].position) self.assertTrue(game_state.game_turns[151].hills[Position( 1, 19)].is_alive) self.assertFalse(game_state.game_turns[152].hills[Position( 1, 19)].is_alive)
def test_construct_map(self): play_result = get_test_play_result() game_map = create_from_map_data(play_result.replaydata.map) self.assertEqual(39, game_map.column_count) self.assertEqual(43, game_map.row_count) self.assertEqual(TerrainType.WATER, game_map.get_terrain(Position(0, 0))) self.assertEqual(TerrainType.LAND, game_map.get_terrain(Position(1, 5))) self.assertEqual(TerrainType.LAND, game_map.get_terrain(Position(21, 18)))
def decode_ant_vision_2d_examples(encoded_examples: Tuple[ndarray, ndarray]) -> List[AntVision2DExample]: gst = GameStateTranslator() features, labels = encoded_examples feature_example_count = features.shape[0] feature_row_min = 0 - floor(features.shape[1] / 2) feature_row_max = 0 + floor(features.shape[1] / 2) feature_col_min = 0 - floor(features.shape[2] / 2) feature_col_max = 0 + floor(features.shape[2] / 2) row_nums = seq(range(feature_row_min, feature_row_max)).to_list() col_nums = seq(range(feature_col_min, feature_col_max)).to_list() if features.shape[3] != 7: raise ValueError( 'Only implemented for 7 channel encoding since down_sampling eliminates information') items = [] for ex_index in range(feature_example_count): example_features: Dict[Position, PositionState] = {} for row_index, row_num in enumerate(row_nums): for col_index, col_num in enumerate(col_nums): position = Position(row_num, col_num) enum_val = gst.convert_array_to_enum(features[ex_index, row_index, col_index].tolist(), PositionState) example_features[position] = enum_val direction = gst.convert_array_to_enum(labels[ex_index].tolist(), Direction) items.append(AntVision2DExample(example_features, direction)) return items
def test_next_direction(self): game_state = create_test_game_state() self.assertEqual( Direction.WEST, self.get_ant_at_pos(game_state, 0, Position(28, 19)).next_direction) self.assertEqual( Direction.NORTH, self.get_ant_at_pos(game_state, 1, Position(28, 18)).next_direction) self.assertEqual( Direction.NORTH, self.get_ant_at_pos(game_state, 2, Position(27, 18)).next_direction) self.assertEqual( Direction.SOUTH, self.get_ant_at_pos(game_state, 12, Position(19, 24)).next_direction)
def test_create_nn_input(self): game_state = create_test_game_state() test_ant = game_state.game_turns[0].ants.get(Position(1, 19)) ant_vision = game_state.game_map.get_positions_within_distance( test_ant.position, game_state.view_radius_squared) translator = GameStateTranslator() nn_input = translator.convert_to_1d_example(test_ant, game_state) self.assertIsNotNone(nn_input) self.assertEqual((len(ant_vision) - 1), len(nn_input.features))
def encode_map_examples(examples: List[AntMapExample], channel_count: int) -> Tuple[ndarray, ndarray]: gst = GameStateTranslator() if len(examples) == 0: return numpy.empty([0, 43, 39, 7], dtype=int), numpy.empty([0, 5], dtype=int) ex = examples[0] features = numpy.zeros([len(examples), ex.row_count, ex.column_count, channel_count], dtype=int) for e_index, e in enumerate(examples): for r in range(ex.row_count): for c in range(ex.column_count): key = Position(r, c) features[e_index, r, c] = down_sample(gst, e.features[key], channel_count) labels = [gst.convert_enum_to_array(ex.label, Direction) for ex in examples] return numpy.array(features), numpy.array(labels)
def map_ant_turn(row): start_row, start_col, start_turn, _, bot_index, direction_history = row position_at_turn = seq(range(turn_number - start_turn)) \ .map(lambda movement_index: Direction(direction_history[movement_index])) \ .reduce(game_map.adjacent_movement_position, Position(start_row, start_col)) next_direction_code = direction_history[( turn_number - start_turn)] if (turn_number - start_turn) < len(direction_history) else None return position_at_turn, AntTurn(turn_number, bots[bot_index], position_at_turn, row, Direction(next_direction_code))
def generate_game_turn(self, turn_number: int, bots: List[BotName], game_map: GameMap, play_result: PlayResult) -> GameTurn: def map_ant_turn(row): start_row, start_col, start_turn, _, bot_index, direction_history = row position_at_turn = seq(range(turn_number - start_turn)) \ .map(lambda movement_index: Direction(direction_history[movement_index])) \ .reduce(game_map.adjacent_movement_position, Position(start_row, start_col)) next_direction_code = direction_history[( turn_number - start_turn)] if (turn_number - start_turn) < len(direction_history) else None return position_at_turn, AntTurn(turn_number, bots[bot_index], position_at_turn, row, Direction(next_direction_code)) ants = seq(play_result.replaydata.ants) \ .filter(lambda row: (turn_number >= row[2]) and (turn_number < (row[3]))) \ .map(map_ant_turn) \ .to_dict() def map_hill_turn(row): row_num, col_num, bot_index, capture_turn = row is_alive = turn_number < capture_turn return Position(row_num, col_num), HillTurn(turn_number, bots[bot_index], Position(row_num, col_num), is_alive) hills = seq(play_result.replaydata.hills).map(map_hill_turn).to_dict() foods = seq(play_result.replaydata.food) \ .filter(lambda row: (turn_number >= row[2]) and (turn_number < row[3])) \ .map(lambda row: (Position(row[0], row[1]), FoodTurn(turn_number, Position(row[0], row[1])))) \ .to_dict() return GameTurn(turn_number, ants, hills, foods, game_map)
def encode_2d_features(examples: List[Dict[Position, PositionState]], gst: GameStateTranslator, channel_count: int) -> ndarray: if len(examples) == 0: return numpy.empty([0, 12, 12, 7], dtype=int) first_feature = examples[0] rows = seq(first_feature.keys()).group_by(lambda p: p.row).map(lambda t: t[0]).order_by(lambda r: r).to_list() columns = seq(first_feature.keys()).group_by(lambda p: p.column).map(lambda t: t[0]).order_by(lambda c: c).to_list() encoded_features = numpy.zeros([len(examples), len(rows), len(columns), channel_count], dtype=int) for e_index, e in enumerate(examples): for r_index, r in enumerate(rows): for c_index, c in enumerate(columns): key = Position(r, c) if key not in e.keys(): print(key) pprint(e) raise ValueError(f'Invalid Feature {key}') encoded_features[e_index, r_index, c_index] = down_sample(gst, e[key], channel_count) return encoded_features
def decode_map_examples(encoded_examples: Tuple[ndarray, ndarray]) -> List[AntMapExample]: features, labels = encoded_examples items = [] gst = GameStateTranslator() row_count = features.shape[1] col_count = features.shape[2] for ex_index in range(features.shape[0]): example_features: Dict[Position, PositionState] = {} for row_num in range(features.shape[1]): for col_num in range(features.shape[2]): position = Position(row_num, col_num) enum_val = gst.convert_array_to_enum(features[ex_index, row_num, col_num].tolist(), PositionState) example_features[position] = enum_val direction = gst.convert_array_to_enum(labels[ex_index].tolist(), Direction) items.append(AntMapExample(example_features, direction, row_count, col_count)) return items
def test_calculate_vision_square(self): game_map = self.get_test_map() expected = [(-6, -6), (-6, -5), (-6, -4), (-6, -3), (-6, -2), (-6, -1), (-6, 0), (-6, 1), (-6, 2), (-6, 3), (-6, 4), (-6, 5), (-5, -6), (-5, -5), (-5, -4), (-5, -3), (-5, -2), (-5, -1), (-5, 0), (-5, 1), (-5, 2), (-5, 3), (-5, 4), (-5, 5), (-4, -6), (-4, -5), (-4, -4), (-4, -3), (-4, -2), (-4, -1), (-4, 0), (-4, 1), (-4, 2), (-4, 3), (-4, 4), (-4, 5), (-3, -6), (-3, -5), (-3, -4), (-3, -3), (-3, -2), (-3, -1), (-3, 0), (-3, 1), (-3, 2), (-3, 3), (-3, 4), (-3, 5), (-2, -6), (-2, -5), (-2, -4), (-2, -3), (-2, -2), (-2, -1), (-2, 0), (-2, 1), (-2, 2), (-2, 3), (-2, 4), (-2, 5), (-1, -6), (-1, -5), (-1, -4), (-1, -3), (-1, -2), (-1, -1), (-1, 0), (-1, 1), (-1, 2), (-1, 3), (-1, 4), (-1, 5), (0, -6), (0, -5), (0, -4), (0, -3), (0, -2), (0, -1), (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (1, -6), (1, -5), (1, -4), (1, -3), (1, -2), (1, -1), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, -6), (2, -5), (2, -4), (2, -3), (2, -2), (2, -1), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (3, -6), (3, -5), (3, -4), (3, -3), (3, -2), (3, -1), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (4, -6), (4, -5), (4, -4), (4, -3), (4, -2), (4, -1), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (5, -6), (5, -5), (5, -4), (5, -3), (5, -2), (5, -1), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)] within_dist = game_map.get_positions_within_distance( Position(16, 25), 77, use_absolute=False, crop_to_square=True) self.assertIsNotNone(within_dist) self.assertEqual(len(expected), len(within_dist)) seq(expected).for_each(lambda pe: self.assertIsNotNone( seq(within_dist).find(lambda pa: pa.row == pe[0] and pa.column == pe[1]), msg=f'Failed to find expected vision ${pe}'))
def test_calculate_vision(self): game_map = self.get_test_map() expected = [ Position(row=8, column=26), Position(row=8, column=27), Position(row=8, column=28), Position(row=8, column=29), Position(row=8, column=30), Position(row=8, column=31), Position(row=8, column=32), Position(row=9, column=24), Position(row=9, column=25), Position(row=9, column=26), Position(row=9, column=27), Position(row=9, column=28), Position(row=9, column=29), Position(row=9, column=30), Position(row=9, column=31), Position(row=9, column=32), Position(row=9, column=33), Position(row=9, column=34), Position(row=10, column=23), Position(row=10, column=24), Position(row=10, column=25), Position(row=10, column=26), Position(row=10, column=27), Position(row=10, column=28), Position(row=10, column=29), Position(row=10, column=30), Position(row=10, column=31), Position(row=10, column=32), Position(row=10, column=33), Position(row=10, column=34), Position(row=10, column=35), Position(row=11, column=22), Position(row=11, column=23), Position(row=11, column=24), Position(row=11, column=25), Position(row=11, column=26), Position(row=11, column=27), Position(row=11, column=28), Position(row=11, column=29), Position(row=11, column=30), Position(row=11, column=31), Position(row=11, column=32), Position(row=11, column=33), Position(row=11, column=34), Position(row=11, column=35), Position(row=11, column=36), Position(row=12, column=22), Position(row=12, column=23), Position(row=12, column=24), Position(row=12, column=25), Position(row=12, column=26), Position(row=12, column=27), Position(row=12, column=28), Position(row=12, column=29), Position(row=12, column=30), Position(row=12, column=31), Position(row=12, column=32), Position(row=12, column=33), Position(row=12, column=34), Position(row=12, column=35), Position(row=12, column=36), Position(row=13, column=21), Position(row=13, column=22), Position(row=13, column=23), Position(row=13, column=24), Position(row=13, column=25), Position(row=13, column=26), Position(row=13, column=27), Position(row=13, column=28), Position(row=13, column=29), Position(row=13, column=30), Position(row=13, column=31), Position(row=13, column=32), Position(row=13, column=33), Position(row=13, column=34), Position(row=13, column=35), Position(row=13, column=36), Position(row=13, column=37), Position(row=14, column=21), Position(row=14, column=22), Position(row=14, column=23), Position(row=14, column=24), Position(row=14, column=25), Position(row=14, column=26), Position(row=14, column=27), Position(row=14, column=28), Position(row=14, column=29), Position(row=14, column=30), Position(row=14, column=31), Position(row=14, column=32), Position(row=14, column=33), Position(row=14, column=34), Position(row=14, column=35), Position(row=14, column=36), Position(row=14, column=37), Position(row=15, column=21), Position(row=15, column=22), Position(row=15, column=23), Position(row=15, column=24), Position(row=15, column=25), Position(row=15, column=26), Position(row=15, column=27), Position(row=15, column=28), Position(row=15, column=29), Position(row=15, column=30), Position(row=15, column=31), Position(row=15, column=32), Position(row=15, column=33), Position(row=15, column=34), Position(row=15, column=35), Position(row=15, column=36), Position(row=15, column=37), Position(row=16, column=21), Position(row=16, column=22), Position(row=16, column=23), Position(row=16, column=24), Position(row=16, column=25), Position(row=16, column=26), Position(row=16, column=27), Position(row=16, column=28), Position(row=16, column=29), Position(row=16, column=30), Position(row=16, column=31), Position(row=16, column=32), Position(row=16, column=33), Position(row=16, column=34), Position(row=16, column=35), Position(row=16, column=36), Position(row=16, column=37), Position(row=17, column=21), Position(row=17, column=22), Position(row=17, column=23), Position(row=17, column=24), Position(row=17, column=25), Position(row=17, column=26), Position(row=17, column=27), Position(row=17, column=28), Position(row=17, column=29), Position(row=17, column=30), Position(row=17, column=31), Position(row=17, column=32), Position(row=17, column=33), Position(row=17, column=34), Position(row=17, column=35), Position(row=17, column=36), Position(row=17, column=37), Position(row=18, column=21), Position(row=18, column=22), Position(row=18, column=23), Position(row=18, column=24), Position(row=18, column=25), Position(row=18, column=26), Position(row=18, column=27), Position(row=18, column=28), Position(row=18, column=29), Position(row=18, column=30), Position(row=18, column=31), Position(row=18, column=32), Position(row=18, column=33), Position(row=18, column=34), Position(row=18, column=35), Position(row=18, column=36), Position(row=18, column=37), Position(row=19, column=21), Position(row=19, column=22), Position(row=19, column=23), Position(row=19, column=24), Position(row=19, column=25), Position(row=19, column=26), Position(row=19, column=27), Position(row=19, column=28), Position(row=19, column=29), Position(row=19, column=30), Position(row=19, column=31), Position(row=19, column=32), Position(row=19, column=33), Position(row=19, column=34), Position(row=19, column=35), Position(row=19, column=36), Position(row=19, column=37), Position(row=20, column=22), Position(row=20, column=23), Position(row=20, column=24), Position(row=20, column=25), Position(row=20, column=26), Position(row=20, column=27), Position(row=20, column=28), Position(row=20, column=29), Position(row=20, column=30), Position(row=20, column=31), Position(row=20, column=32), Position(row=20, column=33), Position(row=20, column=34), Position(row=20, column=35), Position(row=20, column=36), Position(row=21, column=22), Position(row=21, column=23), Position(row=21, column=24), Position(row=21, column=25), Position(row=21, column=26), Position(row=21, column=27), Position(row=21, column=28), Position(row=21, column=29), Position(row=21, column=30), Position(row=21, column=31), Position(row=21, column=32), Position(row=21, column=33), Position(row=21, column=34), Position(row=21, column=35), Position(row=21, column=36), Position(row=22, column=23), Position(row=22, column=24), Position(row=22, column=25), Position(row=22, column=26), Position(row=22, column=27), Position(row=22, column=28), Position(row=22, column=29), Position(row=22, column=30), Position(row=22, column=31), Position(row=22, column=32), Position(row=22, column=33), Position(row=22, column=34), Position(row=22, column=35), Position(row=23, column=24), Position(row=23, column=25), Position(row=23, column=26), Position(row=23, column=27), Position(row=23, column=28), Position(row=23, column=29), Position(row=23, column=30), Position(row=23, column=31), Position(row=23, column=32), Position(row=23, column=33), Position(row=23, column=34), Position(row=24, column=26), Position(row=24, column=27), Position(row=24, column=28), Position(row=24, column=29), Position(row=24, column=30), Position(row=24, column=31), Position(row=24, column=32) ] within_dist = game_map.get_positions_within_distance( Position(16, 29), 77, True) self.assertIsNotNone(within_dist) self.assertEqual(len(expected), len(within_dist)) for pe in expected: # pylint: disable=cell-var-from-loop self.assertIsNotNone(seq(within_dist).find(lambda pa: pa == pe), msg='Failed to find expected vision ${pe}')
def test_ant_position(self): game_state = create_test_game_state() test_ant: AntTurn = self.get_ant_at_pos(game_state, 59, Position(16, 14)) self.assertIsNotNone(test_ant) self.assertEqual('lazarant', test_ant.bot.bot_type)
def parse_segments(line: str) -> Tuple[str, Position, Optional[int]]: segments = line.split(' ') return segments[0], Position(int(segments[1]), int( segments[2])), int(segments[3]) if len(segments) == 4 else None
def test_calculate_adjacent_position_east(self): game_map = self.get_test_map() self.assertEqual( Position(1, 6), game_map.adjacent_movement_position(Position(1, 5), Direction.EAST))
def test_calculate_adjacent_position_north_wrap(self): game_map = self.get_test_map() self.assertEqual( Position(79, 5), game_map.adjacent_movement_position(Position(0, 5), Direction.NORTH))
def test_calculate_adjacent_position_west_wrap(self): game_map = self.get_test_map() self.assertEqual( Position(1, 79), game_map.adjacent_movement_position(Position(1, 0), Direction.WEST))
def test_create_ants_turn1(self): game_state = create_test_game_state() turn1 = game_state.game_turns[1] self.assertEqual(8, len(turn1.ants)) self.assertIsNotNone( self.get_ant_at_pos(game_state, 1, Position(2, 19)))
def test_create_ants_turn2(self): game_state = create_test_game_state() turn2 = game_state.game_turns[2] self.assertEqual(13, len(turn2.ants)) self.assertEqual(Position(3, 19), turn2.ants[Position(3, 19)].position)