DSLs, Stove and The Grand Tournament
Another very busy week in Fireplace! New contributor @beheh is joining us and already contributed dozens of new tests.
Part of that work involved implementing an easy way to create an “empty” game which would start with empty decks and prevent fatigue. This allows for easily testing draw-based events such as Malorne.
The Grand Tournament
A new expansion has been announced! With a new keyword: Inspire!
Well, turns out the INSPIRE
GameTag was already in the game and all I had to do was
implement it.
So that’s done. Most of the announced cards are done, as far as non-static data goes anyway.
DSL changes
Contributed by @zakum42, the RandomNumber LazyNum which allows for elegantly implementing cards such as Lightning Storm:
play = Hit(ENEMY_MINIONS, RandomNumber(2, 3))
The Attr()
LazyNum has gained comparison capabilities, which turn it into an
Evaluator. This can be used to implement cards which behave differently based
on the total of an attribute, such as Mortal Strike:
play = (Attr(FRIENDLY_HERO, "health") <= 12) & Hit(TARGET, 6) | Hit(TARGET, 4)
The ExactCopy()
picker has been implemented.
It functionally works like Copy()
, but recreates buffs, tags etc.
Faceless Manipulator
is very elegant:
play = Morph(SELF, ExactCopy(TARGET))
The Counter()
action, used by Counterspell,
has been implemented
as well. As it turns out, all it does is set a CANT_PLAY
tag on the card, which
prevents its play action from triggering.
The Wild Pyromancer interaction
does not happen like in Hearthstone, however, so that will have to be fixed.
events = Play(OPPONENT, SPELL).on(Counter(Play.Args.CARD), Reveal(SELF))
Another new action: UnlockOverload()
, for Lava Shock.
Not much to say about that one.
There were two important organizational cleanups regarding the DSL. The first one that hit was moving it to fireplace.dsl. This forced clearing up some vocabulary on what is an Evaluator, a Picker etc. Everything is available from the root of the module, but it’s now subdivided like this:
-
fireplace.dsl.evaluator
:Evaluator
,Dead()
,Find()
-
fireplace.dsl.lazynum
:LazyNum
andLazyNumEvaluator
,Attr()
,Count()
,RandomNumber()
-
fireplace.dsl.picker
:Picker
,Copy()
,ExactCopy()
,RandomCardPicker()
-
fireplace.dsl.selector
: All the selectors and their logic
The other significant cleanup was
getting rid of source, game
pairs
in favour of just source
and reusing source.game
.
Engine and simulation
On the game simulation side, Play processing has been redone. This is possibly its fourth major rewrite. I am happy with the results, although it looks like to comply with Hearthstone, I have to pause aura updates. I don’t think this makes any sense but it does look like Patashu is correct and there is no way around it: Auras don’t update during Play.
Finally, Attack/Health swaps are now handled in-engine. I’m not actually a fan of this, but it seems like Hearthstone loves that mechanic, so it’s simpler that way.
The two new brawls, Heart of the Sunwell and Too Many Portals! are also done. They were not particularly hard. The former looks a lot like my BaseTestGame class. :)
Other repositories
The biggest cleanup this week by far has been removing the hs-cards
submodule.
Submodules in git kind of suck (a lot). Chugging it around created its fair share
of problems, especially since all the static data changes were going in that
repository. That meant that when you wanted to implement a new card, you had to
send a pull request to two separate repositories. Urgh.
Well, that’s gone. Static data is now in
fireplace/cards/data/
and all the post-processing that goes with it. Even
Hero Power associations
are now automatically detected from the static files, where they previously had
to be manually assigned.
We now use a different repository, hs-data. This one contains normalized, cleaned up files from the game, both DBF and CardDefs. Each patch is a commit, and each commit is tagged by its build number. So if you wanted to see the diffs from build 9554, you could look at the tag directly.
The extraction scripts used to generate that repository are available in the HearthSim/extract-scripts repository. I even had to update my StormLib Python bindings for the occasion, so I moved them to the HearthSim organization as well.
Most of all this work comes from the needs of Stove, the Hearthstone server @mischanix and I are currently working on. I am really happy with the progress on it. We have a lot of the main menu implemented, including collection management and booster packs. Everything is running on top of a SQLite database which automatically imports most of its contents from the aforementioned hs-data DBFs.
What a month July was.
71 files changed, 4282 insertions(+), 1118 deletions(-)
Jerome