Skip to content

Commit

Permalink
Rewrite cards_drawn_this_turn & cards_played_this_turn, and fix some …
Browse files Browse the repository at this point in the history
…bugs
  • Loading branch information
shinoi2 committed Mar 27, 2024
1 parent 84fcde2 commit 8e88a1f
Show file tree
Hide file tree
Showing 19 changed files with 76 additions and 46 deletions.
6 changes: 4 additions & 2 deletions fireplace/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,8 +519,9 @@ def do(self, source, card, target, index, choose):
card.controller.times_totem_summoned_this_game += 1
if Race.ELEMENTAL in card.races:
player.elemental_played_this_turn += 1
player.cards_played_this_turn.append(card)
player.cards_played_this_turn += 1
player.cards_played_this_game.append(card)
card.turn_played = source.game.turn
card.choose = None


Expand Down Expand Up @@ -1165,7 +1166,8 @@ def do(self, source, target, card):
else:
log.info("%s draws %r", target, card)
card.zone = Zone.HAND
target.cards_drawn_this_turn.append(card)
card.turn_drawn = source.game.turn
source.controller.cards_drawn_this_turn += 1
source.game.manager.targeted_action(self, source, target, card)
if source.game.step > Step.BEGIN_MULLIGAN:
# Proc the draw script, but only if we are past mulligan
Expand Down
26 changes: 22 additions & 4 deletions fireplace/card.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ def __init__(self, data):
self.rarity = Rarity.INVALID
self.choose_cards = CardList()
self.morphed = None
self.turn_drawn = -1
self.turn_played = -1
self.cast_on_friendly_minions = False
self.play_right_most = False
self.custom_card = False
Expand Down Expand Up @@ -344,6 +346,18 @@ def powered_up(self):
def entities(self):
return chain([self], self.buffs)

@property
def drawn_this_turn(self):
return self.turn_drawn == self.game.turn

@property
def played_this_turn(self):
return self.turn_played == self.game.turn

@property
def played_last_turn(self):
return self.turn_played == self.controller.last_turn

@property
def zone_position(self):
"""
Expand Down Expand Up @@ -448,7 +462,7 @@ def is_playable(self):
return False

if PlayReq.REQ_MUST_PLAY_OTHER_CARD_FIRST in self.requirements:
if len(self.controller.cards_played_this_turn) == 0:
if not any(getattr(e, "played_this_turn", False) for e in self.game):
return False

if PlayReq.REQ_HAND_NOT_FULL in self.requirements:
Expand Down Expand Up @@ -587,19 +601,23 @@ def requires_target(self):
req = self.requirements.get(
PlayReq.REQ_TARGET_IF_AVAILABLE_AND_MINIMUM_SPELLS_PLAYED_THIS_TURN)
if req is not None:
if len(self.controller.cards_played_this_turn.filter(type=CardType.SPELL)) >= req:
if sum(
getattr(e, "played_this_turn", False) and
getattr(e, "type", None) == CardType.SPELL
for e in self.game
) >= req:
return bool(self.play_targets)
req = self.requirements.get(PlayReq.REQ_TARGET_IF_AVAILABLE_AND_HAS_OVERLOADED_MANA)
if req is not None:
if self.controller.overloaded > 0:
return bool(self.play_targets)
req = self.requirements.get(PlayReq.REQ_TARGET_IF_AVAILABLE_AND_DRAWN_THIS_TURN)
if req is not None:
if self in self.controller.cards_drawn_this_turn:
if self.drawn_this_turn:
return bool(self.play_targets)
req = self.requirements.get(PlayReq.REQ_TARGET_IF_AVAILABLE_AND_NOT_DRAWN_THIS_TURN)
if req is not None:
if self not in self.controller.cards_drawn_this_turn:
if not self.drawn_this_turn:
return bool(self.play_targets)
req = self.requirements.get(
PlayReq.REQ_TARGET_IF_AVAILABLE_AND_ONLY_EVEN_COST_CARD_IN_DECK)
Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/boomsday/neutral_rare.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class BOT_066:
class BOT_098:
"""Unpowered Mauler"""
# Can only attack if you cast a spell this turn.
update = Find(CARDS_PLAYED_THIS_TRUN + SPELL) | Refresh(SELF, {GameTag.CANT_ATTACK: True})
update = Find(CARDS_PLAYED_THIS_TURN + SPELL) | Refresh(SELF, {GameTag.CANT_ATTACK: True})


class BOT_102:
Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/classic/rogue.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class EX1_134:

class EX1_613:
"""Edwin VanCleef"""
combo = Buff(SELF, "EX1_613e") * Count(CARDS_PLAYED_THIS_TRUN)
combo = Buff(SELF, "EX1_613e") * NUM_CARDS_PLAYED_THIS_TURN


EX1_613e = buff(+2, +2)
Expand Down
4 changes: 2 additions & 2 deletions fireplace/cards/dalaran/mage.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ class DAL_603:
# [x]<b>Battlecry:</b> For each spell you've cast this turn, add a random Mage spell to
# your hand.
play = Give(CONTROLLER, RandomSpell(card_class=CardClass.MAGE)) * Count(
CARDS_PLAYED_THIS_TRUN + SPELL)
CARDS_PLAYED_THIS_TURN + SPELL)


class DAL_609:
"""Kalecgos"""
# Your first spell each turn costs (0). <b>Battlecry:</b> <b>Discover</b> a spell.
update = (
(Count(CARDS_PLAYED_THIS_TRUN + SPELL) == 0) &
(Count(CARDS_PLAYED_THIS_TURN + SPELL) == 0) &
Refresh(FRIENDLY_HAND + SPELL, buff="DAL_609e")
)
play = DISCOVER(RandomSpell())
Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/dalaran/neutral_legendary.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class DAL_558:
"""Archmage Vargoth"""
# [x]At the end of your turn, cast a spell you've cast this turn <i>(targets are
# random)</i>.
events = OWN_TURN_END.on(CastSpell(Copy(RANDOM(CARDS_PLAYED_THIS_TRUN + SPELL))))
events = OWN_TURN_END.on(CastSpell(Copy(RANDOM(CARDS_PLAYED_THIS_TURN + SPELL))))


class DAL_736:
Expand Down
6 changes: 4 additions & 2 deletions fireplace/cards/dalaran/shaman.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ class DAL_049:
class DAL_052:
"""Muckmorpher"""
# [x]<b>Battlecry:</b> Transform into a 4/4 copy of a different minion in your deck.
play = Morph(SELF, Copy(RANDOM(FRIENDLY_DECK + MINION - ID("DAL_052")))).then(
Buff(Morph.CARD, "DAL_052e")
play = Find(FRIENDLY_DECK + MINION - ID("DAL_052")) & (
Morph(SELF, Copy(RANDOM(FRIENDLY_DECK + MINION - ID("DAL_052")))).then(
Buff(Morph.CARD, "DAL_052e")
)
)


Expand Down
3 changes: 2 additions & 1 deletion fireplace/cards/dalaran/warrior.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class DAL_059:

def play(self):
minion = random.choice(self.controller.deck.filter(type=CardType.MINION))
yield Summon(CONTROLLER, minion.id) * 2
if minion:
yield Summon(CONTROLLER, minion.id) * 2


class DAL_062:
Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/icecrown/rogue.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ICC_910:
requirements = {
PlayReq.REQ_TARGET_FOR_COMBO: 0,
}
combo = Hit(TARGET, Count(CARDS_PLAYED_THIS_TRUN))
combo = Hit(TARGET, NUM_CARDS_PLAYED_THIS_TURN)


##
Expand Down
4 changes: 2 additions & 2 deletions fireplace/cards/troll/shaman.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class TRL_085:
class TRL_345:
"""Krag'wa, the Frog"""
# <b>Battlecry:</b> Return all spells you played last turn to_your hand.
play = Give(CONTROLLER, Copy(CARDS_PLAYED_LAST_TRUN + SPELL))
play = Give(CONTROLLER, Copy(CARDS_PLAYED_LAST_TURN + SPELL))


class TRL_522:
Expand All @@ -56,7 +56,7 @@ class TRL_522:
requirements = {
PlayReq.REQ_TARGET_IF_AVAILABLE_AND_MINIMUM_SPELLS_PLAYED_THIS_TURN: 2,
}
powered_up = Count(CARDS_PLAYED_THIS_TRUN + SPELL) >= 2
powered_up = Count(CARDS_PLAYED_THIS_TURN + SPELL) >= 2
play = powered_up & Hit(TARGET, 2)


Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/ungoro/rogue.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class UNG_058:

class UNG_063:
"""Biteweed"""
combo = Buff(SELF, "UNG_063e") * Count(CARDS_PLAYED_THIS_TRUN)
combo = Buff(SELF, "UNG_063e") * NUM_CARDS_PLAYED_THIS_TURN


UNG_063e = buff(+1, +1)
Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/witchwood/hunter.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class GIL_577:
"""Rat Trap"""
# [x]<b>Secret:</b> After your opponent plays three cards in a turn, summon a 6/6 Rat.
secret = Play(OPPONENT).after(
(Count(OPPONENT_CARDS_PLAYED_THIS_TRUN) >= 3) & (
(Attr(OPPONENT, GameTag.NUM_CARDS_PLAYED_THIS_TURN) >= 3) & (
FULL_BOARD | (Reveal(SELF), Summon(CONTROLLER, "GIL_577t"))
)
)
Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/witchwood/paladin.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class GIL_903:
"""Hidden Wisdom"""
# [x]<b>Secret:</b> After your opponent plays three cards in a turn, draw 2 cards.
secret = Play(OPPONENT).after(
(Count(OPPONENT_CARDS_PLAYED_THIS_TRUN) >= 3) & (
(Attr(CONTROLLER, GameTag.NUM_CARDS_PLAYED_THIS_TURN) >= 3) & (
Reveal(SELF), Draw(CONTROLLER) * 2
)
)
Expand Down
9 changes: 3 additions & 6 deletions fireplace/dsl/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,12 +590,9 @@ def CONTROLLED_BY(selector):
lambda entities, source: source.game.player1.hand[:1] + source.game.player2.hand[-1:])
OUTERMOST_HAND = LEFTMOST_HAND + RIGTHMOST_HAND

CARDS_PLAYED_THIS_TRUN = FuncSelector(
lambda entities, source: source.controller.cards_played_this_turn)
CARDS_PLAYED_LAST_TRUN = FuncSelector(
lambda entities, source: source.controller.cards_played_last_turn)
OPPONENT_CARDS_PLAYED_THIS_TRUN = FuncSelector(
lambda entities, source: source.controller.opponent.cards_played_this_turn)
NUM_CARDS_PLAYED_THIS_TURN = Attr(CONTROLLER, GameTag.NUM_CARDS_PLAYED_THIS_TURN)
CARDS_PLAYED_THIS_TURN = AttrValue("played_this_turn") == True # noqa
CARDS_PLAYED_LAST_TURN = AttrValue("played_this_turn") == True # noqa

CARDS_PLAYED_THIS_GAME = FuncSelector(
lambda entities, source: source.controller.cards_played_this_game)
Expand Down
11 changes: 4 additions & 7 deletions fireplace/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ def board(self):
def decks(self):
return CardList(chain(self.players[0].deck, self.players[1].deck))

@property
def discarded(self):
return CardList(chain(self.players[0].discarded, self.players[1].discarded))

@property
def hands(self):
return CardList(chain(self.players[0].hand, self.players[1].hand))
Expand Down Expand Up @@ -334,11 +330,12 @@ def _begin_turn(self, player):
self.manager.step(self.next_step, Step.MAIN_ACTION)

for p in self.players:
p.cards_drawn_this_turn = CardList()
p.cards_drawn_this_turn = 0

player.turn_start = timegm(time.gmtime())
player.cards_played_last_turn = player.cards_played_this_turn
player.cards_played_this_turn = CardList()
player.last_turn = player.turn
player.turn = self.turn
player.cards_played_this_turn = 0
player.minions_played_this_turn = 0
player.minions_killed_this_turn = 0
player.combo = False
Expand Down
8 changes: 4 additions & 4 deletions fireplace/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ def __init__(self, name, deck, hero, is_standard=True):
super().__init__()
self.deck = Deck()
self.hand = CardList()
self.discarded = CardList()
self.field = CardList()
self.graveyard = CardList()
self.secrets = CardList()
Expand All @@ -56,7 +55,6 @@ def __init__(self, name, deck, hero, is_standard=True):
self.cant_fatigue = False
self.fatigue_counter = 0
self.last_card_played = None
self.cards_drawn_this_turn = CardList()
self.overloaded = 0
self.overload_locked = 0
self.overloaded_this_game = 0
Expand All @@ -70,12 +68,14 @@ def __init__(self, name, deck, hero, is_standard=True):
self.minions_killed_this_turn = 0
self.weapon = None
self.zone = Zone.INVALID
self.turn = None
self.last_turn = None
self.jade_golem = 1
self.times_totem_summoned_this_game = 0
self.elemental_played_this_turn = 0
self.elemental_played_last_turn = 0
self.cards_played_this_turn = CardList()
self.cards_played_last_turn = CardList()
self.cards_drawn_this_turn = 0
self.cards_played_this_turn = 0
self.cards_played_this_game = CardList()
self.hero_power_damage_this_game = 0
self.spent_mana_on_spells_this_game = 0
Expand Down
10 changes: 5 additions & 5 deletions tests/test_classic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3506,20 +3506,20 @@ def test_vancleef():
vancleef1 = game.current_player.give("EX1_613")
vancleef2 = game.current_player.give("EX1_613")

assert len(game.current_player.cards_played_this_turn) == 0
assert game.current_player.cards_played_this_turn == 0
for i in range(5):
game.player1.give(THE_COIN).play()
assert len(game.current_player.cards_played_this_turn) == 5
assert game.current_player.cards_played_this_turn == 5
vancleef1.play()
assert len(game.current_player.cards_played_this_turn) == 6
assert game.current_player.cards_played_this_turn == 6
assert vancleef1.atk == 12
assert vancleef1.health == 12
game.end_turn()
game.end_turn()

assert len(game.current_player.cards_played_this_turn) == 0
assert game.current_player.cards_played_this_turn == 0
vancleef2.play()
assert len(game.current_player.cards_played_this_turn) == 1
assert game.current_player.cards_played_this_turn == 1
assert vancleef2.atk == 2
assert vancleef2.health == 2

Expand Down
8 changes: 4 additions & 4 deletions tests/test_mechanics.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,25 +106,25 @@ def test_card_draw():
game.end_turn()
game.end_turn()

assert len(game.current_player.cards_drawn_this_turn) == 1
assert game.current_player.cards_drawn_this_turn == 1
assert len(game.current_player.hand) == 5
novice = game.current_player.give("EX1_015")
assert len(game.current_player.hand) == 6
# novice should draw 1 card
novice.play()
# hand should be 1 card played, 1 card drawn; same size
assert len(game.current_player.hand) == 6
assert len(game.current_player.cards_drawn_this_turn) == 2
assert game.current_player.cards_drawn_this_turn == 2
game.end_turn()

assert len(game.current_player.cards_drawn_this_turn) == 1
assert game.current_player.cards_drawn_this_turn == 1
# succubus should discard 1 card
card = game.current_player.give("EX1_306")
handlength = len(game.current_player.hand)
card.play()
assert len(game.current_player.hand) == handlength - 2
# Discarding a card should not effect the number of cards drawn.
assert len(game.current_player.cards_drawn_this_turn) == 1
assert game.current_player.cards_drawn_this_turn == 1


def test_cant_draw():
Expand Down
13 changes: 13 additions & 0 deletions tests/test_troll.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,16 @@ def test_heavy_metal():
assert game.player1.hero.armor == 15
game.player1.give("TRL_324").play()
assert game.player1.field[1].cost == 10


def test_wartbringer():
game = prepare_game()
wartbringer = game.player1.give("TRL_522")
assert not wartbringer.powered_up
assert not wartbringer.requires_target()
game.player1.give(MOONFIRE).play(target=game.player2.hero)
assert not wartbringer.powered_up
assert not wartbringer.requires_target()
game.player1.give(MOONFIRE).play(target=game.player2.hero)
assert wartbringer.powered_up
assert wartbringer.requires_target()

0 comments on commit 8e88a1f

Please sign in to comment.