Created
March 15, 2026 15:20
-
-
Save jeanmidevacc/52903213c8d32c499c7c3f1d741ac66e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """Game engine for PyScoundrel.""" | |
| from typing import TYPE_CHECKING, Optional | |
| from ..dungeon import Dungeon | |
| from ..models import Card, CardType, Deck, Player, Room, Weapon | |
| from .actions import ActionResult | |
| from .state import GamePhase, GameState | |
| if TYPE_CHECKING: | |
| pass | |
| class GameEngine: | |
| """ | |
| The game engine handles all game logic and rules enforcement. | |
| This class processes player actions and updates game state accordingly. | |
| """ | |
| def __init__( | |
| self, | |
| state: Optional[GameState] = None, | |
| seed: Optional[int] = None, | |
| dungeon: Optional[Dungeon] = None, | |
| ): | |
| """ | |
| Initialize the game engine. | |
| Args: | |
| state: Optional existing game state to continue from | |
| seed: Optional random seed for deck shuffling | |
| dungeon: Optional dungeon configuration (loads default if not provided) | |
| """ | |
| if state is None: | |
| # Always load dungeon - use default if not specified | |
| if dungeon is None: | |
| dungeon = Dungeon() # Loads default_dungeon.yaml | |
| # Create deck from dungeon | |
| deck = Deck(dungeon, shuffle=True, seed=seed) | |
| player = Player() | |
| state = GameState(player=player, deck=deck) | |
| self.state = state | |
| def start_game(self) -> ActionResult: | |
| """Start a new game.""" | |
| self.state.phase = GamePhase.DRAW_ROOM | |
| return ActionResult(success=True, message="Game started! Draw your first room.") | |
| ## Omitting a lot of dunctions | |
| def face_card(self, card_index: int) -> ActionResult: | |
| """ | |
| Face a card from the current room. | |
| Args: | |
| card_index: Index of card to face (0-3) | |
| Returns: | |
| Result indicating what happened | |
| """ | |
| if self.state.phase not in (GamePhase.DECIDE_AVOID, GamePhase.FACE_CARDS): | |
| return ActionResult(success=False, message="Cannot face card in current phase.") | |
| room = self.state.current_room | |
| if not room: | |
| return ActionResult(success=False, message="No room available!") | |
| # Update phase to facing cards | |
| if self.state.phase == GamePhase.DECIDE_AVOID: | |
| self.state.phase = GamePhase.FACE_CARDS | |
| self.state.rooms_avoided_consecutively = 0 | |
| try: | |
| card = room.face_card(card_index) | |
| except (IndexError, ValueError) as e: | |
| return ActionResult(success=False, message=str(e)) | |
| # Handle the card based on its type | |
| if card.card_type == CardType.WEAPON: | |
| return self._handle_weapon(card) | |
| elif card.card_type == CardType.HEALTH_POTION: | |
| return self._handle_potion(card) | |
| elif card.card_type == CardType.MONSTER: | |
| return self._handle_monster_encounter(card) | |
| return ActionResult(success=False, message="Unknown card type!") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment