Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Game generation tweak #89

Merged
merged 7 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 53 additions & 15 deletions game/common/map/game_board.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import random
from typing import Self
from typing import Self, Callable

from game.common.avatar import Avatar
from game.common.enums import *
Expand Down Expand Up @@ -175,11 +175,11 @@ def locations(self, locations: dict[tuple[Vector]:list[GameObject]] | None) -> N
if locations is not None and not isinstance(locations, dict):
raise ValueError("Locations must be a dict. The key must be a tuple of Vector Objects, and the "
"value a list of GameObject.")
if locations is not None:
for k, v in locations.items():
if len(k) != len(v):
raise ValueError("Cannot set the locations for the game_board. A key has a different "
"length than its key.")
# if locations is not None:
# for k, v in locations.items():
# if len(k) != len(v):
# raise ValueError("Cannot set the locations for the game_board. A key has a different "
# "length than its key.")

self.__locations = locations

Expand Down Expand Up @@ -212,28 +212,66 @@ def generate_map(self) -> None:

def __populate_map(self) -> None:
for k, v in self.locations.items():
if len(k) != len(v) or (len(k) == 0 or len(v) == 0): # Key-Value lengths must be > 0 and equal
raise ValueError("A key-value pair from game_board.locations has mismatching lengths. "
"They must be the same length, regardless of size.")
if len(k) == 0 or len(v) == 0: # Key-Value lengths must be > 0 and equal
raise ValueError("A key-value pair from game_board.locations has a length of 0. ")

# random.sample returns a randomized list which is used in __help_populate()
j = random.sample(k, k=len(k))
self.__help_populate(j, v)

def __help_populate(self, vector_list: list[Vector], v: list[GameObject]) -> None:
for j, i in zip(vector_list, v):
if isinstance(i, Avatar): # If the GameObject is an Avatar, assign it the coordinate position
i.position = j
def __occupied_filter(self, game_object_list: list[GameObject]) -> list[GameObject]:
"""
A helper method that returns a list of game objects that have the 'occupied_by' attribute.
:param game_object_list:
:return: a list of game object
"""
return [game_object for game_object in game_object_list if hasattr(game_object, 'occupied_by')]

temp_tile: GameObject = self.game_map[j.y][j.x]
def __help_populate(self, vector_list: list[Vector], game_object_list: list[GameObject]) -> None:
"""
A helper method that helps populate the game map.
:param vector_list:
:param game_object_list:
:return: None
"""

zipped_list: [tuple[list[Vector], list[GameObject]]] = list(zip(vector_list, game_object_list))
last_vec: Vector = zipped_list[-1][0]

remaining_objects: list[GameObject] | None = self.__occupied_filter(game_object_list[len(zipped_list):]) \
if len(self.__occupied_filter(game_object_list)) > len(zipped_list) \
else None

# Will cap at smallest list when zipping two together
for vector, game_object in zipped_list:
if isinstance(game_object, Avatar): # If the GameObject is an Avatar, assign it the coordinate position
game_object.position = vector

temp_tile: GameObject = self.game_map[vector.y][vector.x]

while hasattr(temp_tile.occupied_by, 'occupied_by'):
temp_tile = temp_tile.occupied_by

if temp_tile is None:
raise ValueError("Last item on the given tile doesn't have the 'occupied_by' attribute.")

temp_tile.occupied_by = i
temp_tile.occupied_by = game_object

if remaining_objects is None:
return

# stack remaining game_objects on last vector
temp_tile: GameObject = self.game_map[last_vec.y][last_vec.x]

while hasattr(temp_tile.occupied_by, 'occupied_by'):
temp_tile = temp_tile.occupied_by

for game_object in remaining_objects:
if temp_tile is None:
raise ValueError("Last item on the given tile doesn't have the 'occupied_by' attribute.")

temp_tile.occupied_by = game_object
temp_tile = temp_tile.occupied_by

def get_objects(self, look_for: ObjectType) -> list[tuple[Vector, list[GameObject]]]:
to_return: list[tuple[Vector, list[GameObject]]] = list()
Expand Down
15 changes: 13 additions & 2 deletions game/test_suite/tests/test_game_board.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def setUp(self) -> None:
self.locations: dict[tuple[Vector]:list[GameObject]] = {
(Vector(1, 1),): [Station(None)],
(Vector(1, 2), Vector(1, 3)): [OccupiableStation(self.item), Station(None)],
(Vector(2, 2), Vector(2, 3)): [OccupiableStation(self.item), OccupiableStation(self.item), OccupiableStation(self.item), OccupiableStation(self.item)],
(Vector(3, 1), Vector(3, 2), Vector(3, 3)): [OccupiableStation(self.item), Station(None)],
(Vector(5, 5),): [self.avatar],
(Vector(5, 6),): [self.wall]
}
Expand Down Expand Up @@ -69,14 +71,23 @@ def test_walled_fail(self):
def test_get_objects_station(self):
stations: list[tuple[Vector, list[Station]]] = self.game_board.get_objects(ObjectType.STATION)
self.assertTrue(all(map(lambda station: isinstance(station[1][0], Station), stations)))
self.assertEqual(len(stations), 2)
self.assertEqual(len(stations), 3)

# test that get_objects works correctly with occupiable stations
def test_get_objects_occupiable_station(self):
occupiable_stations: list[tuple[Vector, list[OccupiableStation]]] = self.game_board.get_objects(ObjectType.OCCUPIABLE_STATION)
self.assertTrue(
all(map(lambda occupiable_station: isinstance(occupiable_station[1][0], OccupiableStation), occupiable_stations)))
self.assertEqual(len(occupiable_stations), 1)
objects_stacked = [x[1] for x in occupiable_stations]
objects_unstacked = [x for xs in objects_stacked for x in xs]
self.assertEqual(len(objects_unstacked), 6)

def test_get_objects_occupiable_station_2(self):
occupiable_stations: list[tuple[Vector, list[OccupiableStation]]] = self.game_board.get_objects(ObjectType.OCCUPIABLE_STATION)
self.assertTrue(any(map(lambda vec_list: len(vec_list[1]) == 3, occupiable_stations)))
objects_stacked = [x[1] for x in occupiable_stations]
objects_unstacked = [x for xs in objects_stacked for x in xs]
self.assertEqual(len(objects_unstacked), 6)

# test that get_objects works correctly with avatar
def test_get_objects_avatar(self):
Expand Down
12 changes: 0 additions & 12 deletions game/test_suite/tests/test_game_board_no_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,6 @@ def test_locations_fail_type(self):
self.assertEqual(str(e.exception), 'Locations must be a dict. The key must be a tuple of Vector Objects, '
'and the value a list of GameObject.')

def test_locations_fail_len(self):
with self.assertRaises(ValueError) as e:
self.locations = {
(Vector(1, 1),): [],
(Vector(1, 2), Vector(1, 3)): [OccupiableStation(self.item), Station(None)],
(Vector(5, 5),): [Station(None)],
(Vector(5, 6),): [self.wall]
}
self.game_board.locations = self.locations
self.assertEqual(str(e.exception), 'Cannot set the locations for the game_board. A key has a different length '
'than its key.')

# test walled
def test_walled(self):
self.game_board.walled = True
Expand Down