Skip to content

Commit 4efeeb9

Browse files
fix: initial_creator tracking
1 parent 5b955da commit 4efeeb9

2 files changed

Lines changed: 73 additions & 3 deletions

File tree

hearthstone/entities.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,18 @@ def _capture_initial_card_id(self, card_id: str, tags: GameTagsDict) -> None:
354354

355355
def _update_tags(self, tags: GameTagsDict) -> None:
356356
super()._update_tags(tags)
357-
if self.is_original_entity and self.initial_creator is None:
358-
creator = tags.get(GameTag.CREATOR, 0)
359-
if creator:
357+
if self.is_original_entity and not self.initial_creator:
358+
# DISPLAYED_CREATOR is included because cards generated into the deck at the
359+
# start of the game (eg. by Azalina Soulsever) only get tagged with it before
360+
# they are revealed. Once they are revealed, reveal() has already cleared
361+
# is_original_entity and it is too late to capture the creator.
362+
creator = tags.get(GameTag.CREATOR, 0) or tags.get(GameTag.DISPLAYED_CREATOR, 0)
363+
364+
# A card is never created by itself. Cards that generate other cards can end up
365+
# tagged as their own DISPLAYED_CREATOR (eg. Direhorn Hatchling, whose
366+
# Deathrattle shuffles a Direhorn Matriarch into the deck); that does not make
367+
# them generated cards.
368+
if creator and creator != self.id:
360369
self.initial_creator = creator
361370

362371
def reveal(self, card_id: str, tags: GameTagsDict) -> None:

tests/test_entities.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,67 @@ def test_initial_deck_with_souleathers_scythe(self, game, player):
130130

131131
assert list(player.initial_deck) == [wisp, scythe]
132132

133+
def test_initial_deck_with_cards_generated_at_start_of_game(self, game, player):
134+
# Azalina Soulsever has a 20 card deck rule and generates the remaining cards
135+
# into the deck during CREATE_GAME, before the game is set up.
136+
azalina = Card(5, None)
137+
azalina.tags.update({
138+
GameTag.ZONE: Zone.DECK,
139+
GameTag.CONTROLLER: player.player_id,
140+
})
141+
game.register_entity(azalina)
142+
azalina.reveal("JAIL_430", {GameTag.CARDTYPE: CardType.MINION})
143+
144+
# The generated cards are created knowing nothing but their zone. The creator
145+
# only follows as a separate tag change...
146+
generated = Card(6, None)
147+
generated.tags.update({
148+
GameTag.ZONE: Zone.DECK,
149+
GameTag.CONTROLLER: player.player_id,
150+
})
151+
game.register_entity(generated)
152+
generated.tag_change(GameTag.DISPLAYED_CREATOR, azalina.id)
153+
154+
# ...and they are only revealed much later, once they are drawn.
155+
generated.reveal("CS2_231", {
156+
GameTag.CARDTYPE: CardType.MINION,
157+
GameTag.CREATOR: azalina.id,
158+
GameTag.DISPLAYED_CREATOR: azalina.id,
159+
})
160+
161+
assert generated.initial_creator == azalina.id
162+
assert list(player.initial_deck) == [azalina]
163+
164+
def test_initial_deck_with_card_that_is_its_own_creator(self, game, player):
165+
# Direhorn Hatchling tags itself as its own DISPLAYED_CREATOR when its Deathrattle
166+
# shuffles a Direhorn Matriarch into the deck. It is still an original deck card.
167+
hatchling = Card(5, None)
168+
hatchling.tags.update({
169+
GameTag.ZONE: Zone.DECK,
170+
GameTag.CONTROLLER: player.player_id,
171+
})
172+
game.register_entity(hatchling)
173+
hatchling.reveal("UNG_957", {GameTag.CARDTYPE: CardType.MINION})
174+
hatchling.tag_change(GameTag.DISPLAYED_CREATOR, hatchling.id)
175+
176+
assert hatchling.initial_creator == 0
177+
assert list(player.initial_deck) == [hatchling]
178+
179+
def test_initial_deck_with_game_entity_as_creator(self, game, player):
180+
# Monster Hunt / Dungeon Run decks are created by the game entity (CREATOR=1).
181+
# Those cards are the player's deck and must be kept.
182+
card = Card(5, None)
183+
card.tags.update({
184+
GameTag.ZONE: Zone.DECK,
185+
GameTag.CONTROLLER: player.player_id,
186+
})
187+
game.register_entity(card)
188+
card.tag_change(GameTag.CREATOR, game.id)
189+
card.reveal("CS2_231", {GameTag.CARDTYPE: CardType.MINION})
190+
191+
assert card.initial_creator == game.id
192+
assert list(player.initial_deck) == [card]
193+
133194
def test_known_starting_deck_list(self, game, player):
134195
WISP = "CS2_231"
135196

0 commit comments

Comments
 (0)