From 325b4b02ceb80965489da1e8d748b13b72e75d87 Mon Sep 17 00:00:00 2001 From: shinoi2 Date: Wed, 13 Dec 2023 17:13:44 +0800 Subject: [PATCH] Fix issues (#502) Fix issues * https://github.com/jleclanche/fireplace/issues/210 * https://github.com/jleclanche/fireplace/issues/225 --- fireplace/actions.py | 4 ++-- fireplace/card.py | 4 ++-- fireplace/cards/classic/shaman.py | 5 +---- fireplace/cards/debug/all.py | 2 +- fireplace/cards/icecrown/paladin.py | 6 +----- fireplace/cards/kobolds/neutral_common.py | 2 +- fireplace/cards/league/adventure.py | 4 ++-- fireplace/cards/league/collectible.py | 2 +- fireplace/cards/utils.py | 6 +++--- fireplace/dsl/random_picker.py | 12 ++++++++++-- fireplace/game.py | 16 ++++++++++++---- fireplace/player.py | 2 -- tests/test_classic.py | 11 +++++++++++ 13 files changed, 47 insertions(+), 29 deletions(-) diff --git a/fireplace/actions.py b/fireplace/actions.py index dcedc4727..30894544c 100644 --- a/fireplace/actions.py +++ b/fireplace/actions.py @@ -425,8 +425,6 @@ def do(self, source, card, target, index, choose): # NOTE: A Play is not a summon! But it sure looks like one. # We need to fake a Summon broadcast. summon_action = Summon(player, card) - if card.type == CardType.MINION and card.race == Race.TOTEM: - card.controller.times_totem_summoned_this_game += 1 if card.type in (CardType.MINION, CardType.WEAPON): self.queue_broadcast(summon_action, (player, EventListener.ON, player, card)) @@ -452,6 +450,8 @@ def do(self, source, card, target, index, choose): player.cards_played_this_turn += 1 if card.type == CardType.MINION: player.minions_played_this_turn += 1 + if card.race == Race.TOTEM: + card.controller.times_totem_summoned_this_game += 1 if card.race == Race.ELEMENTAL: player.elemental_played_this_turn += 1 player.cards_played_this_game.append(card) diff --git a/fireplace/card.py b/fireplace/card.py index 323d54917..60ab3a8e3 100644 --- a/fireplace/card.py +++ b/fireplace/card.py @@ -183,7 +183,7 @@ def _set_zone(self, value): caches[value].append(self) self._zone = value - if value == Zone.PLAY: + if value == Zone.PLAY or value == Zone.SECRET: self.play_counter = self.game.play_counter self.game.play_counter += 1 @@ -749,6 +749,7 @@ def _getattr(self, attr, i): return ret def _set_zone(self, value): + super()._set_zone(value) if value == Zone.PLAY: old_hero = self.controller.hero self.controller.hero = self @@ -761,7 +762,6 @@ def _set_zone(self, value): self.power.zone = Zone.GRAVEYARD if self.controller.hero is self: self.controller.playstate = PlayState.LOSING - super()._set_zone(value) def _hit(self, amount): amount = super()._hit(amount) diff --git a/fireplace/cards/classic/shaman.py b/fireplace/cards/classic/shaman.py index 5965bc43a..c1c31f015 100644 --- a/fireplace/cards/classic/shaman.py +++ b/fireplace/cards/classic/shaman.py @@ -10,10 +10,7 @@ class CS2_049: PlayReq.REQ_ENTIRE_ENTOURAGE_NOT_IN_PLAY: 0, PlayReq.REQ_NUM_MINION_SLOTS: 1} entourage = ["CS2_050", "CS2_051", "CS2_052", "NEW1_009"] - - def activate(self): - totems = [t for t in self.entourage if not self.controller.field.contains(t)] - yield Summon(CONTROLLER, random.choice(totems)) + activate = Summon(CONTROLLER, RandomEntourage(exclude=FRIENDLY_MINIONS)) class CS2_049_H1: diff --git a/fireplace/cards/debug/all.py b/fireplace/cards/debug/all.py index 6408d203f..04bdcda44 100644 --- a/fireplace/cards/debug/all.py +++ b/fireplace/cards/debug/all.py @@ -83,7 +83,7 @@ def play(self): class XXX_016: """Snake Ball""" - play = Summon("EX1_554t") * 5 + play = Summon(CONTROLLER, "EX1_554t") * 5 class XXX_017: diff --git a/fireplace/cards/icecrown/paladin.py b/fireplace/cards/icecrown/paladin.py index 3452daece..f7d470922 100644 --- a/fireplace/cards/icecrown/paladin.py +++ b/fireplace/cards/icecrown/paladin.py @@ -71,11 +71,7 @@ class ICC_829: class ICC_829p: entourage = ["ICC_829t2", "ICC_829t3", "ICC_829t4", "ICC_829t5"] - - def activate(self): - totems = [t for t in self.entourage if not self.controller.field.contains(t)] - yield Summon(CONTROLLER, random.choice(totems)) - + activate = Summon(CONTROLLER, RandomEntourage(exclude=FRIENDLY_MINIONS)) update = FindAll( FRIENDLY_MINIONS + ID("ICC_829t2"), FRIENDLY_MINIONS + ID("ICC_829t3"), diff --git a/fireplace/cards/kobolds/neutral_common.py b/fireplace/cards/kobolds/neutral_common.py index c5f6cebfc..bc296fc2f 100644 --- a/fireplace/cards/kobolds/neutral_common.py +++ b/fireplace/cards/kobolds/neutral_common.py @@ -65,7 +65,7 @@ class LOOT_152: class LOOT_153: """Violet Wurm""" # Deathrattle: Summon seven 1/1 Grubs. - deathrattle = Summon("LOOT_153t1") * 7 + deathrattle = Summon(CONTROLLER, "LOOT_153t1") * 7 class LOOT_167: diff --git a/fireplace/cards/league/adventure.py b/fireplace/cards/league/adventure.py index 604031571..ce196e4a4 100644 --- a/fireplace/cards/league/adventure.py +++ b/fireplace/cards/league/adventure.py @@ -307,7 +307,7 @@ class LOEA09_2H: class LOEA09_3: """Getting Hungry""" - activate = Summon("LOEA09_5").then( + activate = Summon(CONTROLLER, "LOEA09_5").then( Buff(Summon.CARD, "LOEA09_3a") * Attr( CONTROLLER, GameTag.NUM_TIMES_HERO_POWER_USED_THIS_GAME ) @@ -319,7 +319,7 @@ class LOEA09_3: class LOEA09_3H: """Getting Hungry (Heroic)""" - activate = Summon("LOEA09_5").then( + activate = Summon(CONTROLLER, "LOEA09_5").then( Buff(Summon.CARD, "LOEA09_3aH") * Attr( CONTROLLER, GameTag.NUM_TIMES_HERO_POWER_USED_THIS_GAME ) diff --git a/fireplace/cards/league/collectible.py b/fireplace/cards/league/collectible.py index 256b8581a..4bd689341 100644 --- a/fireplace/cards/league/collectible.py +++ b/fireplace/cards/league/collectible.py @@ -142,7 +142,7 @@ class LOE_073: class LOE_076: """Sir Finley Mrrgglton""" - play = GenericChoice(CONTROLLER, RandomBasicHeroPower() * 3) + play = GenericChoice(CONTROLLER, RandomBasicHeroPower(exclude=FRIENDLY_HERO_POWER) * 3) class LOE_077: diff --git a/fireplace/cards/utils.py b/fireplace/cards/utils.py index 9307f2778..0f6567eab 100644 --- a/fireplace/cards/utils.py +++ b/fireplace/cards/utils.py @@ -80,9 +80,9 @@ THE_COIN = "GAME_005" -RandomBasicTotem = lambda *args: RandomID(*BASIC_TOTEMS) -RandomBasicHeroPower = lambda *args: RandomID(*BASIC_HERO_POWERS) -RandomPotion = lambda *args: RandomID(*POTIONS) +RandomBasicTotem = lambda *args, **kw: RandomID(*BASIC_TOTEMS, **kw) +RandomBasicHeroPower = lambda *args, **kw: RandomID(*BASIC_HERO_POWERS, **kw) +RandomPotion = lambda *args, **kw: RandomID(*POTIONS, **kw) # 50% chance to attack the wrong enemy. FORGETFUL = Attack(SELF).on( diff --git a/fireplace/dsl/random_picker.py b/fireplace/dsl/random_picker.py index e74e50768..12730f364 100644 --- a/fireplace/dsl/random_picker.py +++ b/fireplace/dsl/random_picker.py @@ -81,6 +81,14 @@ def evaluate(self, source, cards=None) -> str: if cards: # Use specific card list if given self.weights = [1] + if "exclude" in self.filters: + exclude = self.filters["exclude"] + if isinstance(exclude, LazyValue): + exclude = exclude.evaluate(source) + elif isinstance(exclude, Selector): + exclude = exclude.eval(source.game, source) + exclude = [card.id for card in exclude] + cards = [card for card in cards if card not in exclude] card_sets = [list(cards)] elif not self.weightedfilters: # Use global filters if no weighted filter sets given @@ -118,8 +126,8 @@ def evaluate(self, source): class RandomID(RandomCardPicker): - def __init__(self, *args): - super().__init__() + def __init__(self, *args, **kw): + super().__init__(**kw) self._cards = args def clone(self, memo): diff --git a/fireplace/game.py b/fireplace/game.py index aa776701e..d3758b30f 100644 --- a/fireplace/game.py +++ b/fireplace/game.py @@ -54,7 +54,9 @@ def is_standard(self): @property def board(self): - return CardList(chain(self.players[0].field, self.players[1].field)) + ret = CardList(chain(self.players[0].field, self.players[1].field)) + ret.sort(key=lambda e: e.play_counter) + return ret @property def decks(self): @@ -70,7 +72,9 @@ def hands(self): @property def characters(self): - return CardList(chain(self.players[0].characters, self.players[1].characters)) + ret = CardList(chain(self.players[0].characters, self.players[1].characters)) + ret.sort(key=lambda e: e.play_counter) + return ret @property def graveyard(self): @@ -78,11 +82,15 @@ def graveyard(self): @property def entities(self): - return CardList(chain([self], self.players[0].entities, self.players[1].entities)) + ret = CardList(chain([self], self.players[0].entities, self.players[1].entities)) + ret.sort(key=lambda e: e.play_counter) + return ret @property def live_entities(self): - return CardList(chain(self.players[0].live_entities, self.players[1].live_entities)) + ret = CardList(chain(self.players[0].live_entities, self.players[1].live_entities)) + ret.sort(key=lambda e: e.play_counter) + return ret @property def minions_killed_this_turn(self): diff --git a/fireplace/player.py b/fireplace/player.py index 3484ba58a..6882a8afe 100644 --- a/fireplace/player.py +++ b/fireplace/player.py @@ -163,8 +163,6 @@ def card(self, id, source=None, parent=None, zone=Zone.SETASIDE): card = Card(id) card.controller = self card.zone = zone - card.play_counter = self.game.play_counter - self.game.play_counter += 1 if source is not None: card.creator = source if parent is not None: diff --git a/tests/test_classic.py b/tests/test_classic.py index aa655169f..9ad496b3c 100644 --- a/tests/test_classic.py +++ b/tests/test_classic.py @@ -3810,3 +3810,14 @@ def test_gruul_ragnaros(): assert len(game.player1.field) == 1 assert gruul.atk == 9 assert (gruul.damage == 8) ^ (game.player1.hero.damage == 8) + + +def test_sorted_deathrattle(): + game = prepare_game() + game.player1.give("LOOT_153").play() + game.player1.give("OG_241").play(index=0) + game.end_turn() + game.player2.give("EX1_312").play() + assert len(game.player1.field) == 7 + for minion in game.player1.field: + assert minion.id == "LOOT_153t1"