diff --git a/dungeonbattle/bootstrap.py b/dungeonbattle/bootstrap.py index 0bc97be..7c65e0e 100644 --- a/dungeonbattle/bootstrap.py +++ b/dungeonbattle/bootstrap.py @@ -4,6 +4,11 @@ from dungeonbattle.term_manager import TermManager class Bootstrap: + """ + The bootstrap object is used to bootstrap the game so that it starts properly. + (It was initially created to avoid circulary imports between the Game and + Display classes) + """ @staticmethod def run_game(): diff --git a/dungeonbattle/enums.py b/dungeonbattle/enums.py index 2a6b993..ed4e211 100644 --- a/dungeonbattle/enums.py +++ b/dungeonbattle/enums.py @@ -3,13 +3,22 @@ from typing import Optional from dungeonbattle.settings import Settings +#This file contains a few useful enumeration classes used elsewhere in the code + class DisplayActions(Enum): + """ + Display actions options for the callable displayaction Game uses + (it just calls the same action on the display object displayaction refers to) + """ REFRESH = auto() UPDATE = auto() class GameMode(Enum): + """ + Game mode options + """ MAINMENU = auto() PLAY = auto() SETTINGS = auto() @@ -17,6 +26,9 @@ class GameMode(Enum): class KeyValues(Enum): + """ + Key values options used in the game + """ UP = auto() DOWN = auto() LEFT = auto() diff --git a/dungeonbattle/game.py b/dungeonbattle/game.py index e050e50..bbf4a8d 100644 --- a/dungeonbattle/game.py +++ b/dungeonbattle/game.py @@ -12,6 +12,9 @@ from typing import Callable class Game: + """ + The game object controls all actions in the game. + """ map: Map player: Player display_actions: Callable[[DisplayActions], None] @@ -42,8 +45,8 @@ class Game: def run(self, screen: Any) -> None: """ Main infinite loop. - We wait for a player action, then we do what that should be done - when the given key got pressed. + We wait for the player's action, then we do what that should be done + when the given key gets pressed. """ while True: # pragma no cover screen.clear() @@ -69,7 +72,7 @@ class Game: def handle_key_pressed_play(self, key: KeyValues) -> None: """ - In play mode, arrows or zqsd should move the main character. + In play mode, arrows or zqsd move the main character. """ if key == KeyValues.UP: if self.player.move_up(): @@ -107,15 +110,16 @@ class Game: elif option == menus.MainMenuValues.EXIT: sys.exit(0) - def game_to_str(self) -> str: - d = dict() - d["Map"] = game.map - d["Player"] = game.player - def save_state(self) -> dict(): + """ + Saves the game to a dictionnary + """ return self.map.save_state() def load_state(self, d: dict) -> None: + """ + Loads the game from a dictionnary + """ self.map.load_state(d) def load_game(self) -> None: @@ -128,7 +132,7 @@ class Game: def save_game(self) -> None: """ - Save the game to a file + Saves the game to a file """ with open("save.json", "w") as f: f.write(json.dumps(self.save_state())) diff --git a/dungeonbattle/interfaces.py b/dungeonbattle/interfaces.py index 7a8ae8b..d234578 100644 --- a/dungeonbattle/interfaces.py +++ b/dungeonbattle/interfaces.py @@ -10,7 +10,7 @@ from dungeonbattle.display.texturepack import TexturePack class Map: """ Object that represents a Map with its width, height - and the whole tiles, with their custom properties. + and tiles, that have their custom properties. """ width: int height: int @@ -120,6 +120,9 @@ class Map: entity.act(self) def save_state(self) -> dict: + """ + Saves the map's attributes to a dictionnary + """ d = dict() d["width"] = self.width d["height"] = self.height @@ -133,6 +136,9 @@ class Map: return d def load_state(self, d: dict) -> None: + """ + Loads the map's attributes from a dictionnary + """ self.width = d["width"] self.height = d["height"] self.start_y = d["start_y"] @@ -143,6 +149,9 @@ class Map: #add entities class Tile(Enum): + """ + The internal representation of the tiles of the map + """ EMPTY = auto() WALL = auto() FLOOR = auto() @@ -158,9 +167,15 @@ class Tile(Enum): raise ValueError(ch) def char(self, pack: TexturePack) -> str: + """ + Translates a Tile to the corresponding character according to the texture pack + """ return getattr(pack, self.name) def is_wall(self) -> bool: + """ + Is this Tile a wall? + """ return self == Tile.WALL def can_walk(self) -> bool: @@ -171,10 +186,13 @@ class Tile(Enum): class Entity: + """ + An Entity object represents any entity present on the map + """ y: int x: int name: str - map: Map + map: Map def __init__(self): self.y = 0 @@ -182,29 +200,47 @@ class Entity: def check_move(self, y: int, x: int, move_if_possible: bool = False)\ -> bool: + """ + Checks if moving to (y,x) is authorized + """ free = self.map.is_free(y, x) if free and move_if_possible: self.move(y, x) return free def move(self, y: int, x: int) -> bool: + """ + Moves an entity to (y,x) coordinates + """ self.y = y self.x = x return True def move_up(self, force: bool = False) -> bool: + """ + Moves the entity up one tile, if possible + """ return self.move(self.y - 1, self.x) if force else \ self.check_move(self.y - 1, self.x, True) def move_down(self, force: bool = False) -> bool: + """ + Moves the entity down one tile, if possible + """ return self.move(self.y + 1, self.x) if force else \ self.check_move(self.y + 1, self.x, True) def move_left(self, force: bool = False) -> bool: + """ + Moves the entity left one tile, if possible + """ return self.move(self.y, self.x - 1) if force else \ self.check_move(self.y, self.x - 1, True) def move_right(self, force: bool = False) -> bool: + """ + Moves the entity right one tile, if possible + """ return self.move(self.y, self.x + 1) if force else \ self.check_move(self.y, self.x + 1, True) @@ -229,14 +265,23 @@ class Entity: return sqrt(self.distance_squared(other)) def is_fighting_entity(self) -> bool: + """ + Is this entity a fighting entity? + """ return isinstance(self, FightingEntity) def is_item(self) -> bool: + """ + Is this entity an item? + """ from dungeonbattle.entities.items import Item return isinstance(self, Item) @staticmethod def get_all_entity_classes(): + """ + Returns all entities subclasses + """ from dungeonbattle.entities.items import Heart, Bomb from dungeonbattle.entities.monsters import Beaver, Hedgehog, \ Rabbit, TeddyBear @@ -260,6 +305,10 @@ class Entity: class FightingEntity(Entity): + """ + A FightingEntity is an entity that can fight, and thus has a health, + level and stats + """ maxhealth: int health: int strength: int @@ -285,27 +334,45 @@ class FightingEntity(Entity): def hit(self, opponent: "FightingEntity") -> None: + """ + Deals damage to the opponent, based on the stats + """ opponent.take_damage(self, self.strength) def take_damage(self, attacker: "Entity", amount: int) -> None: + """ + Take damage from the attacker, based on the stats + """ self.health -= amount if self.health <= 0: self.die() def die(self) -> None: + """ + If a fighting entity has no more health, it dies and is removed + """ self.dead = True self.map.remove_entity(self) def keys(self) -> list: + """ + Returns a fighting entities specific attributes + """ return ["maxhealth", "health", "level", "dead", "strength", "intelligence", "charisma", "dexterity", "constitution"] def save_state(self) -> dict: + """ + Saves the state of the entity into a dictionnary + """ d = super().save_state() for name in self.keys(): d[name] = self.__getattribute__(name) return d def recover_state(self, d : dict) -> None: + """ + Loads the state of an entity from a dictionnary + """ super().recover_state(d) for name in d.keys(): self.__setattribute__(name, d[name]) diff --git a/dungeonbattle/menus.py b/dungeonbattle/menus.py index e543731..59b364f 100644 --- a/dungeonbattle/menus.py +++ b/dungeonbattle/menus.py @@ -8,22 +8,37 @@ from .settings import Settings class Menu: + """ + A Menu object is the logical representation of a menu in the game + """ values: list def __init__(self): self.position = 0 def go_up(self) -> None: + """ + Moves the pointer of the menu on the previous value + """ self.position = max(0, self.position - 1) def go_down(self) -> None: + """ + Moves the pointer of the menu on the next value + """ self.position = min(len(self.values) - 1, self.position + 1) def validate(self) -> Any: + """ + Selects the value that is pointed by the menu pointer + """ return self.values[self.position] class MainMenuValues(Enum): + """ + Values of the main menu + """ START = 'Jouer' SAVE = 'Sauvegarder' LOAD = 'Charger' @@ -35,13 +50,22 @@ class MainMenuValues(Enum): class MainMenu(Menu): + """ + A special instance of a menu : the main menu + """ values = [e for e in MainMenuValues] class SettingsMenu(Menu): + """ + A special instance of a menu : the settings menu + """ waiting_for_key: bool = False def update_values(self, settings: Settings) -> None: + """ + The settings can change, so they are updated + """ self.values = [] for i, key in enumerate(settings.settings_keys): s = settings.get_comment(key) @@ -61,7 +85,7 @@ class SettingsMenu(Menu): def handle_key_pressed(self, key: Optional[KeyValues], raw_key: str, game: Any) -> None: """ - Update settings + In the setting menu, we van select a setting and change it """ if not self.waiting_for_key: # Navigate normally through the menu.