Skip to content

Commit

Permalink
Randobot fixes and typing
Browse files Browse the repository at this point in the history
  • Loading branch information
dwagon committed Nov 2, 2023
1 parent 715413d commit 2aa408e
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 79 deletions.
2 changes: 1 addition & 1 deletion dominion/Card.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def __init__(self) -> None:
self.potion = 0
self.cards = 0
self.victory = 0
self.required_cards: list[str] = []
self.required_cards: list[str | tuple[str, str]] = []
self.image = None
self.numcards = 10
self.retain_boon = False
Expand Down
9 changes: 5 additions & 4 deletions dominion/Player.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,10 +552,10 @@ def _spendable_selection(self) -> list[Option]:
options = []
spendable = [_ for _ in self.piles[Piles.HAND] if _.isTreasure()]
spendable.sort(key=lambda x: x.name)
totcoin = sum(self.hook_spend_value(_) for _ in spendable)
total_coin = sum(self.hook_spend_value(_) for _ in spendable)
numpots = sum(1 for _ in spendable if _.name == "Potion")
potstr = f", {numpots} potions" if numpots else ""
details = f"{totcoin} coin{potstr}"
details = f"{total_coin} coin{potstr}"
if spendable:
o = Option(
selector="1",
Expand Down Expand Up @@ -1427,7 +1427,8 @@ def gain_card(
# trash: True - trash the new card
# shuffle: True - shuffle the deck after gaining new card
options: dict[str, Any] = {}
if not new_card:
if new_card is None:
assert card_name is not None
if card_name == "Loot":
pile = "Loot"
else:
Expand All @@ -1436,7 +1437,7 @@ def gain_card(
pile = card_name
new_card = self.game.get_card_from_pile(pile)

if not new_card:
if new_card is None:
self.output(f"No more {card_name}")
return None
self.output(f"Gained a {new_card}")
Expand Down
35 changes: 19 additions & 16 deletions dominion/cards/Card_Cultist.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#!/usr/bin/env python

import unittest
from dominion import Game, Card, Piles
from typing import Any

from dominion import Game, Card, Piles, Player


###############################################################################
class Card_Cultist(Card.Card):
def __init__(self):
def __init__(self) -> None:
Card.Card.__init__(self)
self.cardtype = [
Card.CardType.ACTION,
Expand All @@ -20,44 +22,45 @@ def __init__(self):
self.cost = 5
self.cards = 2

def special(self, game, player):
def special(self, game: Game.Game, player: Player.Player) -> None:
"""Each other play gains a Ruins. You may play a Cultist
from your hand."""
for plr in player.attack_victims():
plr.output(f"Gained a ruin from {player.name}'s Cultist")
plr.gain_card("Ruins")
cultist = player.piles[Piles.HAND]["Cultist"]
if cultist:
ans = player.plr_choose_options(
if cultist := player.piles[Piles.HAND]["Cultist"]:
if player.plr_choose_options(
"Play another cultist?",
("Don't play cultist", False),
("Play another cultist", True),
)
if ans:
):
player.play_card(cultist, cost_action=False)

def hook_trash_this_card(self, game, player):
def hook_trash_this_card(
self, game: Game.Game, player: Player.Player
) -> dict[str, Any]:
"""When you trash this, +3 cards"""
player.pickup_cards(3)
return {}


###############################################################################
class TestCultist(unittest.TestCase):
def setUp(self):
def setUp(self) -> None:
self.g = Game.TestGame(numplayers=2, initcards=["Cultist", "Moat"])
self.g.start_game()
self.plr, self.victim = self.g.player_list()
self.card = self.g.get_card_from_pile("Cultist")

def test_play(self):
def test_play(self) -> None:
"""Play a cultists - should give 2 cards"""
self.plr.add_card(self.card, Piles.HAND)
self.plr.play_card(self.card)
self.assertEqual(self.plr.piles[Piles.HAND].size(), 7)
self.assertEqual(self.victim.piles[Piles.DISCARD].size(), 1)
self.assertTrue(self.victim.piles[Piles.DISCARD][0].isRuin())

def test_defense(self):
def test_defense(self) -> None:
"""Make sure moats work against cultists"""
self.plr.add_card(self.card, Piles.HAND)
moat = self.g.get_card_from_pile("Moat")
Expand All @@ -66,23 +69,23 @@ def test_defense(self):
self.assertEqual(self.plr.piles[Piles.HAND].size(), 7)
self.assertTrue(self.victim.piles[Piles.DISCARD].is_empty())

def test_no_other(self):
def test_no_other(self) -> None:
"""Don't ask to play another cultist if it doesn't exist"""
self.plr.piles[Piles.HAND].set("Estate", "Estate", "Estate")
self.plr.add_card(self.card, Piles.HAND)
self.plr.test_input = ["0"]
self.plr.play_card(self.card)
self.assertEqual(self.plr.test_input, ["0"])

def test_another_cultist_no(self):
def test_another_cultist_no(self) -> None:
"""Don't play the other cultist"""
self.plr.piles[Piles.HAND].set("Cultist", "Estate", "Estate")
self.plr.add_card(self.card, Piles.HAND)
self.plr.test_input = ["0"]
self.plr.play_card(self.card)
self.assertEqual(self.plr.piles[Piles.PLAYED].size(), 1)

def test_another_cultist_yes(self):
def test_another_cultist_yes(self) -> None:
"""Another cultist can be played for free"""
self.plr.piles[Piles.HAND].set("Cultist", "Estate", "Estate")
self.plr.add_card(self.card, Piles.HAND)
Expand All @@ -96,7 +99,7 @@ def test_another_cultist_yes(self):
for c in self.victim.piles[Piles.DISCARD]:
self.assertTrue(c.isRuin())

def test_trash(self):
def test_trash(self) -> None:
"""Trashing a cultist should give 3 more cards"""
self.plr.add_card(self.card, Piles.HAND)
self.plr.trash_card(self.card)
Expand Down
1 change: 1 addition & 0 deletions dominion/cards/Card_Giant.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def giant_attack(victim: "Player.Player", player: "Player.Player") -> None:
player.output(f"Trashed {victim.name}'s {card}")
else:
victim.output(f"{player.name}'s Giant discarded your {card} and cursed you")
victim.move_card(card, Piles.HAND)
victim.discard_card(card)
victim.gain_card("Curse")

Expand Down
18 changes: 10 additions & 8 deletions dominion/cards/Card_Guard_Dog.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
""" http://wiki.dominionstrategy.com/index.php/Guard_Dog """

import unittest
from dominion import Card, Game, Piles
from dominion import Card, Game, Piles, Player


###############################################################################
class Card_Guard_Dog(Card.Card):
"""Guard Dog"""

def __init__(self):
def __init__(self) -> None:
Card.Card.__init__(self)
self.cardtype = [Card.CardType.ACTION, Card.CardType.REACTION]
self.base = Card.CardExpansion.HINTERLANDS
Expand All @@ -18,12 +18,14 @@ def __init__(self):
self.name = "Guard Dog"
self.cost = 3

def special(self, game, player):
def special(self, game: Game.Game, player: Player.Player) -> None:
player.pickup_cards(2)
if player.piles[Piles.HAND].size() <= 5:
player.pickup_cards(2)

def hook_under_attack(self, game, player, attacker):
def hook_under_attack(
self, game: Game.Game, player: Player.Player, attacker: Player.Player
) -> None:
player.output(f"Playing Guard Dog as under attack by {attacker.name}")
player.play_card(self, cost_action=False)

Expand All @@ -32,27 +34,27 @@ def hook_under_attack(self, game, player, attacker):
class TestGuardDog(unittest.TestCase):
"""Test Guard Dog"""

def setUp(self):
def setUp(self) -> None:
self.g = Game.TestGame(numplayers=2, initcards=["Guard Dog", "Witch"])
self.g.start_game()
self.plr, self.att = self.g.player_list()
self.card = self.g.get_card_from_pile("Guard Dog")

def test_play_small_hand(self):
def test_play_small_hand(self) -> None:
"""Play a card - gain twice"""
self.plr.piles[Piles.HAND].set("Copper")
self.plr.add_card(self.card, Piles.HAND)
self.plr.play_card(self.card)
self.assertEqual(self.plr.piles[Piles.HAND].size(), 5)

def test_play_big_hand(self):
def test_play_big_hand(self) -> None:
"""Play a card - gain once"""
self.plr.piles[Piles.HAND].set("Copper", "Silver", "Gold", "Duchy")
self.plr.add_card(self.card, Piles.HAND)
self.plr.play_card(self.card)
self.assertEqual(self.plr.piles[Piles.HAND].size(), 6)

def test_attack(self):
def test_attack(self) -> None:
"""Test under attack"""
self.plr.piles[Piles.HAND].set("Copper", "Guard Dog")
witch = self.g.get_card_from_pile("Witch")
Expand Down
45 changes: 29 additions & 16 deletions dominion/cards/Card_Necromancer.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#!/usr/bin/env python
""" https://wiki.dominionstrategy.com/index.php/Necromancer"""

import unittest
from dominion import Card
from dominion import PlayArea
from dominion import Game, Piles
from dominion import Card, PlayArea, Game, Piles, Player

NECROMANCER = "necromancer"


###############################################################################
class Card_Necromancer(Card.Card):
def __init__(self):
def __init__(self) -> None:
Card.Card.__init__(self)
self.cardtype = [Card.CardType.ACTION]
self.base = Card.CardExpansion.NOCTURNE
Expand All @@ -21,29 +22,41 @@ def __init__(self):
("Card", "Zombie Spy"),
]

def special(self, game, player):
act = [_ for _ in game.trash_pile if _.isAction() and not _.isDuration() and _ not in game._necromancer]
card = player.card_sel(cardsrc=act, prompt="Select Action card from Trash")
game._necromancer.add(card[0])
player.play_card(card[0], discard=False, cost_action=False)
def special(self, game: Game.Game, player: Player.Player) -> None:
"""Play a non-Duration Action card from the trash, leaving it there."""
action_cards = [
_
for _ in game.trash_pile
if _.isAction()
and not _.isDuration()
and _ not in game.specials[NECROMANCER]
]
if card := player.card_sel(
cardsrc=action_cards, prompt="Select Action card from Trash"
):
assert card[0] is not None
game.specials[NECROMANCER].add(card[0])
player.play_card(card[0], discard=False, cost_action=False)

def setup(self, game):
game._necromancer = PlayArea.PlayArea()
def setup(self, game: Game.Game) -> None:
"""Use a play area to keep track of what has been played by Necromancer this turn"""
game.specials[NECROMANCER] = PlayArea.PlayArea()

def hook_cleanup(self, game, player):
game._necromancer = PlayArea.PlayArea()
def hook_cleanup(self, game: Game.Game, player: Player.Player) -> None:
"""Reset what has been played by Necromancer"""
game.specials[NECROMANCER].empty()


###############################################################################
class Test_Necromancer(unittest.TestCase):
def setUp(self):
class TestNecromancer(unittest.TestCase):
def setUp(self) -> None:
self.g = Game.TestGame(numplayers=1, initcards=["Necromancer", "Moat"])
self.g.start_game()
self.plr = self.g.player_list()[0]
self.card = self.g.get_card_from_pile("Necromancer")
self.plr.add_card(self.card, Piles.HAND)

def test_play(self):
def test_play(self) -> None:
"""Play a Necromancer"""
self.plr.piles[Piles.DECK].set("Gold", "Silver")
self.plr.test_input = ["Zombie Spy", "Keep"]
Expand Down
2 changes: 1 addition & 1 deletion dominion/cards/Card_Scryingpool.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def special(self, game: "Game.Game", player: "Player.Player") -> None:
if not top_card.isAction():
break
for card in revealed:
player.add_card(card, Piles.HAND)
player.move_card(card, Piles.HAND)


###############################################################################
Expand Down
26 changes: 16 additions & 10 deletions dominion/cards/Card_Tiara.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#!/usr/bin/env python
"""https://wiki.dominionstrategy.com/index.php/Tiara """
import unittest
from dominion import Game, Card, Piles
from typing import Any

from dominion import Game, Card, Piles, Player


###############################################################################
class Card_Tiara(Card.Card):
"""Tiara"""

def __init__(self):
def __init__(self) -> None:
Card.Card.__init__(self)
self.cardtype = Card.CardType.TREASURE
self.base = Card.CardExpansion.PROSPERITY
Expand All @@ -18,38 +20,42 @@ def __init__(self):
self.cost = 4
self.buys = 1

def special(self, game, player):
def special(self, game: Game.Game, player: Player.Player) -> None:
"""Play a treasure from your hand twice"""
treasures = [_ for _ in player.piles[Piles.HAND] if _.isTreasure()]
if not treasures:
return
player.output("Select treasure that Tiara will let you play twice")
player.move_card(self, Piles.PLAYED)
if treasure := player.card_sel(cardsrc=treasures):
for _ in range(2):
player.play_card(treasure[0], discard=False, cost_action=False)
player.move_card(treasure[0], Piles.DISCARD)
player.move_card(treasure[0], Piles.PLAYED)

def hook_gain_card(self, game, player, card):
def hook_gain_card(
self, game: Game.Game, player: Player.Player, card: Card.Card
) -> dict[str, Any]:
"""when you gain a card, you may put it onto your deck."""
if top_deck := player.plr_choose_options(
if player.plr_choose_options(
f"Tiara lets you put {card} on top of your deck.",
(f"Put {card} on top of your deck?", True),
(f"Discard {card} as per normal?", False),
):
return {"destination": "topdeck"}
return {}


###############################################################################
class TestTiara(unittest.TestCase):
"""Test Tiara"""

def setUp(self):
def setUp(self) -> None:
self.g = Game.TestGame(numplayers=1, initcards=["Tiara"])
self.g.start_game()
self.plr = self.g.player_list()[0]
self.card = self.g.get_card_from_pile("Tiara")

def test_play_deck(self):
def test_play_deck(self) -> None:
"""Play a Tiara and put gained cards on to the deck"""
self.plr.piles[Piles.HAND].empty()
self.plr.add_card(self.card, Piles.HAND)
Expand All @@ -60,7 +66,7 @@ def test_play_deck(self):
self.plr.gain_card("Gold")
self.assertIn("Gold", self.plr.piles[Piles.DECK])

def test_discard(self):
def test_discard(self) -> None:
"""Play a tiara and discard gained cards"""
self.plr.piles[Piles.HAND].empty()
self.plr.add_card(self.card, Piles.HAND)
Expand All @@ -70,7 +76,7 @@ def test_discard(self):
self.assertNotIn("Gold", self.plr.piles[Piles.DECK])
self.assertIn("Gold", self.plr.piles[Piles.DISCARD])

def test_treasure(self):
def test_treasure(self) -> None:
"""Play a tiara and play a treasure twice"""
self.plr.piles[Piles.HAND].set("Copper", "Duchy", "Province")
self.plr.add_card(self.card, Piles.HAND)
Expand Down
Loading

0 comments on commit 2aa408e

Please sign in to comment.