Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions hearthstone/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,18 @@ def _capture_initial_card_id(self, card_id: str, tags: GameTagsDict) -> None:

def _update_tags(self, tags: GameTagsDict) -> None:
super()._update_tags(tags)
if self.is_original_entity and self.initial_creator is None:
creator = tags.get(GameTag.CREATOR, 0)
if creator:
if self.is_original_entity and not self.initial_creator:
# DISPLAYED_CREATOR is included because cards generated into the deck at the
# start of the game (eg. by Azalina Soulsever) only get tagged with it before
# they are revealed. Once they are revealed, reveal() has already cleared
# is_original_entity and it is too late to capture the creator.
creator = tags.get(GameTag.CREATOR, 0) or tags.get(GameTag.DISPLAYED_CREATOR, 0)

# A card is never created by itself. Cards that generate other cards can end up
# tagged as their own DISPLAYED_CREATOR (eg. Direhorn Hatchling, whose
# Deathrattle shuffles a Direhorn Matriarch into the deck); that does not make
# them generated cards.
if creator and creator != self.id:
self.initial_creator = creator

def reveal(self, card_id: str, tags: GameTagsDict) -> None:
Expand Down
61 changes: 61 additions & 0 deletions tests/test_entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,67 @@ def test_initial_deck_with_souleathers_scythe(self, game, player):

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

def test_initial_deck_with_cards_generated_at_start_of_game(self, game, player):
# Azalina Soulsever has a 20 card deck rule and generates the remaining cards
# into the deck during CREATE_GAME, before the game is set up.
azalina = Card(5, None)
azalina.tags.update({
GameTag.ZONE: Zone.DECK,
GameTag.CONTROLLER: player.player_id,
})
game.register_entity(azalina)
azalina.reveal("JAIL_430", {GameTag.CARDTYPE: CardType.MINION})

# The generated cards are created knowing nothing but their zone. The creator
# only follows as a separate tag change...
generated = Card(6, None)
generated.tags.update({
GameTag.ZONE: Zone.DECK,
GameTag.CONTROLLER: player.player_id,
})
game.register_entity(generated)
generated.tag_change(GameTag.DISPLAYED_CREATOR, azalina.id)

# ...and they are only revealed much later, once they are drawn.
generated.reveal("CS2_231", {
GameTag.CARDTYPE: CardType.MINION,
GameTag.CREATOR: azalina.id,
GameTag.DISPLAYED_CREATOR: azalina.id,
})

assert generated.initial_creator == azalina.id
assert list(player.initial_deck) == [azalina]

def test_initial_deck_with_card_that_is_its_own_creator(self, game, player):
# Direhorn Hatchling tags itself as its own DISPLAYED_CREATOR when its Deathrattle
# shuffles a Direhorn Matriarch into the deck. It is still an original deck card.
hatchling = Card(5, None)
hatchling.tags.update({
GameTag.ZONE: Zone.DECK,
GameTag.CONTROLLER: player.player_id,
})
game.register_entity(hatchling)
hatchling.reveal("UNG_957", {GameTag.CARDTYPE: CardType.MINION})
hatchling.tag_change(GameTag.DISPLAYED_CREATOR, hatchling.id)

assert hatchling.initial_creator == 0
assert list(player.initial_deck) == [hatchling]

def test_initial_deck_with_game_entity_as_creator(self, game, player):
# Monster Hunt / Dungeon Run decks are created by the game entity (CREATOR=1).
# Those cards are the player's deck and must be kept.
card = Card(5, None)
card.tags.update({
GameTag.ZONE: Zone.DECK,
GameTag.CONTROLLER: player.player_id,
})
game.register_entity(card)
card.tag_change(GameTag.CREATOR, game.id)
card.reveal("CS2_231", {GameTag.CARDTYPE: CardType.MINION})

assert card.initial_creator == game.id
assert list(player.initial_deck) == [card]

def test_known_starting_deck_list(self, game, player):
WISP = "CS2_231"

Expand Down
Loading