예제 #1
0
def create_map_with(map_data: List[List[int]]) -> GameMap:
    data_size = len(map_data)
    assert data_size == len(map_data[0])
    game_map = GameMap(data_size + 2)
    for y in range(data_size):
        for x in range(data_size):
            pos = Position(x + 1, y + 1)
            if map_data[y][x] == W:
                game_map.set_tile(pos, GameMap.ASTEROIDS, player_id=None)
            elif map_data[y][x] == E:
                game_map.set_tile(pos, GameMap.EMPTY, player_id=None)
            elif map_data[y][x] == P:
                game_map.set_tile(pos, GameMap.PLANET, player_id=None)
            elif map_data[y][x] == P1:
                game_map.set_tile(pos, GameMap.PLANET, player_id=1)
            else:
                game_map.conquer_tile(pos, player_id=map_data[y][x])
    return game_map
예제 #2
0
    def from_str(cls, data: str) -> "GameConfig":
        lines = data.strip().split("\n")

        map_size = len(lines)
        game_map = GameMap(map_size)

        spawn_positions = []
        spawn_directions = []
        spawn_direction_markers = []

        for y, line in enumerate(lines):
            line = line.strip()
            if len(line) != map_size:
                raise Exception(f"Map is not square! (line {y} as length {len(line)})")

            for x, tile in enumerate(line):
                pos = Position(x, y)
                if tile == GameMap.EMPTY:
                    game_map.set_tile(pos, GameMap.EMPTY, None)
                elif tile == GameMap.ASTEROIDS:
                    game_map.set_tile(pos, GameMap.ASTEROIDS, None)
                elif tile == GameMap.BLACK_HOLE:
                    game_map.set_tile(pos, GameMap.BLACK_HOLE, None)
                elif tile == GameMap.BLITZIUM:
                    game_map.set_tile(pos, GameMap.BLITZIUM, None)
                elif tile == GameMap.PLANET:
                    game_map.set_tile(pos, GameMap.PLANET, None)
                elif tile == GameMap.DIRECTION:
                    # Directions are meta information not visible on the map
                    game_map.set_tile(pos, GameMap.EMPTY, None)
                    spawn_direction_markers.append(pos)
                elif tile.isdigit():
                    player_id = int(tile)
                    spawn_positions.append((player_id, pos))
                else:
                    raise Exception(f"Invalid tile '{tile}' as position {pos}.")

        spawn_positions.sort()

        if len(spawn_direction_markers) > 0:
            # for each player we find the closest direction marker
            # this algorithm won't work if a direction marker is
            # close to 2 spawn_positions
            for player_id, spawn_position in spawn_positions:
                for direction_marker in spawn_direction_markers:
                    if spawn_position.is_next_to(direction_marker):
                        direction = spawn_position.direction_to(direction_marker)
                        spawn_directions.append(direction)

        return GameConfig(game_map, [p for i, p in spawn_positions], spawn_directions)
예제 #3
0
def dict_to_game_map(data: List[List[str]]) -> GameMap:
    map_size = len(data)
    game_map = GameMap(map_size)

    for y in range(1, map_size - 1):
        for x in range(1, map_size - 1):
            splitted = data[y][x].split("-")
            tile = splitted[0]
            owner = None
            if len(splitted) > 1:
                owner = int(splitted[1])

            pos = Position(x, y)
            if tile == " ":
                game_map.set_tile(pos, GameMap.EMPTY, None)
            elif tile == "W":
                game_map.set_tile(pos, GameMap.ASTEROIDS, None)
            elif tile == "!":
                game_map.set_tile(pos, GameMap.BLACK_HOLE, None)
            elif tile == "$":
                game_map.set_tile(pos, GameMap.BLITZIUM, None)
            elif tile == "%":
                game_map.set_tile(pos, GameMap.PLANET, owner)
            elif tile == "C":
                game_map.set_tile(pos, GameMap.EMPTY, owner)

    return game_map
예제 #4
0
class TestMap(unittest.TestCase):
    def setUp(self):
        self.map_size = 10
        self.my_map = GameMap(self.map_size)

    def test_init_with_empty_map(self):
        """
        Test that a new map will be empty and the correct size
        """
        self.assertEqual(self.my_map.size, self.map_size)
        self.assertEqual(len(self.my_map.tiles), self.my_map.size)
        [
            self.assertEqual(len(self.my_map.tiles[y]), self.my_map.size)
            for y in range(self.my_map.size)
        ]

        # there is an asteroids around the map
        self.assertEqual(self.my_map.empty_tiles, (self.map_size - 2)**2)

        for y in range(self.map_size):
            for x in range(self.map_size):
                pos = Position(x=x, y=y)
                self.assertFalse(self.my_map.is_out_of_bound(pos))

                if x == 0 or x == self.map_size - 1 or y == 0 or y == self.map_size - 1:
                    # check asteroids
                    self.assertFalse(self.my_map.is_empty(pos))
                    self.assertEqual(self.my_map.tiles[y][x],
                                     (GameMap.ASTEROIDS, None))
                    self.assertTrue(self.my_map.is_asteroids(pos))
                    self.assertEqual(self.my_map.get_tile(Position(x=x, y=y)),
                                     (GameMap.ASTEROIDS, None))
                else:
                    # must be empty
                    self.assertTrue(self.my_map.is_empty(pos))
                    self.assertFalse(self.my_map.is_asteroids(pos))
                    self.assertEqual(self.my_map.get_tile(Position(x=x, y=y)),
                                     (GameMap.EMPTY, None))

    def test_eq(self):
        self.assertEqual(GameMap(5), GameMap(5))
        self.assertNotEqual(GameMap(5), GameMap(6))

        map_data1 = [[E, W, W], [E, 1, 2], [E, 3, E]]
        map_data2 = [[E, W, W], [E, 2, 3], [E, 1, E]]
        self.assertEqual(create_map_with(map_data1),
                         create_map_with(map_data1))
        self.assertNotEqual(create_map_with(map_data1),
                            create_map_with(map_data2))

    def test_str(self):
        map = create_map_with([
            # fmt: off
            [W, E, E],
            [E, 0, E],
            [E, E, 1]
            # fmt: on
        ])
        map.set_tile(Position(2, 1), state=GameMap.PLANET, player_id=0)
        map.set_tile(Position(3, 1), state=GameMap.BLACK_HOLE)
        self.assertTrue(map.is_black_hole(Position(3, 1)))
        map.set_tile(Position(3, 2), state=GameMap.BLITZIUM)
        self.assertTrue(map.is_blitzium(Position(3, 2)))
        str_map = str(map)
        expected = "\n".join([
            # fmt: off
            'WWWWW',
            'WW%!W',
            'W 0$W',
            'W  1W',
            'WWWWW'
            # fmt: on
        ])
        self.assertEqual(str_map, expected)

    def test_cannot_overwrite_asteroids(self):
        # Ok to write an asteroids on an asteroids
        self.my_map.set_tile(Position(x=0, y=0), state=GameMap.ASTEROIDS)

        # Invalid to overwrite an asteroids with something else
        with self.assertRaises(InvalidStateException):
            self.my_map.set_tile(Position(x=0, y=0),
                                 state=GameMap.EMPTY,
                                 player_id=0)

        with self.assertRaises(InvalidStateException):
            self.my_map.set_tile(Position(x=0, y=0), state=GameMap.EMPTY)

    def test_cannot_overwrite_planet(self):
        # Ok to write a planet on a planet (take ownership)
        pos = Position(x=1, y=1)
        self.my_map.set_tile(pos, state=GameMap.PLANET, player_id=None)
        self.my_map.set_tile(pos, state=GameMap.PLANET, player_id=1)
        self.my_map.set_tile(pos, state=GameMap.PLANET, player_id=2)
        self.my_map.set_tile(pos, state=GameMap.PLANET, player_id=None)
        self.my_map.set_tile(pos, state=GameMap.PLANET, player_id=3)

        # Invalid to overwrite a planet with something else
        with self.assertRaises(InvalidStateException):
            self.my_map.set_tile(pos, state=GameMap.BLACK_HOLE)

        with self.assertRaises(InvalidStateException):
            self.my_map.set_tile(pos, state=GameMap.ASTEROIDS)

        with self.assertRaises(InvalidStateException):
            self.my_map.set_tile(pos, state=GameMap.BLITZIUM)

        with self.assertRaises(InvalidStateException):
            self.my_map.set_tile(pos, state=GameMap.EMPTY)

    def test_invalid_set_title(self):
        pos = Position(x=1, y=1)

        # cannot have player id
        with self.assertRaises(InvalidStateException):
            self.my_map.set_tile(pos, state=GameMap.ASTEROIDS, player_id=1)
        with self.assertRaises(InvalidStateException):
            self.my_map.set_tile(pos, state=GameMap.BLITZIUM, player_id=1)
        with self.assertRaises(InvalidStateException):
            self.my_map.set_tile(pos, state=GameMap.BLACK_HOLE, player_id=1)

    def test_get_set_tile(self):
        """
        Test that you can set a tile and get it back
        """
        position = Position(x=2, y=1)
        old_is_empty = self.my_map.empty_tiles
        self.assertTrue(self.my_map.is_empty(position))
        self.assertEqual(self.my_map.get_tile(position), GameMap.empty_tile)

        # conquer empty tile is the same as setting an owner on it
        self.my_map.set_tile(position, GameMap.EMPTY, 1)
        self.assertFalse(self.my_map.is_empty(position))
        self.assertTrue(self.my_map.is_conquered_by(position, 1))
        self.assertEqual(self.my_map.get_owner(position), 1)
        self.assertEqual(self.my_map.get_tile(position), (GameMap.EMPTY, 1))
        self.assertEqual(self.my_map.empty_tiles, old_is_empty - 1)

        # clear tile remove owner
        self.my_map.clear_tile(position)
        self.assertTrue(self.my_map.is_empty(position))
        self.assertEqual(self.my_map.get_tile(position)[0], GameMap.EMPTY)
        self.assertEqual(self.my_map.empty_tiles, old_is_empty)

        with self.assertRaises(OutOfBoundExeption):
            self.my_map.get_tile(
                Position(self.map_size + 10, self.map_size + 10))

        with self.assertRaises(OutOfBoundExeption):
            self.my_map.set_tile(
                Position(self.map_size + 10, self.map_size + 10),
                GameMap.EMPTY, 1)

    def test_get_owner(self):
        """
        Test that you can get the tile owner
        """
        position = Position(1, 1)
        self.assertTrue(self.my_map.is_empty(position))
        self.assertEqual(self.my_map.get_owner(position), None)

        self.my_map.conquer_tile(position, player_id=1)
        self.assertEqual(self.my_map.get_owner(position), 1)

        self.my_map.conquer_tile(position, player_id=0)
        self.assertEqual(self.my_map.get_owner(position), 0)

        self.my_map.set_tile(position, GameMap.PLANET, player_id=None)
        self.assertEqual(self.my_map.get_owner(position), None)

        self.my_map.conquer_tile(position, player_id=0)
        self.assertEqual(self.my_map.get_owner(position), 0)

        with self.assertRaises(OutOfBoundExeption):
            self.my_map.get_owner(
                Position(self.map_size + 10, self.map_size + 10))

    def test_is_conquered_by(self):
        """
        Test that you can identify tiles owned by you
        """

        position = Position(1, 1)
        self.assertTrue(self.my_map.is_empty(position))
        self.assertFalse(self.my_map.is_conquered_by(position, player_id=1))

        self.my_map.conquer_tile(position, player_id=1)
        self.assertTrue(self.my_map.is_conquered_by(position, player_id=1))
        self.assertFalse(self.my_map.is_conquered_by(position, player_id=0))

        self.my_map.set_tile(position, GameMap.PLANET, player_id=None)
        self.my_map.conquer_tile(position, player_id=1)
        self.assertTrue(self.my_map.is_conquered_by(position, player_id=1))
        self.assertEqual(self.my_map.get_tile(position), (GameMap.PLANET, 1))

        with self.assertRaises(OutOfBoundExeption):
            self.my_map.is_conquered_by(Position(self.map_size + 10,
                                                 self.map_size + 10),
                                        player_id=0)

    def test_is_out_of_bound(self):
        """
        Test that a position is out of bound for the current map
        """

        self.assertTrue(
            self.my_map.is_out_of_bound(Position(-self.map_size, 5)))
        self.assertTrue(self.my_map.is_out_of_bound(Position(self.map_size,
                                                             5)))
        self.assertTrue(
            self.my_map.is_out_of_bound(Position(5, -self.map_size)))
        self.assertTrue(self.my_map.is_out_of_bound(Position(5,
                                                             self.map_size)))
        self.assertTrue(
            self.my_map.is_out_of_bound(Position(self.map_size,
                                                 self.map_size)))
        self.assertTrue(
            self.my_map.is_out_of_bound(
                Position(-self.map_size, -self.map_size)))

        self.assertFalse(self.my_map.is_out_of_bound(Position(0, 0)))
        self.assertFalse(self.my_map.is_out_of_bound(Position(5, 5)))
        self.assertFalse(
            self.my_map.is_out_of_bound(
                Position(self.map_size - 1, self.map_size - 1)))

    def test_clear_tile_owned_by(self):
        """
        Tests that test_clear_tile_owned_by only clear tiles owned by the right player
        """
        self.my_map.set_tile(Position(5, 5), GameMap.PLANET, player_id=None)
        self.my_map.conquer_tile(Position(5, 5), player_id=1)
        self.my_map.conquer_tile(Position(5, 6), player_id=1)
        self.my_map.conquer_tile(Position(5, 7), player_id=1)
        self.my_map.conquer_tile(Position(1, 5), player_id=2)
        self.assertEqual(self.my_map.count_tiles_owned_by(player_id=1), 3)

        self.my_map.clear_tile_owned_by(player_id=1)
        self.assertEqual(self.my_map.count_tiles_owned_by(player_id=1), 0)

        self.assertFalse(self.my_map.is_empty(Position(5, 5)))
        self.assertEqual(self.my_map.get_tile(Position(5, 5)),
                         (GameMap.PLANET, None))
        self.assertTrue(self.my_map.is_empty(Position(7, 5)))

        self.assertEqual(self.my_map.get_tile(Position(1, 5)),
                         (GameMap.EMPTY, 2))
        self.assertEqual(self.my_map.get_owner(Position(1, 5)), 2)

    def test_find_path_empty_tiles(self):
        map = create_map_with([
            # fmt: off
            [1, E, E, E],
            [W, W, E, E],
            [W, E, E, W],
            [2, E, W, E]
            # fmt: on
        ])
        found, path = map.find_path(start=Position(1, 1), goal=Position(4, 1))
        self.assertTrue(found)
        self.assertEqual(len(path), 4)
        self.assertEqual(
            path,
            [Position(1, 1),
             Position(2, 1),
             Position(3, 1),
             Position(4, 1)])

        found, path = map.find_path(start=Position(1, 1), goal=Position(1, 4))
        self.assertTrue(found)
        self.assertEqual(len(path), 8)

        found, path = map.find_path(start=Position(1, 1), goal=Position(4, 4))
        self.assertFalse(found)

    def test_find_path_conquered_tiles(self):
        map = create_map_with([
            # fmt: off
            [1, 1, E, 1],
            [E, 1, E, 2],
            [E, 1, E, 1],
            [E, 1, 1, E]
            # fmt: on
        ])
        found, path = map.find_path(start=Position(1, 1),
                                    goal=Position(3, 4),
                                    player_id=1)
        self.assertTrue(found)
        self.assertEqual(len(path), 6)
        self.assertEqual(path, [
            Position(1, 1),
            Position(2, 1),
            Position(2, 2),
            Position(2, 3),
            Position(2, 4),
            Position(3, 4)
        ])

        found, path = map.find_path(start=Position(1, 1),
                                    goal=Position(4, 1),
                                    player_id=1)
        self.assertFalse(found)

        found, path = map.find_path(start=Position(4, 1),
                                    goal=Position(4, 3),
                                    player_id=1)
        self.assertFalse(found)

        with self.assertRaises(Exception):
            map.find_path(start=Position(4, 1),
                          goal=Position(4, 2),
                          player_id=1)

        with self.assertRaises(Exception):
            map.find_path(start=Position(3, 1),
                          goal=Position(4, 1),
                          player_id=1)

    def test_get_random_empty_position(self):
        positions = set()

        map_size = 10
        game_map = GameMap(map_size)

        for i in range(25):
            pos = game_map.get_random_empty_position()
            self.assertNotIn(pos, positions)
            self.assertTrue(game_map.is_empty(pos))
            game_map.conquer_tile(pos, i)
            positions.add(pos)

    def test_get_empty_tiles(self):
        map = GameMap(4)
        self.assertEqual(
            map.get_empty_tiles(),
            [Position(1, 1),
             Position(1, 2),
             Position(2, 1),
             Position(2, 2)])

        map.set_tile(Position(1, 1), GameMap.PLANET)
        self.assertEqual(
            map.get_empty_tiles(),
            [Position(1, 2), Position(2, 1),
             Position(2, 2)])

        map.set_tile(Position(1, 1), GameMap.PLANET, 1)
        self.assertEqual(
            map.get_empty_tiles(),
            [Position(1, 2), Position(2, 1),
             Position(2, 2)])

        map.set_tile(Position(1, 2), GameMap.ASTEROIDS)
        self.assertEqual(map.get_empty_tiles(),
                         [Position(2, 1), Position(2, 2)])

        map.set_tile(Position(2, 1), GameMap.BLITZIUM)
        self.assertEqual(map.get_empty_tiles(), [Position(2, 2)])

        map.set_tile(Position(2, 1), GameMap.BLACK_HOLE)
        self.assertEqual(map.get_empty_tiles(), [Position(2, 2)])

        map.set_tile(Position(2, 1), GameMap.EMPTY, 1)
        self.assertEqual(map.get_empty_tiles(), [Position(2, 2)])
예제 #5
0
    def test_get_empty_tiles(self):
        map = GameMap(4)
        self.assertEqual(
            map.get_empty_tiles(),
            [Position(1, 1),
             Position(1, 2),
             Position(2, 1),
             Position(2, 2)])

        map.set_tile(Position(1, 1), GameMap.PLANET)
        self.assertEqual(
            map.get_empty_tiles(),
            [Position(1, 2), Position(2, 1),
             Position(2, 2)])

        map.set_tile(Position(1, 1), GameMap.PLANET, 1)
        self.assertEqual(
            map.get_empty_tiles(),
            [Position(1, 2), Position(2, 1),
             Position(2, 2)])

        map.set_tile(Position(1, 2), GameMap.ASTEROIDS)
        self.assertEqual(map.get_empty_tiles(),
                         [Position(2, 1), Position(2, 2)])

        map.set_tile(Position(2, 1), GameMap.BLITZIUM)
        self.assertEqual(map.get_empty_tiles(), [Position(2, 2)])

        map.set_tile(Position(2, 1), GameMap.BLACK_HOLE)
        self.assertEqual(map.get_empty_tiles(), [Position(2, 2)])

        map.set_tile(Position(2, 1), GameMap.EMPTY, 1)
        self.assertEqual(map.get_empty_tiles(), [Position(2, 2)])