Skip to content

Commit

Permalink
Merge pull request #104 from jbw3/event-handlers
Browse files Browse the repository at this point in the history
Adding event handlers
  • Loading branch information
evanofslack authored Mar 17, 2024
2 parents 0f1fd04 + b515943 commit 8892515
Show file tree
Hide file tree
Showing 27 changed files with 1,921 additions and 319 deletions.
11 changes: 10 additions & 1 deletion pyminion/bots/bot.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from typing import TYPE_CHECKING, Iterator, List, Optional
from typing import TYPE_CHECKING, Iterator, List, Optional, Sequence

from pyminion.core import Card
from pyminion.decider import Decider
from pyminion.player import Player

if TYPE_CHECKING:
from pyminion.effects import Effect
from pyminion.game import Game


Expand Down Expand Up @@ -75,6 +76,14 @@ def buy_phase_decision(

return None

def effects_order_decision(
self,
effects: Sequence["Effect"],
player: "Player",
game: "Game",
) -> int:
return 0

def binary_decision(
self,
prompt: str,
Expand Down
74 changes: 54 additions & 20 deletions pyminion/core.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import random
from collections import Counter
from typing import TYPE_CHECKING, Any, Iterable, Iterator, List, Optional, Tuple
from typing import TYPE_CHECKING, Any, Callable, Iterable, Iterator, List, Optional, Tuple

if TYPE_CHECKING:
from pyminion.game import Game
Expand All @@ -10,8 +10,8 @@
from enum import Enum
from pyminion.exceptions import EmptyPile, InsufficientActions, PileNotFound

logger = logging.getLogger()

logger = logging.getLogger()


class CardType(Enum):
Expand All @@ -26,6 +26,7 @@ class CardType(Enum):
Attack = 5
Reaction = 6


class Card:

"""
Expand All @@ -48,6 +49,9 @@ def get_cost(self, player: "Player", game: "Game") -> int:
def get_pile_starting_count(self, game: "Game") -> int:
return 10

def set_up(self, game: "Game") -> None:
pass


class ScoreCard(Card):
def __init__(self, name: str, cost: int, type: Tuple[CardType, ...]):
Expand Down Expand Up @@ -141,17 +145,23 @@ def __str__(self):


class AbstractDeck:

"""
Base class representing a generic list of dominion cards
"""

def __init__(self, cards: Optional[List[Card]] = None):
def __init__(
self,
cards: Optional[List[Card]] = None,
on_add: Optional[Callable[[Card], None]] = None,
on_remove: Optional[Callable[[Card], None]] = None,
):
if cards:
self.cards = cards
else:
self.cards = []
self.on_add = on_add
self.on_remove = on_remove

def __repr__(self):
return str(DeckCounter(self.cards))
Expand All @@ -161,26 +171,54 @@ def __len__(self):

def add(self, card: Card) -> None:
self.cards.append(card)
if self.on_add is not None:
self.on_add(card)

def remove(self, card: Card) -> Card:
self.cards.remove(card)
if self.on_remove is not None:
self.on_remove(card)
return card

def move_to(self, destination: "AbstractDeck") -> None:
destination.cards += self.cards
self.cards = []
if destination.on_add is None and self.on_remove is None:
destination.cards += self.cards
self.cards = []
else:
cards = self.cards[:] # copy cards that are being moved
destination.cards += self.cards
self.cards = []

if destination.on_add is not None:
for card in cards:
destination.on_add(card)

if self.on_remove is not None:
for card in cards:
self.on_remove(card)


class Deck(AbstractDeck):
def __init__(self, cards: Optional[List[Card]] = None):
super().__init__(cards)
def __init__(
self,
cards: Optional[List[Card]] = None,
on_add: Optional[Callable[[Card], None]] = None,
on_remove: Optional[Callable[[Card], None]] = None,
on_shuffle: Optional[Callable[[], None]] = None,
):
super().__init__(cards, on_add, on_remove)
self.on_shuffle = on_shuffle

def draw(self) -> Card:
drawn_card = self.cards.pop()
if self.on_remove is not None:
self.on_remove(drawn_card)
return drawn_card

def shuffle(self) -> None:
random.shuffle(self.cards)
if self.on_shuffle is not None:
self.on_shuffle()


class DiscardPile(AbstractDeck):
Expand All @@ -189,8 +227,13 @@ def __init__(self, cards: Optional[List[Card]] = None):


class Hand(AbstractDeck):
def __init__(self, cards: Optional[List[Card]] = None):
super().__init__(cards)
def __init__(
self,
cards: Optional[List[Card]] = None,
on_add: Optional[Callable[[Card], None]] = None,
on_remove: Optional[Callable[[Card], None]] = None,
):
super().__init__(cards, on_add, on_remove)


class Pile(AbstractDeck):
Expand All @@ -206,7 +249,7 @@ def __init__(self, cards: Optional[List[Card]] = None):
def remove(self, card: Card) -> Card:
if len(self.cards) < 1:
raise EmptyPile(f"{self.name} pile is empty, cannot gain card")
self.cards.remove(card)
super().remove(card)
return card


Expand Down Expand Up @@ -268,15 +311,6 @@ def return_card(self, card: Card) -> None:
pile = self.get_pile(card.name)
pile.add(card)

def trash_card(self, card: Card, trash: "Trash") -> None:
"""
Trash a card from the supply.
"""
pile = self.get_pile(card.name)
pile.remove(card)
trash.add(card)

def available_cards(self) -> List[Card]:
"""
Returns a list containing a single card from each non-empty pile in the supply.
Expand Down
11 changes: 10 additions & 1 deletion pyminion/decider.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from typing import TYPE_CHECKING, List, Optional, Protocol
from typing import TYPE_CHECKING, List, Optional, Protocol, Sequence

if TYPE_CHECKING:
from pyminion.core import Card, Player
from pyminion.effects import Effect
from pyminion.game import Game


Expand Down Expand Up @@ -35,6 +36,14 @@ def buy_phase_decision(
) -> Optional["Card"]:
raise NotImplementedError("buy_phase_decision is not implemented")

def effects_order_decision(
self,
effects: Sequence["Effect"],
player: "Player",
game: "Game",
) -> int:
raise NotImplementedError("effects_order_decision is not implemented")

def binary_decision(
self,
prompt: str,
Expand Down
Loading

0 comments on commit 8892515

Please sign in to comment.