Skip to content

Commit

Permalink
Fix bugs (#514)
Browse files Browse the repository at this point in the history
* fix bug

* Spirit of the Shark only work on minion
  • Loading branch information
shinoi2 authored Jan 9, 2024
1 parent d9fbed9 commit 83a5c63
Show file tree
Hide file tree
Showing 19 changed files with 158 additions and 60 deletions.
89 changes: 50 additions & 39 deletions fireplace/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -832,11 +832,10 @@ class Damage(TargetedAction):
TARGET = ActionArg()
AMOUNT = IntArg()

def get_target_args(self, source, target):
return [target.predamage]

def do(self, source, target, amount):
amount = target._hit(target.predamage)
def do(self, source, target, amount=None):
if not amount:
amount = target.predamage
amount = target._hit(amount)
target.predamage = 0
if (source.type == CardType.MINION or source.type == CardType.HERO) and source.stealthed:
# TODO this should be an event listener of sorts
Expand Down Expand Up @@ -938,12 +937,15 @@ def do(self, source, card, target=None):
source.game.main_power(source, actions, target)

if (
player.extra_combos and card.type == CardType.MINION and
player.minion_extra_combos and card.type == CardType.MINION and
card.has_combo and player.combo
) or (
player.extra_battlecries and card.has_battlecry
) or (
player.minion_extra_battlecries and card.type == CardType.MINION and
card.has_battlecry
):
source.game.main_power(source, actions, target)
elif player.extra_battlecries and card.has_battlecry:
source.game.main_power(source, actions, target)

if card.overload:
source.game.queue_actions(card, [Overload(player, card.overload)])
Expand Down Expand Up @@ -1612,9 +1614,6 @@ def get_target_args(self, source, target):
spell_target = [None]
if ret:
spell_target = ret[0]
else:
if target.target:
return [target.target]
return [spell_target]

def do(self, source, card, targets):
Expand Down Expand Up @@ -1831,18 +1830,23 @@ def do_step3(self):

def done(self):
card = self.choosed_cards[0]
new_card = self.player.card(self.potions_card[card.id])
self.potions = self.potions_choice_map[card.id][:]
card1 = self.choosed_cards[1]
card2 = self.choosed_cards[2]
self.potions = self.potions_choice_map[card.id][:]
if self.potions.index(card1.id) > self.potions.index(card2.id):
card1, card2 = card2, card1
new_card.requirements.update(card1.requirements)
new_card.requirements.update(card2.requirements)
new_card.data.scripts.play = card1.data.scripts.play + card2.data.scripts.play
new_card.requirements = card1.requirements | card2.requirements
new_card.tags[GameTag.CARDTEXT_ENTITY_0] = card1.data.strings[GameTag.CARDTEXT]
new_card.tags[GameTag.CARDTEXT_ENTITY_1] = card2.data.strings[GameTag.CARDTEXT]

new_card = self.player.card(self.potions_card[card.id])
new_card.custom_card = True

def create_custom_card(new_card):
new_card.data.scripts.play = card1.data.scripts.play + card2.data.scripts.play
new_card.requirements = card1.requirements | card2.requirements
new_card.tags[GameTag.CARDTEXT_ENTITY_0] = card1.data.strings[GameTag.CARDTEXT]
new_card.tags[GameTag.CARDTEXT_ENTITY_1] = card2.data.strings[GameTag.CARDTEXT]

new_card.create_custom_card = create_custom_card
new_card.create_custom_card(new_card)
self.player.give(new_card)

def choose(self, card):
Expand Down Expand Up @@ -2047,28 +2051,35 @@ def do_step2(self):
self.cards = [self.player.card(id) for id in random.sample(self.second_ids, 3)]

def done(self):
zombeast = self.player.card("ICC_828t")
card1 = self.choosed_cards[0]
card2 = self.choosed_cards[1]
zombeast.tags[GameTag.CARDTEXT_ENTITY_0] = card2.data.strings[GameTag.CARDTEXT]
zombeast.tags[GameTag.CARDTEXT_ENTITY_1] = card1.data.strings[GameTag.CARDTEXT]
zombeast.data.scripts = card1.data.scripts
int_mergeable_attributes = (
"atk", "cost", "max_health", "incoming_damage_multiplier", "spellpower",
"windfury",
)
bool_mergeable_attributes = (
"has_deathrattle", "charge", "has_inspire", "stealthed", "cant_attack",
"cant_be_targeted_by_opponents", "cant_be_targeted_by_abilities",
"cant_be_targeted_by_hero_powers", "heavily_armored", "min_health",
"rush", "taunt", "poisonous", "ignore_taunt", "cannot_attack_heroes",
"unlimited_attacks", "cant_be_damaged", "lifesteal",
"cant_be_targeted_by_op_abilities", "cant_be_targeted_by_op_hero_powers",
)
for attribute in int_mergeable_attributes:
setattr(zombeast, attribute, getattr(card1, attribute) + getattr(card2, attribute))
for attribute in bool_mergeable_attributes:
setattr(zombeast, attribute, getattr(card1, attribute) or getattr(card2, attribute))

zombeast = self.player.card("ICC_828t")
zombeast.custom_card = True

def create_custom_card(zombeast):
zombeast.tags[GameTag.CARDTEXT_ENTITY_0] = card2.data.strings[GameTag.CARDTEXT]
zombeast.tags[GameTag.CARDTEXT_ENTITY_1] = card1.data.strings[GameTag.CARDTEXT]
zombeast.data.scripts = card1.data.scripts
int_mergeable_attributes = (
"atk", "cost", "max_health", "incoming_damage_multiplier", "spellpower",
"windfury",
)
bool_mergeable_attributes = (
"has_deathrattle", "charge", "has_inspire", "stealthed", "cant_attack",
"cant_be_targeted_by_opponents", "cant_be_targeted_by_abilities",
"cant_be_targeted_by_hero_powers", "heavily_armored", "min_health",
"rush", "taunt", "poisonous", "ignore_taunt", "cannot_attack_heroes",
"unlimited_attacks", "cant_be_damaged", "lifesteal",
"cant_be_targeted_by_op_abilities", "cant_be_targeted_by_op_hero_powers",
)
for attribute in int_mergeable_attributes:
setattr(zombeast, attribute, getattr(card1, attribute) + getattr(card2, attribute))
for attribute in bool_mergeable_attributes:
setattr(zombeast, attribute, getattr(card1, attribute) or getattr(card2, attribute))

zombeast.create_custom_card = create_custom_card
zombeast.create_custom_card(zombeast)
self.player.give(zombeast)

def choose(self, card):
Expand Down
1 change: 1 addition & 0 deletions fireplace/card.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ def __init__(self, data):
self.upgrade_counter = 0
self.cast_on_friendly_minions = False
self.play_right_most = False
self.custom_card = False
super().__init__(data)

@property
Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/blackrock/collectible.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class BRM_029:

class BRM_030:
"""Nefarian"""
play = Find(ENEMY_HERO + CLASS_CARD) & (
play = Find(ENEMY_HERO - NEUTRAL) & (
Give(CONTROLLER, RandomSpell(card_class=ENEMY_CLASS)) * 2
) | (
Give(CONTROLLER, "BRM_030t") * 2
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_GAME + SPELL) | Refresh(SELF, {GameTag.CANT_ATTACK: True})
update = Find(CARDS_PLAYED_THIS_TRUN + SPELL) | Refresh(SELF, {GameTag.CANT_ATTACK: True})


class BOT_102:
Expand Down
3 changes: 2 additions & 1 deletion fireplace/cards/icecrown/rogue.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class ICC_809:

class ICC_811:
"""Lilian Voss"""
play = Morph(FRIENDLY_HAND + SPELL, RandomSpell(card_class=ENEMY_CLASS))
play = Find(ENEMY_HERO - NEUTRAL) & (
Morph(FRIENDLY_HAND + SPELL, RandomSpell(card_class=ENEMY_CLASS)))


class ICC_910:
Expand Down
3 changes: 2 additions & 1 deletion fireplace/cards/kobolds/rogue.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class LOOT_211:
class LOOT_412:
"""Kobold Illusionist"""
# <b>Deathrattle:</b> Summon a 1/1 copy of a minion from your hand.
deathrattle = Summon(CONTROLLER, Buff(RANDOM(FRIENDLY_HAND + MINION), "LOOT_412e"))
deathrattle = Summon(CONTROLLER, RANDOM(FRIENDLY_HAND + MINION)).then(
Buff(Summon.CARD, "LOOT_412e"))


class LOOT_412e:
Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/troll/hunter.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class TRL_065:
"""Zul'jin"""
# [x]<b>Battlecry:</b> Cast all spells you've played this game <i>(targets chosen
# randomly)</i>.
play = CastSpell(CARDS_PLAYED_THIS_GAME + SPELL)
play = CastSpell(Copy(CARDS_PLAYED_THIS_GAME + SPELL))


class TRL_065h:
Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/troll/neutral_epic.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class TRL_535:
"""Snapjaw Shellfighter"""
# [x]Whenever an adjacent minion takes damage, this _minion takes it instead.
events = Predamage(SELF_ADJACENT).on(
Predamage(Predamage.TARGET, 0), Hit(SELF, Predamage.AMOUNT)
Predamage(Predamage.TARGET, 0), Damage(SELF, Predamage.AMOUNT)
)


Expand Down
6 changes: 3 additions & 3 deletions fireplace/cards/troll/rogue.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class TRL_092:
OWN_TURN_BEGIN.on(Unstealth(SELF)),
)
update = (
Refresh(CONTROLLER, {enums.EXTRA_BATTLECRIES: True}),
Refresh(CONTROLLER, {enums.EXTRA_COMBOS: True}),
Refresh(CONTROLLER, {enums.MINION_EXTRA_BATTLECRIES: True}),
Refresh(CONTROLLER, {enums.MINION_EXTRA_COMBOS: True}),
)


Expand All @@ -53,7 +53,7 @@ class TRL_409:
"""Gral, the Shark"""
# [x]<b>Battlecry:</b> Eat a minion in your deck and gain its stats.
# <b>Deathrattle:</b> Add it to your hand.
play = (
play = Find(FRIENDLY_DECK + MINION) & (
Retarget(SELF, RANDOM(FRIENDLY_DECK + MINION)),
Reveal(TARGET),
Destroy(TARGET),
Expand Down
8 changes: 6 additions & 2 deletions fireplace/cards/witchwood/priest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ class GIL_142:
# Each turn this is in your hand, transform it into a card your opponent is holding.
class Hand:
events = OWN_TURN_BEGIN.on(
Morph(SELF, ExactCopy(RANDOM(ENEMY_HAND))).then(Buff(Morph.CARD, "GIL_142e"))
Find(ENEMY_HAND) & (
Morph(SELF, ExactCopy(RANDOM(ENEMY_HAND))).then(Buff(Morph.CARD, "GIL_142e"))
)
)


class GIL_142e:
class Hand:
events = OWN_TURN_BEGIN.on(
Morph(OWNER, ExactCopy(RANDOM(ENEMY_HAND))).then(Buff(Morph.CARD, "GIL_142e"))
Find(ENEMY_HAND) & (
Morph(OWNER, ExactCopy(RANDOM(ENEMY_HAND))).then(Buff(Morph.CARD, "GIL_142e"))
)
)
events = REMOVED_IN_PLAY

Expand Down
2 changes: 1 addition & 1 deletion fireplace/cards/witchwood/shaman.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class GIL_820:
"""Shudderwock"""
# [x]<b>Battlecry:</b> Repeat all other <b>Battlecries</b> from cards you played this
# game <i>(targets chosen randomly)</i>.
play = Battlecry(RANDOM(CARDS_PLAYED_THIS_GAME + BATTLECRITES - SELF) * 30, None)
play = Battlecry(RANDOM(CARDS_PLAYED_THIS_GAME + BATTLECRY - ID("GIL_820")) * 30, None)


##
Expand Down
9 changes: 7 additions & 2 deletions fireplace/dsl/copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ def copy(self, source, entity):
Return a copy of \a entity
"""
log.info("Creating a copy of %r", entity)
return source.controller.card(entity.id, source)
new_entity = source.controller.card(entity.id, source)
if entity.custom_card:
new_entity.custom_card = True
new_entity.create_custom_card = entity.create_custom_card
new_entity.create_custom_card(new_entity)
return new_entity

def evaluate(self, source) -> list[str]:
if isinstance(self.selector, LazyValue):
Expand Down Expand Up @@ -53,7 +58,7 @@ def copy(self, source, entity):
for buff in entity.buffs:
# Recreate the buff stack
new_buff = source.controller.card(buff.id)
new_buff.source = source
new_buff.source = buff.source
attributes = ["atk", "max_health", "_xatk", "_xhealth", "_xcost", "store_card"]
for attribute in attributes:
if hasattr(buff, attribute):
Expand Down
3 changes: 2 additions & 1 deletion fireplace/dsl/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ def check(self, source):
if isinstance(self.selector, Selector):
entities = self.selector.eval(source.game, source)
else:
entities = [self.selector.evaluate(source)]
entity = self.selector.evaluate(source)
entities = [entity] if entity else []
for target in entities:
if target.dead:
return True
Expand Down
1 change: 0 additions & 1 deletion fireplace/dsl/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,6 @@ def CONTROLLED_BY(selector):
BATTLECRY = EnumSelector(GameTag.BATTLECRY)
CHARGE = EnumSelector(GameTag.CHARGE)
COMBO = EnumSelector(GameTag.COMBO)
BATTLECRITES = EnumSelector(GameTag.BATTLECRY)
DAMAGED = EnumSelector(GameTag.DAMAGE)
DEATHRATTLE = EnumSelector(GameTag.DEATHRATTLE)
DIVINE_SHIELD = EnumSelector(GameTag.DIVINE_SHIELD)
Expand Down
3 changes: 2 additions & 1 deletion fireplace/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@
CANT_BE_TARGETED_BY_OP_HERO_POWERS = -23
KEEP_BUFF = -24,
DAMAGED_THIS_TURN = -25
EXTRA_COMBOS = -26
MINION_EXTRA_COMBOS = -26
MINION_EXTRA_BATTLECRIES = -27
3 changes: 2 additions & 1 deletion fireplace/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ class PlayerManager(Manager):
enums.ALWAYS_WINS_BRAWLS: "always_wins_brawls",
enums.CAST_ON_FRIENDLY_MINIONS: "cast_on_friendly_minions",
enums.EXTRA_BATTLECRIES: "extra_battlecries",
enums.EXTRA_COMBOS: "extra_combos",
enums.MINION_EXTRA_BATTLECRIES: "minio_extra_battlecries",
enums.MINION_EXTRA_COMBOS: "minio_extra_combos",
enums.KILLED_THIS_TURN: "killed_this_turn",
enums.DISCARDED: "discarded",
enums.MURLOCS_COST_HEALTH: "murlocs_cost_health",
Expand Down
8 changes: 5 additions & 3 deletions fireplace/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class Player(Entity, TargetableByAuras):
cant_overload = slot_property("cant_overload")
choose_both = slot_property("choose_both")
extra_battlecries = slot_property("extra_battlecries")
extra_combos = slot_property("extra_combos")
minion_extra_battlecries = slot_property("minion_extra_battlecries")
minion_extra_combos = slot_property("minion_extra_combos")
extra_deathrattles = slot_property("extra_deathrattles")
extra_end_turn_effect = slot_property("extra_end_turn_effect")
healing_double = slot_property("healing_double", sum)
Expand Down Expand Up @@ -303,8 +304,9 @@ def draw(self, count=1):
return ret

def give(self, id):
cards = self.game.cheat_action(self, [Give(self, id)])[0]
return cards[0][0]
cards = self.game.cheat_action(self, [Give(self, id)])[0][0]
if len(cards) > 0:
return cards[0]

def concede(self):
ret = self.game.cheat_action(self, [Concede(self)])
Expand Down
42 changes: 42 additions & 0 deletions tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,45 @@ def test_lifesteal_and_auchenai():
game.player1.give("TRL_512").play(target=game.player2.hero)
assert game.player1.hero.health == 29
assert game.player2.hero.health == 29


def test_mirror_entity_and_pumpkin_peasant():
game = prepare_empty_game()
game.player1.give("GIL_201")
game.end_turn()
game.player2.give("EX1_294").play()
game.end_turn()
for _ in range(3):
game.skip_turn()
game.player1.hand[0].play()
minion1 = game.player1.field[0]
minion2 = game.player2.field[0]
assert minion1.id == minion2.id
assert minion1.atk == minion2.atk
assert minion1.health == minion2.health


def test_nefarian_and_ragnaros_hero():
game = prepare_empty_game()
game.end_turn()
game.player2.give("BRM_027").play().destroy()
assert game.player2.hero.card_class == CardClass.NEUTRAL
game.end_turn()
game.player1.give("BRM_030").play()
assert len(game.player1.hand) == 2
assert game.player1.hand[0].id == "BRM_030t"
assert game.player1.hand[0].id == "BRM_030t"


def test_lilian_voss_andragnaros_hero():
game = prepare_empty_game()
game.end_turn()
game.player2.give("BRM_027").play().destroy()
assert game.player2.hero.card_class == CardClass.NEUTRAL
game.end_turn()
game.player1.give(MOONFIRE)
game.player1.give(MOONFIRE)
game.player1.give("ICC_811").play()
assert len(game.player1.hand) == 2
assert game.player1.hand[0].id == MOONFIRE
assert game.player1.hand[0].id == MOONFIRE
Loading

0 comments on commit 83a5c63

Please sign in to comment.