Skip to content

Instantly share code, notes, and snippets.

@jeanmidevacc
Created March 15, 2026 15:20
Show Gist options
  • Select an option

  • Save jeanmidevacc/52903213c8d32c499c7c3f1d741ac66e to your computer and use it in GitHub Desktop.

Select an option

Save jeanmidevacc/52903213c8d32c499c7c3f1d741ac66e to your computer and use it in GitHub Desktop.
"""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