jleclanche / fireplace Goto Github PK
View Code? Open in Web Editor NEWA Hearthstone simulator in Python
Home Page: https://hearthsim.info
License: GNU Affero General Public License v3.0
A Hearthstone simulator in Python
Home Page: https://hearthsim.info
License: GNU Affero General Public License v3.0
While it should only be minions that have taunt.
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 527, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 497, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 150, in DoMove
minion.attack(minion.targets[move[3]])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 368, in attack
self.game.attack(self, target)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 72, in attack
return self.queueActions(source, [Attack(source, target)])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 136, in queueActions
self._processDeaths()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 119, in _processDeaths
self.queueActions(self, actions)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 132, in queueActions
ret.append(action.trigger(source, self))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\actions.py", line 87, in trigger
self.do(source, game, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\actions.py", line 139, in do
target.zone = Zone.GRAVEYARD
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 75, in zone
self._setZone(value)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 518, in _setZone
super()._setZone(value)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 363, in _setZone
super()._setZone(zone)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 181, in _setZone
super()._setZone(zone)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 97, in _setZone
aura.destroy()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 736, in destroy
self.game.auras.remove(self)
ValueError: list.remove(x): x not in list
INFO:root:two ends turn 2
INFO:root:one begins turn 3
INFO:root:one is now at 11 mana crystals
INFO:root:Player(name='one', hero=<Hero ('Jaina Proudmoore')>) triggering <TargetedAction: Draw()> targeting [Player(name='one', hero=<Hero ('Jaina Proudmoore')>)]
INFO:root:one draws <Minion ('Bluegill Warrior')>
DEBUG:root:<Minion ('Bluegill Warrior')> moves from <Zone.DECK: 2> to <Zone.HAND: 3>
INFO:root:<Minion ('Raid Leader')> attacks <Minion ('Faerie Dragon')>
INFO:root:<Minion ('Raid Leader')> triggering <TargetedAction: Damage(amount=3)> targeting [<Minion ('Faerie Dragon')>]
INFO:root:<Minion ('Faerie Dragon')> damaged for 3 health
INFO:root:<Minion ('Faerie Dragon')> triggering <TargetedAction: Damage(amount=3)> targeting [<Minion ('Raid Leader')>]
INFO:root:<Minion ('Raid Leader')> damaged for 3 health
INFO:root:Destroying buff <Enchantment ('Enhanced')> from <Minion ('Raid Leader')>
DEBUG:root:<Enchantment ('Enhanced')> moves from <Zone.PLAY: 1> to <Zone.GRAVEYARD: 4>
INFO:root:<Minion ('Raid Leader')> is removed from the field
INFO:root:<Minion ('Raid Leader')> healed for 3 health
DEBUG:root:<Minion ('Raid Leader')> moves from <Zone.PLAY: 1> to <Zone.GRAVEYARD: 4>
INFO:root:Removing <Aura ('CS2_122e')> affecting [<Minion ('Gurubashi Berserker')>, <Minion ('Frostwolf Warlord')>]
Hi,
Running a test with secretkeeper and seems to run into a CARD_PLAYED error:
game = prepare_game()
secretkeeper = game.player1.give("EX1_080")
secretkeeper.play()
mirror = game.player2.give("CS2_027")
mirror.play()
TypeError: CARD_PLAYED() takes 2 positional arguments but 3 were given.
Commanding shout is an aura. Need to check if it's on the hero.
[13:09:01] <jleclanche> cho on the board
[13:09:16] <jleclanche> opponent warrior plays commanding shout
[13:09:25] <jleclanche> then millhouse
[13:09:32] <jleclanche> you (warlock) play jaraxxus, commanding shout, wisp
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 527, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 497, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 145, in DoMove
card.play()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 283, in play
self.controller.play(self, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 178, in play
return self.game.queueActions(self, [Play(card, target, choose)])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 132, in queueActions
ret.append(action.trigger(source, self))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\actions.py", line 87, in trigger
self.do(source, game, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\actions.py", line 190, in do
source._play(card)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 196, in _play
self.summon(card)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 174, in summon
self.game.queueActions(self, [Summon(self, card)])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 132, in queueActions
ret.append(action.trigger(source, self))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\actions.py", line 235, in trigger
ret.append(self.do(source, game, *extra_args))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\actions.py", line 512, in do
card.summon()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 580, in summon
super().summon()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 371, in summon
super().summon()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 188, in summon
self.action()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 214, in action
self.game.queueActions(self, actions)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 132, in queueActions
ret.append(action.trigger(source, self))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\actions.py", line 235, in trigger
ret.append(self.do(source, game, *extra_args))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\actions.py", line 317, in do
target.draw(card)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 121, in draw
ret = self.game.queueActions(self, [Draw(self) * count])[0]
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\actions.py", line 38, in __mul__
self.times *= value
TypeError: unsupported operand type(s) for *=: 'int' and 'Minion'
INFO:root:one begins turn 11
INFO:root:one is now at 6 mana crystals
INFO:root:Player(name='one', hero=<Hero ('Jaina Proudmoore')>) triggering <TargetedAction: Draw()> targeting [Player(name='one', hero=<Hero ('Jaina Proudmoore')>)]
INFO:root:one draws <Minion ('Gurubashi Berserker')>
DEBUG:root:<Minion ('Gurubashi Berserker')> moves from <Zone.DECK: 2> to <Zone.HAND: 3>
INFO:root:one plays <Minion ('Goldshire Footman')> from their hand
INFO:root:Player(name='one', hero=<Hero ('Jaina Proudmoore')>) triggering <TargetedAction: Summon(card=<Minion ('Goldshire Footman')>)> targeting [Player(name='one', hero=<Hero ('Jaina Proudmoore')>)]
INFO:root:one summons <Minion ('Goldshire Footman')>
INFO:root:Summoning <Minion ('Goldshire Footman')>
DEBUG:root:<Minion ('Goldshire Footman')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
DEBUG:root:<Enchantment ('Enhanced')> moves from <Zone.INVALID: 0> to <Zone.SETASIDE: 6>
INFO:root:Applying <Enchantment ('Enhanced')> to <Minion ('Goldshire Footman')>
DEBUG:root:<Enchantment ('Enhanced')> moves from <Zone.SETASIDE: 6> to <Zone.PLAY: 1>
INFO:root:<Minion ('Raid Leader')> attacks <Hero ('Valeera Sanguinar')>
INFO:root:<Minion ('Raid Leader')> triggering <TargetedAction: Damage(amount=2)> targeting [<Hero ('Valeera Sanguinar')>]
INFO:root:<Hero ('Valeera Sanguinar')> damaged for 2 health
INFO:root:one plays <Minion ('Kobold Geomancer')> from their hand
INFO:root:Player(name='one', hero=<Hero ('Jaina Proudmoore')>) triggering <TargetedAction: Summon(card=<Minion ('Kobold Geomancer')>)> targeting [Player(name='one', hero=<Hero ('Jaina Proudmoore')>)]
INFO:root:one summons <Minion ('Kobold Geomancer')>
INFO:root:Summoning <Minion ('Kobold Geomancer')>
DEBUG:root:<Minion ('Kobold Geomancer')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
DEBUG:root:<Enchantment ('Enhanced')> moves from <Zone.INVALID: 0> to <Zone.SETASIDE: 6>
INFO:root:Applying <Enchantment ('Enhanced')> to <Minion ('Kobold Geomancer')>
DEBUG:root:<Enchantment ('Enhanced')> moves from <Zone.SETASIDE: 6> to <Zone.PLAY: 1>
INFO:root:one plays hero power <HeroPower ('Fireblast')>
INFO:root:<HeroPower ('Fireblast')> triggering <TargetedAction: Hit(amount=1)> targeting [<Hero ('Jaina Proudmoore')>]
INFO:root:<HeroPower ('Fireblast')> triggering <TargetedAction: Damage(amount=1)> targeting [<Hero ('Jaina Proudmoore')>]
INFO:root:<Hero ('Jaina Proudmoore')> damaged for 1 health
INFO:root:one ends turn 11
INFO:root:two begins turn 12
INFO:root:two is now at 6 mana crystals
INFO:root:Player(name='two', hero=<Hero ('Valeera Sanguinar')>) triggering <TargetedAction: Draw()> targeting [Player(name='two', hero=<Hero ('Valeera Sanguinar')>)]
INFO:root:two draws <Minion ('Magma Rager')>
DEBUG:root:<Minion ('Magma Rager')> moves from <Zone.DECK: 2> to <Zone.HAND: 3>
INFO:root:two plays <Minion ('Piloted Shredder')> from their hand
INFO:root:Player(name='two', hero=<Hero ('Valeera Sanguinar')>) triggering <TargetedAction: Summon(card=<Minion ('Piloted Shredder')>)> targeting [Player(name='two', hero=<Hero ('Valeera Sanguinar')>)]
INFO:root:two summons <Minion ('Piloted Shredder')>
INFO:root:Summoning <Minion ('Piloted Shredder')>
DEBUG:root:<Minion ('Piloted Shredder')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:two plays <Minion ("Captain's Parrot")> from their hand
INFO:root:Player(name='two', hero=<Hero ('Valeera Sanguinar')>) triggering <TargetedAction: Summon(card=<Minion ("Captain's Parrot")>)> targeting [Player(name='two', hero=<Hero ('Valeera Sanguinar')>)]
INFO:root:two summons <Minion ("Captain's Parrot")>
INFO:root:Summoning <Minion ("Captain's Parrot")>
DEBUG:root:<Minion ("Captain's Parrot")> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:Activating <Minion ("Captain's Parrot")> action targeting None
INFO:root:<Minion ("Captain's Parrot")> triggering <TargetedAction: ForceDraw(cards=<Selector: DECK FRIENDLY and PIRATE and>)> targeting [Player(name='two', hero=<Hero ('Valeera Sanguinar')>)]
Hi,
I ran the following test:
game = prepare_game()
waraxe = game.player1.give("CS2_106")
waraxe.play()
game.endTurn()
tinker = game.player2.give("GVG_102")
print(tinker.health)
tinker.attack(game.player1.hero)
print(tinker.health)
tinker health is 3 and then 0. It should be 3 and then 3 as player2's minion should not receive damage from player1s weapon. However, the weapon correctly does not lose durability due to the tinker's attack.
Hey,
I think the felcannon has a 2 hit left out.
# Fel Cannon
class GVG_020:
OWN_TURN_END = [Hit(RANDOM_MINION - MECH)]
Thanks!
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['EX1_009', 'CS2_226', 'GVG_064', 'EX1_556', 'CS2_118', 'EX1_586', 'EX1_572', 'NEW1_016', 'EX1_507', 'GVG_111', 'NEW1_040', 'GVG_092', 'EX1_128', 'EX1_561', 'CS2_120', 'NEW1_025', 'GVG_013', 'EX1_015', 'GVG_098', 'CS2_155', 'NEW1_029', 'CS2_181', 'GVG_112', 'GVG_013', 'GVG_107', 'CS2_196', 'EX1_021', 'EX1_043', 'CS2_189', 'GVG_093']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 527, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 497, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 145, in DoMove
card.play()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 277, in play
self.controller.play(self, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 212, in play
self.game.action(PowSubType.PLAY, self, card, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 54, in action
args[0]._play(*args[1:])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 245, in _play
card.action()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 219, in action
func(self, **kwargs)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\cards\classic\neutral_epic.py", line 39, in action
pirates = self.controller.deck.filter(race=Race.PIRATE)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\utils.py", line 35, in filter
return self.__class__(e for k, v in kwargs.items() for e in self if getattr(e, k) == v)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\deck.py", line 15, in __init__
super().__init__(cards or [])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\utils.py", line 35, in <genexpr>
return self.__class__(e for k, v in kwargs.items() for e in self if getattr(e, k) == v)
AttributeError: 'Spell' object has no attribute 'race'
INFO:root:two begins turn 12
INFO:root:two is now at 6 mana crystals
DEBUG:root:<Minion ('Gnomish Experimenter')> moves from <Zone.DECK: 2> to <Zone.HAND: 3>
INFO:root:two draws <Minion ('Gnomish Experimenter')>
INFO:root:two plays <Minion ('Enhance-o Mechano')> from their hand
DEBUG:root:two summons <Minion ('Enhance-o Mechano')>
INFO:root:Summoning <Minion ('Enhance-o Mechano')>
DEBUG:root:<Minion ('Enhance-o Mechano')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:<Minion ('Harvest Golem')> attacks <Hero ('Jaina Proudmoore')>
INFO:root:<Minion ('Harvest Golem')> hits <Hero ('Jaina Proudmoore')> for 2
INFO:root:<Hero ('Jaina Proudmoore')> damaged for 2 health
INFO:root:two plays <Minion ("Captain's Parrot")> from their hand
DEBUG:root:two summons <Minion ("Captain's Parrot")>
INFO:root:Summoning <Minion ("Captain's Parrot")>
DEBUG:root:<Minion ("Captain's Parrot")> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:Activating <Minion ("Captain's Parrot")> action targeting None
In the current model it won't break stealth as stealth is only broken from its owner.
Hey,
Was able to create an infinite loop case using reversing switch and printing attack. Here's the test case:
GOLDSHIRE = "CS1_042"
REVERSE = "PART_006"
game = prepare_game()
minion1 = game.player1.give(GOLDSHIRE)
spell1 = game.player1.give(REVERSE)
minion1.play()
spell1.play(minion1)
print(minion1.atk)
Webspinner FP1_011 in the enUS.xml does not contain an entourage list for its deathrattle, so the random summon will error out on selecting random from an empty list. I think the webspinner needs to generate a list of "collectible" beasts instead.
Knife juggler should not hit when it is summoned. In addition, the potential targets has a typo
# Knife Juggler
class NEW1_019:
def OWN_MINION_SUMMON(self, minion):
if minion is not self :
self.hit(random.choice(self.controller.getTargets(TARGET_ENEMY_CHARACTERS)), 1)
On the same note, mass dispell also has a typo
# Mass Dispel
class EX1_626:
def action(self):
for target in self.controller.getTargets(TARGET_ENEMY_MINIONS):
target.silence()
self.controller.draw()
Hey,
I was testing floating watcher and hit the following error using this test case:
TypeError: <lambda>() takes 3 positional arguments but 4 were given
WATCHER = "GVG_100"
def test_watcher() :
game = prepare_game(WARLOCK,WARLOCK)
watcher = game.player1.give(WATCHER)
watcher.play()
game.endTurn();game.endTurn()
assert(watcher.atk==4)
game.player1.hero.power.play()
assert(watcher.atk==6)
assert(watcher.atk==6)
I think the lambda function requires 4 arguments (aka lambda self, target, amount, source:). Thanks!
Minions with battlecries that target minions can be played without a target if none are present.
def test_empty_shattered() :
game = prepare_game()
shattered = game.player1.give("EX1_019")
shattered.play()
game.endTurn()
However, the following test leads to the error:
AttributeError: 'NoneType' object has no attribute 'buffs'
I think having a target == None check in the utils.py for buffTarget would enable these battlecry minions to be played with an empty target.
I think the druid ancient of war uproot (+5 attack) should be "a" and rooted (+5 health + taunt) should be "b"
Hey,
I was seeing some issues with druid choice cards such as Druid of the Claw (EX1_165). It looks like once you make the choice to like EX1_165b which is a Spell card, you then call MORPH on the spell card. However, Spells do not have the morph attribute only Minions do. I encountered this issue on an earlier commit but I think it should still happen on the latest build. Let me know thanks!
Hi,
I think there may be a few auras that are not implemented yet (not sure if it was intentional). I ran the following code to check for cards with AURA=1 without an associated aura card.
import fireplace.cards
game = prepare_game()
for cardid in fireplace.cards.filter(collectible=True) :
if Card(cardid).aura and not Card(cardid).data.auras:
card = Card(cardid)
print(cardid)
It looks like most are there except for the following :
GVG_095 = Goblin Sapper
EX1_591 = Auchenai Soulpriest
GVG_024 = Cogmaster's Wrench
GVG_122 = Wee Spellstopper
GVG_013 = Cogmaster
It seems like the Soulpriest aura may require some work to rebroadcast DAMAGE instead of HEAL (i.e., infinite death combo with soulpriest + mistress of pain). In addition, "+ spell damage" appears to boost the heal "damage" when this aura is active.
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['GVG_097', 'FP1_024', 'EX1_522', 'EX1_021', 'EX1_067', 'GVG_111', 'EX1_080', 'CS2_222', 'FP1_005', 'EX1_002', 'EX1_009', 'NEW1_041', 'EX1_577', 'CS2_162', 'EX1_089', 'EX1_032', 'CS2_151', 'BRM_007', 'EX1_508', 'EX1_028', 'GVG_095', 'CS2_127', 'GVG_070', 'CS2_151', 'NEW1_017', 'EX1_563', 'EX1_019', 'EX1_110', 'EX1_586', 'EX1_017']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 532, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 502, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 146, in DoMove
card.play()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 277, in play
self.controller.play(self, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 212, in play
self.game.action(PowSubType.PLAY, self, card, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 54, in action
args[0]._play(*args[1:])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 230, in _play
self.summon(card)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 208, in summon
card.summon()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 593, in summon
self.game.broadcast("MINION_SUMMON", self.controller, self)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 177, in broadcast
super().broadcast(event, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\entity.py", line 31, in broadcast
self.broadcast("UPDATE")
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 177, in broadcast
super().broadcast(event, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\entity.py", line 24, in broadcast
f(*args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 181, in UPDATE
aura.update()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 733, in update
if self.isValidTarget(target):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 695, in isValidTarget
return targeting.isValidTarget(self.source, target, requirements=self.requirements)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\targeting.py", line 83, in isValidTarget
if target.race != param:
AttributeError: 'Weapon' object has no attribute 'race'
DEBUG:root:two summons <Enchantment ('Might of Stormwind')>
INFO:root:Summoning <Enchantment ('Might of Stormwind')>
DEBUG:root:<Enchantment ('Might of Stormwind')> moves from <Zone.INVALID: 0> to <Zone.PLAY: 1>
INFO:root:Applying <Enchantment ('Might of Stormwind')> to <Minion ('Sunwalker')>
INFO:root:<Minion ('Stormwind Champion')> attacks <Hero ('Jaina Proudmoore')>
INFO:root:<Minion ('Stormwind Champion')> hits <Hero ('Jaina Proudmoore')> for 6
INFO:root:<Hero ('Jaina Proudmoore')> damaged for 6 health
INFO:root:<Minion ('Goblin Sapper')> attacks <Hero ('Jaina Proudmoore')>
INFO:root:<Minion ('Goblin Sapper')> hits <Hero ('Jaina Proudmoore')> for 3
INFO:root:<Hero ('Jaina Proudmoore')> damaged for 3 health
INFO:root:two plays <Minion ('Grimscale Oracle')> from their hand
DEBUG:root:two summons <Minion ('Grimscale Oracle')>
INFO:root:Summoning <Minion ('Grimscale Oracle')>
DEBUG:root:<Minion ('Grimscale Oracle')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:Summoning Aura <fireplace.card.Aura object at 0x0000000004D319B0>
DEBUG:root:two summons <Enchantment ('Might of Stormwind')>
INFO:root:Summoning <Enchantment ('Might of Stormwind')>
DEBUG:root:<Enchantment ('Might of Stormwind')> moves from <Zone.INVALID: 0> to <Zone.PLAY: 1>
INFO:root:Applying <Enchantment ('Might of Stormwind')> to <Minion ('Grimscale Oracle')>
Lightwell needs a targets empty check so that you do not random.choice with none.
# Lightwell
class EX1_341:
def OWN_TURN_BEGIN(self):
targets = [t for t in self.controller.getTargets(TARGET_FRIENDLY_CHARACTERS) if t.damage]
if targets :
self.heal(random.choice(targets), 3)
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['EX1_412', 'GVG_089', 'GVG_074', 'GVG_117', 'EX1_004', 'GVG_121', 'GVG_110', 'GVG_079', 'CS2_117', 'EX1_145', 'BRM_030', 'EX1_043', 'EX1_390', 'CS2_213', 'GVG_022', 'EX1_004', 'GVG_090', 'EX1_043', 'CS2_227', 'EX1_005', 'EX1_562', 'GVG_109', 'EX1_032', 'GVG_090', 'EX1_028', 'FP1_008', 'CS2_146', 'GVG_084', 'EX1_007', 'CS2_197']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 537, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 507, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 142, in DoMove
self.game.endTurn()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 153, in endTurn
self.broadcast("TURN_END", self.currentPlayer)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 177, in broadcast
super().broadcast(event, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\entity.py", line 24, in broadcast
f(*args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 211, in TURN_END
player.broadcast("OWN_TURN_END")
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 265, in broadcast
super().broadcast(event, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\entity.py", line 24, in broadcast
f(*args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 60, in <lambda>
_func = lambda *args: func(self, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\cards\classic\neutral_rare.py", line 16, in OWN_TURN_END
target.buff("EX1_004e")
TypeError: buff() missing 1 required positional argument: 'buff'
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['EX1_399', 'EX1_506', 'EX1_508', 'CS2_075', 'NEW1_017', 'EX1_562', 'EX1_112', 'BRM_008', 'CS2_146', 'GVG_102', 'CS2_221', 'CS2_077', 'NEW1_024', 'EX1_509', 'GVG_078', 'EX1_004', 'EX1_405', 'CS2_182', 'GVG_090', 'GVG_081', 'EX1_144', 'GVG_044', 'EX1_522', 'EX1_405', 'GVG_006', 'GVG_023', 'GVG_082', 'GVG_095', 'EX1_595', 'CS2_182']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 527, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 497, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 147, in DoMove
card.play(target=card.targets[move[3]])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 277, in play
self.controller.play(self, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 212, in play
self.game.action(PowSubType.PLAY, self, card, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 54, in action
args[0]._play(*args[1:])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 245, in _play
card.action()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 219, in action
func(self, **kwargs)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\cards\utils.py", line 35, in <lambda>
bounceTarget = lambda self, target: target.bounce()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 544, in bounce
self.zone = Zone.HAND
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 87, in zone
self._setZone(value)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 530, in _setZone
aura.destroy()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 747, in destroy
logging.info("Removing %r affecting %r" % (self, self._buffed))
AttributeError: 'Aura' object has no attribute '_buffed'
INFO:root:two begins turn 20
INFO:root:two is now at 10 mana crystals
DEBUG:root:<Minion ('Madder Bomber')> moves from <Zone.DECK: 2> to <Zone.HAND: 3>
INFO:root:two draws <Minion ('Madder Bomber')>
INFO:root:two plays <Minion ('Grimscale Oracle')> from their hand
DEBUG:root:two summons <Minion ('Grimscale Oracle')>
INFO:root:Summoning <Minion ('Grimscale Oracle')>
DEBUG:root:<Minion ('Grimscale Oracle')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:Summoning Aura <fireplace.card.Aura object at 0x00000000047ADDD8>
INFO:root:two plays hero power <HeroPower ('Dagger Mastery')>
INFO:root:Activating <HeroPower ('Dagger Mastery')> action targeting None
DEBUG:root:two summons <Weapon ('Wicked Knife')>
INFO:root:Summoning <Weapon ('Wicked Knife')>
DEBUG:root:<Weapon ('Wicked Knife')> moves from <Zone.INVALID: 0> to <Zone.PLAY: 1>
INFO:root:two plays <Minion ('Madder Bomber')> from their hand
DEBUG:root:two summons <Minion ('Madder Bomber')>
INFO:root:Summoning <Minion ('Madder Bomber')>
DEBUG:root:<Minion ('Madder Bomber')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:<Minion ('Southsea Deckhand')> attacks <Minion ('Booty Bay Bodyguard')>
INFO:root:<Minion ('Southsea Deckhand')> hits <Minion ('Booty Bay Bodyguard')> for 2
INFO:root:<Minion ('Booty Bay Bodyguard')> damaged for 2 health
INFO:root:<Minion ('Booty Bay Bodyguard')> hits <Minion ('Southsea Deckhand')> for 5
INFO:root:<Minion ('Southsea Deckhand')> damaged for 5 health
INFO:root:<Minion ('Booty Bay Bodyguard')> dies
INFO:root:<Minion ('Booty Bay Bodyguard')> is removed from the field
INFO:root:<Minion ('Booty Bay Bodyguard')> healed for 4 health
DEBUG:root:<Minion ('Booty Bay Bodyguard')> moves from <Zone.PLAY: 1> to <Zone.GRAVEYARD: 4>
INFO:root:<Minion ('Southsea Deckhand')> dies
INFO:root:<Minion ('Southsea Deckhand')> is removed from the field
INFO:root:<Minion ('Southsea Deckhand')> healed for 5 health
DEBUG:root:<Minion ('Southsea Deckhand')> moves from <Zone.PLAY: 1> to <Zone.GRAVEYARD: 4>
INFO:root:two plays <Minion ('Patient Assassin')> from their hand
DEBUG:root:two summons <Minion ('Patient Assassin')>
INFO:root:Summoning <Minion ('Patient Assassin')>
DEBUG:root:<Minion ('Patient Assassin')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:two plays <Spell ('Time Rewinder')> from their hand
DEBUG:root:two summons <Spell ('Time Rewinder')>
INFO:root:Summoning <Spell ('Time Rewinder')>
DEBUG:root:<Spell ('Time Rewinder')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:Activating <Spell ('Time Rewinder')> action targeting <Minion ('Grimscale Oracle')>
INFO:root:<Minion ('Grimscale Oracle')> is bounced back to two's hand
INFO:root:<Minion ('Grimscale Oracle')> is removed from the field
Hi, I am new to your code but I am having some issues getting the attack from enrages from showing up. For example, I was creating an Amani Berserker (CardID=EX1_393) for player1 and player2 and having one attack the other.
game = prepare_game(WARLOCK, WARLOCK)
amani1 = game.currentPlayer.give("EX1_393")
amani1.play()
game.currentPlayer.field.append(amani1)
game.endTurn()
amani2 = game.currentPlayer.give("EX1_393")
amani2.play()
game.currentPlayer.field.append(amani2)
game.endTurn()
print(amani2.atk,amani2.extraAtk,amani2.health)
>> 2 0 3
amani1.attack(amani2)
print(amani2.atk,amani2.extraAtk,amani2.health)
>> 2 0 1
print(amani2.slots)
>> [<Enrage ('Enrage Buff')>]
game.endTurn()
I would have expected the amani2.extraAtk to pick up the Atk=3 in the Enrage class.
Hi,
I am currently running the following test case as I was hitting some issues with aura removes. In the test case, I created two Timber Wolfs for player1 and had player2 moonfire both.
game = prepare_game()
timber1 = game.player1.give("DS1_175")
timber2 = game.player1.give("DS1_175")
timber1.play()
timber2.play()
game.endTurn();
moonfire1 = game.player2.give("CS2_008")
moonfire2 = game.player2.give("CS2_008")
print([card.atk for card in game.player1.field])
moonfire1.play(timber1)
print([card.atk for card in game.player1.field])
moonfire2.play(timber2)
During the second moonfire, I get a ValueError during the aura destroy. Currently trying to see if I can characterize the error further. Let me know if you need more information or if I may have set up the test case incorrectly. Thanks!
./full_game.py
Traceback (most recent call last):
File "./full_game.py", line 48, in <module>
main()
File "./full_game.py", line 11, in main
deck1 = randomDraft(hero=fireplace.heroes.MAGE)
AttributeError: 'module' object has no attribute 'heroes'
I'm submitting a pull request that fixes these problems. The test now runs for 5 turns before throwing this exception. (I'm brand new to the codebase - haven't dug deeper.)
Traceback (most recent call last):
File "full_game.py", line 53, in <module>
main()
File "full_game.py", line 49, in main
gm.endTurn()
File "../fireplace/game.py", line 186, in endTurn
self.broadcast("TURN_END", self.currentPlayer)
File "../fireplace/game.py", line 209, in broadcast
super().broadcast(event, *args)
File "../fireplace/entity.py", line 24, in broadcast
f(*args)
File "../fireplace/game.py", line 231, in TURN_END
player.broadcast("OWN_TURN_END")
File "../fireplace/player.py", line 260, in broadcast
super().broadcast(event, *args)
File "../fireplace/entity.py", line 24, in broadcast
f(*args)
File "../fireplace/card.py", line 66, in _func
self.game.queueActions(self, actions)
File "../fireplace/game.py", line 138, in queueActions
action.trigger(source, self)
File "../fireplace/actions.py", line 31, in trigger
targets = self.eval(self.target, source, game)
File "../fireplace/actions.py", line 28, in eval
return selector.eval(game, source)
File "../fireplace/targeting.py", line 156, in eval
result += [e for e in entities if self.test(e, source)]
File "../fireplace/targeting.py", line 156, in <listcomp>
result += [e for e in entities if self.test(e, source)]
File "../fireplace/targeting.py", line 202, in test
op(self, stack)
File "../fireplace/targeting.py", line 211, in _and
b = stack.pop()
IndexError: pop from empty list
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['NEW1_022', 'EX1_616', 'EX1_170', 'CS2_119', 'EX1_144', 'GVG_093', 'FP1_001', 'EX1_025', 'GVG_090', 'NEW1_019', 'EX1_507', 'BRM_008', 'GVG_079', 'EX1_131', 'FP1_017', 'GVG_115', 'CS2_186', 'BRM_008', 'CS2_141', 'CS2_221', 'FP1_009', 'EX1_066', 'CS2_142', 'CS2_186', 'CS2_074', 'GVG_075', 'BRM_025', 'EX1_283', 'CS2_131', 'EX1_509']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 530, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 500, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 144, in DoMove
card.play()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 274, in play
self.controller.play(self, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 204, in play
self.game.action(PowSubType.PLAY, self, card, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 54, in action
args[0]._play(*args[1:])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 237, in _play
card.action()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 219, in action
func(self, **kwargs)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\cards\classic\rogue.py", line 52, in action
self.buff(self.controller.weapon, "CS2_074e")
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 148, in buff
ret.apply(target)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 651, in apply
if target.type == CardType.WEAPON and getattr(self, "durability", 0):
AttributeError: 'NoneType' object has no attribute 'type'
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['CS2_187', 'PRO_001', 'NEW1_037', 'EX1_043', 'EX1_009', 'EX1_283', 'GVG_091', 'CS2_173', 'EX1_096', 'NEW1_027', 'EX1_020', 'CS2_125', 'FP1_007', 'EX1_103', 'EX1_562', 'FP1_009', 'EX1_062', 'CS2_161', 'GVG_109', 'FP1_003', 'GVG_084', 'BRM_007', 'CS2_233', 'EX1_032', 'EX1_506', 'GVG_024', 'EX1_616', 'GVG_104', 'BRM_022', 'EX1_508']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 527, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 497, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 135, in DoMove
self.game.endTurn()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 153, in endTurn
self.broadcast("TURN_END", self.currentPlayer)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 177, in broadcast
super().broadcast(event, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\entity.py", line 24, in broadcast
f(*args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 211, in TURN_END
player.broadcast("OWN_TURN_END")
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 273, in broadcast
super().broadcast(event, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\entity.py", line 24, in broadcast
f(*args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 60, in <lambda>
_func = lambda *args: func(self, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\cards\classic\neutral_rare.py", line 186, in OWN_TURN_END
self.buff(target, "NEW1_037e")
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 147, in buff
ret = self.controller.summon(buff)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 205, in summon
card = self.game.card(card)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 100, in card
card = Card(id)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 29, in Card
return subclass(id, data)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 640, in __init__
super().__init__(*args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 51, in __init__
self.tags.update(data.tags)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\managers.py", line 32, in update
if self.map[k]:
KeyError: <GameTag.Collectible: 321>
DEBUG:root:two summons <Minion ('Nerubian Egg')>
INFO:root:Summoning <Minion ('Nerubian Egg')>
DEBUG:root:<Minion ('Nerubian Egg')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:two plays <Minion ('Loot Hoarder')> from their hand
DEBUG:root:two summons <Minion ('Loot Hoarder')>
INFO:root:Summoning <Minion ('Loot Hoarder')>
DEBUG:root:<Minion ('Loot Hoarder')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:two plays <Minion ('Twilight Drake')> from their hand
DEBUG:root:two summons <Minion ('Twilight Drake')>
INFO:root:Summoning <Minion ('Twilight Drake')>
DEBUG:root:<Minion ('Twilight Drake')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:Activating <Minion ('Twilight Drake')> action targeting None
DEBUG:root:two summons <Enchantment ('Hour of Twilight')>
INFO:root:Summoning <Enchantment ('Hour of Twilight')>
DEBUG:root:<Enchantment ('Hour of Twilight')> moves from <Zone.INVALID: 0> to <Zone.PLAY: 1>
INFO:root:Applying <Enchantment ('Hour of Twilight')> to <Minion ('Twilight Drake')>
DEBUG:root:two summons <Enchantment ('Hour of Twilight')>
INFO:root:Summoning <Enchantment ('Hour of Twilight')>
DEBUG:root:<Enchantment ('Hour of Twilight')> moves from <Zone.INVALID: 0> to <Zone.PLAY: 1>
INFO:root:Applying <Enchantment ('Hour of Twilight')> to <Minion ('Twilight Drake')>
DEBUG:root:two summons <Enchantment ('Hour of Twilight')>
INFO:root:Summoning <Enchantment ('Hour of Twilight')>
DEBUG:root:<Enchantment ('Hour of Twilight')> moves from <Zone.INVALID: 0> to <Zone.PLAY: 1>
INFO:root:Applying <Enchantment ('Hour of Twilight')> to <Minion ('Twilight Drake')>
INFO:root:two plays <Minion ('Master Swordsmith')> from their hand
DEBUG:root:two summons <Minion ('Master Swordsmith')>
INFO:root:Summoning <Minion ('Master Swordsmith')>
DEBUG:root:<Minion ('Master Swordsmith')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:<Minion ('Flying Machine')> attacks <Hero ('Jaina Proudmoore')>
INFO:root:<Minion ('Flying Machine')> hits <Hero ('Jaina Proudmoore')> for 1
INFO:root:<Hero ('Jaina Proudmoore')> damaged for 1 health
INFO:root:two ends turn
Hey,
I get the following error playing Animal Companion (NEW1_031):
File "C:\Python34\lib\site-packages\fireplace-0.1-py3.4.egg\fireplace\cards\classic\hunter.py", line 120, in action
self.controller.summon(random.choice(self.entourage))
AttributeError: 'Spell' object has no attribute 'entourage'
Seems like entourage cards are there in the xml files.
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['NEW1_004', 'EX1_033', 'CS2_147', 'GVG_091', 'EX1_096', 'EX1_126', 'PRO_001', 'NEW1_041', 'EX1_085', 'GVG_108', 'EX1_396', 'EX1_562', 'GVG_113', 'EX1_025', 'BRM_019', 'GVG_047', 'EX1_059', 'EX1_009', 'FP1_028', 'CS2_155', 'EX1_581', 'GVG_024', 'GVG_084', 'EX1_059', 'EX1_393', 'GVG_097', 'EX1_067', 'tt_004', 'NEW1_021', 'EX1_009']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 538, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 508, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 155, in DoMove
card.play(target=card.targets[move[3]])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 277, in play
self.controller.play(self, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 212, in play
self.game.action(PowSubType.PLAY, self, card, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 54, in action
args[0]._play(*args[1:])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 245, in _play
card.action()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 219, in action
func(self, **kwargs)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\cards\classic\neutral_legendary.py", line 222, in action
target.damage(4)
TypeError: 'int' object is not callable
INFO:root:two begins turn 16
INFO:root:two is now at 8 mana crystals
DEBUG:root:<Minion ('Doomsayer')> moves from <Zone.DECK: 2> to <Zone.HAND: 3>
INFO:root:two draws <Minion ('Doomsayer')>
INFO:root:two plays <Minion ('Arcane Nullifier X-21')> from their hand
DEBUG:root:two summons <Minion ('Arcane Nullifier X-21')>
INFO:root:Summoning <Minion ('Arcane Nullifier X-21')>
DEBUG:root:<Minion ('Arcane Nullifier X-21')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:two plays <Spell ('Rogues Do It...')> from their hand
DEBUG:root:two summons <Spell ('Rogues Do It...')>
INFO:root:Summoning <Spell ('Rogues Do It...')>
DEBUG:root:<Spell ('Rogues Do It...')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:Activating <Spell ('Rogues Do It...')> action targeting <Hero ('Jaina Proudmoore')>
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['FP1_031', 'CS2_171', 'EX1_093', 'FP1_007', 'NEW1_016', 'EX1_017', 'EX1_283', 'GVG_093', 'GVG_094', 'GVG_108', 'tt_004', 'CS2_118', 'CS2_146', 'FP1_024', 'CS2_072', 'FP1_014', 'GVG_116', 'EX1_562', 'BRM_026', 'CS2_222', 'CS2_227', 'GVG_025', 'EX1_062', 'EX1_014', 'GVG_099', 'GVG_097', 'CS2_169', 'BRM_025', 'EX1_023', 'EX1_043']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 532, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 502, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 146, in DoMove
card.play()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 277, in play
self.controller.play(self, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 204, in play
self.game.action(PowSubType.PLAY, self, card, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 54, in action
args[0]._play(*args[1:])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 237, in _play
card.action()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 219, in action
func(self, **kwargs)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\cards\classic\neutral_epic.py", line 41, in action
self.controller.draw(random.choice(pirates))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 149, in draw
count -= 1
TypeError: unsupported operand type(s) for -=: 'Minion' and 'int'
DEBUG:root:two summons <Weapon ('Wicked Knife')>
INFO:root:Summoning <Weapon ('Wicked Knife')>
DEBUG:root:<Weapon ('Wicked Knife')> moves from <Zone.INVALID: 0> to <Zone.PLAY: 1>
INFO:root:<Weapon ('Wicked Knife')> dies
DEBUG:root:<Weapon ('Wicked Knife')> moves from <Zone.PLAY: 1> to <Zone.GRAVEYARD: 4>
INFO:root:<Hero ('Valeera Sanguinar')> attacks <Hero ('Jaina Proudmoore')>
INFO:root:<Weapon ('Wicked Knife')> loses 1 point of durability
INFO:root:<Hero ('Valeera Sanguinar')> hits <Hero ('Jaina Proudmoore')> for 1
INFO:root:<Hero ('Jaina Proudmoore')> damaged for 1 health
INFO:root:two plays <Minion ('Jeeves')> from their hand
DEBUG:root:two summons <Minion ('Jeeves')>
INFO:root:Summoning <Minion ('Jeeves')>
DEBUG:root:<Minion ('Jeeves')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:two plays <Minion ("Captain's Parrot")> from their hand
DEBUG:root:two summons <Minion ("Captain's Parrot")>
INFO:root:Summoning <Minion ("Captain's Parrot")>
DEBUG:root:<Minion ("Captain's Parrot")> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
INFO:root:Activating <Minion ("Captain's Parrot")> action targeting None
DEBUG:root:<Minion ('Southsea Deckhand')> moves from <Zone.DECK: 2> to <Zone.HAND: 3>
INFO:root:two draws <Minion ('Southsea Deckhand')>
I used brewmaster to re-play my Iron Juggernaut earlier in the game. My opponent used far sight and drew 2 burrowing mines (on the same draw), giving me lethal and what would have won me the game. Instead I am sitting here waiting for my win, haha.
Hey,
I'll look into joining the irc channel. I was running the following test and hit "AssertionError: Zone.GRAVEYARD". The error looks like it has to do with the zone assertion in the adjacentMinions function.
game = prepare_game()
dire1 = game.player1.give("EX1_162")
dire2 = game.player1.give("EX1_162")
dire1.play()
dire2.play()
game.endTurn();
yeti = game.player2.give("GVG_078")
yeti.play()
yeti.attack(dire2)
Interestingly enough, if the yeti attack dire1, the assert is not triggered.
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['CS2_182', 'CS2_118', 'GVG_067', 'GVG_071', 'CS2_119', 'EX1_509', 'BRM_007', 'GVG_025', 'EX1_008', 'BRM_028', 'EX1_059', 'GVG_013', 'EX1_009', 'EX1_134', 'EX1_021', 'NEW1_004', 'GVG_084', 'GVG_013', 'EX1_563', 'EX1_080', 'GVG_103', 'NEW1_040', 'GVG_082', 'CS2_131', 'CS2_161', 'EX1_067', 'CS2_226', 'EX1_017', 'GVG_089', 'GVG_016']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 530, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 500, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 145, in DoMove
card.play()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 277, in play
self.controller.play(self, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 212, in play
self.game.action(PowSubType.PLAY, self, card, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 54, in action
args[0]._play(*args[1:])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 230, in _play
self.summon(card)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 208, in summon
card.summon()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 593, in summon
self.game.broadcast("MINION_SUMMON", self.controller, self)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 177, in broadcast
super().broadcast(event, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\entity.py", line 24, in broadcast
f(*args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 342, in MINION_SUMMON
minion.controller.broadcast("OWN_MINION_SUMMON", minion)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 273, in broadcast
super().broadcast(event, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\entity.py", line 24, in broadcast
f(*args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 60, in <lambda>
_func = lambda *args: func(self, *args)
TypeError: OWN_MINION_SUMMON() missing 1 required positional argument: 'minion'
INFO:root:two begins turn 12
INFO:root:two is now at 6 mana crystals
DEBUG:root:<Minion ('Cogmaster')> moves from <Zone.DECK: 2> to <Zone.HAND: 3>
INFO:root:two draws <Minion ('Cogmaster')>
INFO:root:<Minion ('Frostwolf Warlord')> attacks <Minion ('Raid Leader')>
INFO:root:<Minion ('Frostwolf Warlord')> hits <Minion ('Raid Leader')> for 6
INFO:root:<Minion ('Raid Leader')> damaged for 6 health
INFO:root:<Minion ('Raid Leader')> hits <Minion ('Frostwolf Warlord')> for 2
INFO:root:<Minion ('Frostwolf Warlord')> damaged for 2 health
INFO:root:<Minion ('Raid Leader')> dies
INFO:root:<Minion ('Raid Leader')> is removed from the field
INFO:root:Removing <fireplace.card.Aura object at 0x00000000065E4080> affecting [<Minion ('Darkscale Healer')>]
INFO:root:Destroying buff <Enchantment ('Enhanced')> from <Minion ('Darkscale Healer')>
INFO:root:<Minion ('Raid Leader')> healed for 6 health
DEBUG:root:<Minion ('Raid Leader')> moves from <Zone.PLAY: 1> to <Zone.GRAVEYARD: 4>
INFO:root:two plays <Minion ('One-eyed Cheat')> from their hand
DEBUG:root:two summons <Minion ('One-eyed Cheat')>
INFO:root:Summoning <Minion ('One-eyed Cheat')>
DEBUG:root:<Minion ('One-eyed Cheat')> moves from <Zone.HAND: 3> to <Zone.PLAY: 1>
https://www.reddit.com/r/hearthstone/comments/207lvz/truesilver_champion_explosive_trap_bug_fixed/
You no longer heal twice with Truesilver when running into an explosive trap. You do still go down to 0 and then go back up to 2 health, but your attack isn't cancelled so you don't heal a second time.
Confirmed by Xinhuan
Deck 1: ['EX1_508', 'CS2_226', 'CS2_142', 'EX1_011', 'CS1_042', 'EX1_011', 'CS2_197', 'EX1_399', 'CS2_173', 'CS2_023', 'CS1_042', 'CS2_122', 'CS2_120', 'DS1_055', 'CS2_162', 'CS2_187', 'CS2_120', 'CS2_141', 'DS1_055', 'CS2_032', 'CS2_127', 'CS2_029', 'CS2_173', 'EX1_399', 'EX1_066', 'EX1_508', 'CS2_026', 'CS2_122', 'CS2_171', 'CS2_187']
Deck 2: ['CS2_074', 'NEW1_023', 'EX1_059', 'CS2_117', 'CS2_189', 'FP1_008', 'EX1_564', 'EX1_128', 'EX1_126', 'CS2_120', 'GVG_013', 'CS2_169', 'GVG_067', 'EX1_145', 'CS2_073', 'EX1_561', 'CS2_161', 'CS2_169', 'FP1_016', 'EX1_048', 'CS2_124', 'CS2_196', 'BRM_019', 'CS2_161', 'FP1_024', 'GVG_102', 'FP1_001', 'EX1_100', 'CS2_172', 'EX1_029']
Traceback (most recent call last):
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 530, in UCTPlayGame
m = UCT(rootstate = state, seconds = 10, verbose = False)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 500, in UCT
state.DoMove(random.choice(state.GetMoves()))
File "C:\Users\Ragowit\Documents\GitHub\fireplace\mcts\uct.py", line 145, in DoMove
card.play()
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 277, in play
self.controller.play(self, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 212, in play
self.game.action(PowSubType.PLAY, self, card, target, choose)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 54, in action
args[0]._play(*args[1:])
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\player.py", line 220, in _play
self.game.broadcast("CARD_PLAYED", self, card)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\game.py", line 177, in broadcast
super().broadcast(event, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\entity.py", line 24, in broadcast
f(*args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\card.py", line 60, in <lambda>
_func = lambda *args: func(self, *args)
File "C:\Users\Ragowit\Documents\GitHub\fireplace\fireplace\cards\gvg\neutral_common.py", line 19, in CARD_PLAYED
self.buff("GVG_067a")
TypeError: buff() missing 1 required positional argument: 'buff'
INFO:root:one begins turn 25
INFO:root:one is now at 11 mana crystals
DEBUG:root:<Spell ('Frost Nova')> moves from <Zone.DECK: 2> to <Zone.HAND: 3>
INFO:root:one draws <Spell ('Frost Nova')>
INFO:root:one plays hero power <HeroPower ('Fireblast')>
INFO:root:Activating <HeroPower ('Fireblast')> action targeting <Minion ('Alexstrasza')>
INFO:root:<HeroPower ('Fireblast')> hits <Minion ('Alexstrasza')> for 1
INFO:root:<Minion ('Alexstrasza')> damaged for 1 health
INFO:root:<Minion ('Voodoo Doctor')> attacks <Minion ('Alexstrasza')>
INFO:root:<Minion ('Voodoo Doctor')> hits <Minion ('Alexstrasza')> for 2
INFO:root:<Minion ('Alexstrasza')> damaged for 2 health
INFO:root:<Minion ('Alexstrasza')> hits <Minion ('Voodoo Doctor')> for 8
INFO:root:<Minion ('Voodoo Doctor')> damaged for 8 health
INFO:root:<Minion ('Voodoo Doctor')> dies
INFO:root:<Minion ('Voodoo Doctor')> is removed from the field
INFO:root:<Minion ('Voodoo Doctor')> healed for 8 health
DEBUG:root:<Minion ('Voodoo Doctor')> moves from <Zone.PLAY: 1> to <Zone.GRAVEYARD: 4>
INFO:root:<Minion ('Alexstrasza')> dies
INFO:root:<Minion ('Alexstrasza')> is removed from the field
INFO:root:<Minion ('Alexstrasza')> healed for 10 health
DEBUG:root:<Minion ('Alexstrasza')> moves from <Zone.PLAY: 1> to <Zone.GRAVEYARD: 4>
INFO:root:one plays <Spell ('Frost Nova')> from their hand
[16:33:53] Xinhuan: did u remember the thread about how silence works on a minion that had been crazed alchemist and took damage?
[16:34:03] Xinhuan: and how the current HP gets adjusted
[16:35:15] Xinhuan: for example, a 2/5 gets swapped to a 5/2, takes 1 damage becomes a 5/1, if its silenced then, it becomes a 2/4
Hey,
The new tag push seems to be pretty good although I hit a few minor issues during my testing. Below, I posted some quick fixes that seemed to make my code work again as a couple of the attributes seem to be missing in the latest commit:
In card.py, the Character class should probably be initialized with self.numAttacks = 0 (hit a few errors not finding that attribute during Minion attacks). The BaseCard class should probably have self.secret = False (secretkeeper will error when a non-secret was played)
In player.py the Player class should probably be initialized with self.usedMana = 0, self.combo = False, self.minionsPlayedThisTurn = 0.
In targeting.py, I was hitting an issue where a weapon's race was being checked so maybe checking that the 'race' attribute is available or the target is a Minion before checking for race is needed.
In cards/utils.py, healHero(amount) should be applied to self.controller.hero rather than hero.
In cards/classic/druid.py, the buffSelf(self, "**")
should be changed to buffSelf("**")
for Claw and Bite; and replace character to target in self.hit(target,5) in Starfire.
In cards/classic/warrior.py, the Frothing Beserker action should be OWN_DAMAGE not DAMAGE
In cards/gvg/hunter.py, metaltooth leaper is buffing all entities, should only do mechs
def action(self) :
for minion in self.controller.field:
if minion is not self and minion.race == Race.MECHANICAL :
self.buff(minion, "GVG_048e")
I also implemented a few cards (probably not in the most ideal way), so if you would like to use them as a starting point, please feel free:
# Repentance
class EX1_379e:
HEALTH = lambda i: 1
# Call Pet
class GVG_017:
def action(self):
card = self.controller.draw()
if card.type == CardType.MINION and card.race == Race.BEAST :
self.buff(card, "GVG_017e")
Missing buff for call pet
GVG_017e = {
GameTag.CARDNAME: "Call Pet Buff",
GameTag.CARDTYPE: CardType.ENCHANTMENT,
GameTag.COST: -4,
}
# Tinkertown Technician
class GVG_102:
def action(self):
if self.poweredUp:
self.buff(self, "GVG_102e")
self.controller.give(random.choice(self.data.entourage))
from ..utils import *
##
# Minions
# Goblin Auto-Barber
class GVG_023:
def action(self):
if self.controller.hero.weapon:
self.buff(self.controller.hero.weapon, "GVG_023a")
# One-eyed Cheat
class GVG_025:
def OWN_MINION_SUMMON(self, minion):
if minion.race == Race.PIRATE:
self.stealthed = True
# Iron Sensei
class GVG_027:
def OWN_TURN_END(self):
own_mechs = [minion for minion in self.controller.field if minion.race == Race.MECHANICAL]
if own_mechs :
self.buff(random.choice(own_mechs),"GVG_027e")
# Trade Prince Gallywix
class GVG_028:
def CARD_PLAYED(self, player, card):
if player == self.controller.opponent and card.type == CardType.SPELL:
self.controller.give(card.id)
player.give("GVG_028t")
# Gallywix's Coin
class GVG_028t:
def action(self):
self.controller.tempMana += 1
##
# Spells
# Sabotage
class GVG_047:
def action(self):
if self.controller.opponent.field :
random.choice(self.controller.opponent.field).destroy()
def combo(self):
if self.controller.opponent.field :
random.choice(self.controller.opponent.field).destroy()
if self.controller.opponent.hero.weapon:
self.controller.opponent.hero.weapon.destroy()
# Tinker's Sharpsword Oil
class GVG_022:
def action(self):
if self.controller.hero.weapon :
self.buff(self.controller.hero.weapon, "GVG_022a")
def combo(self):
if self.controller.hero.weapon :
self.buff(self.controller.hero.weapon, "GVG_022a")
if self.controller.field :
self.buff(random.choice(self.controller.field), "GVG_022b")
which required these additions in buffs.py
# Iron Sensei
GVG_027e = {
GameTag.ATK: 2,
GameTag.HEALTH: 2
}
# Tinker's Sharpsword Oil
GVG_022a = buff(atk=3)
GVG_022b = buff(atk=3)
# Goblin Auto-Barber
GVG_023a = buff(atk=1)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.