Decoding Hearthstone Deck Codes with R
Introduction
A few months ago from writing, Hearthstone released a way to generate and read a code to make deck sharing easier. Using the code, allows the Hearthstone client to populate the deck list quickly, allowing users to avoid the cumbersome task of finding the card and adding it to their deck. This is a quick introduction on how to decode the list in R.
This will use the jsonlite package to deencode the string as well as fetch the card list from HearthstoneJSON. The rest will be parsing the resultant to form a the deck. BMS package will be used to check encoding.
The Deck
It’s always easiest when working towards a known solution. So the following deckcode and deck will be used:
Secret Mage
Class: Mage
Format: Standard
Year of the Mammoth
2x (1) Mana Wyrm
2x (2) Arcanologist
2x (2) Frostbolt
2x (2) Medivh’s Valet
2x (2) Primordial Glyph
2x (3) Arcane Intellect
2x (3) Counterspell
1x (3) Ice Block
2x (3) Kirin Tor Mage
2x (3) Mirror Entity
2x (3) Volcanic Potion
2x (4) Fireball
1x (4) Ghastly Conjurer
2x (6) Kabal Crystal Runner
1x (7) Bonemare
2x (7) Firelands Portal
1x (8) Medivh, the Guardian
AAECAf0EBMABobcC3s0Cps4CDXHDAbsClQOrBJYF7AWjtgLXtgLpugKHvQLBwQKYxAIA
To use this deck, copy it to your clipboard and create a new deck in Hearthstone
Decoding The String
The deck string is a base64 encoded compact byte string. This can make it a bit harder to decode in R compared to other languages such as python or c/c++/c#. For more information about the deck string HearthSim has an excellent write up. From this, the values are in varint, so will need be be decoded properly.
DeEncode base64
The first step is to deencode the base64 byte string. To do this, the jsonlite package will be used to do this.
Now going over this, there is a header block followed by card blocks, and finally terminating the 0x00. Since this is in base 16, let us set this.
Before we begin, we have to setup a function that will become helpful later on. This is to convert the hex value in a given base to a number:
Other functions will be needed later but for now, this gets us started.
Header Block
The header block starts with 0x00, followed by the version, then the Hearthstone game format (Standard or Wild). So, to decode this:
This gives us a version of 1, and format 2 which is standard.
Card Block
The cards are split into four blocks, starting with a length then the list. The order goes:
- Heroes
- Single cards
- Double cards
- 3 or more cards
Hero and Card Blocks
The first block starts at position 4 (R starts arrays at 1). From this, we can convert it to a number and use this as the number of cards in the list for that block. This list is varint values, which may cause an issue due to endianness.
Endianess of the system. Currently, I’m using my Windows machine which can assume little endian. Unfortunately, I’m not sure how to set the endianness in R to properly decode. The last part is the card codes are stored as varint. This means that the least or most signifigant bit must be check for a ‘1’ indicating there is more values to read in for the number. The values are swapped in order, concatenated and ‘0’s removed from start. More on varint can be found from Google write up.
Now we can grab the blocks.
The last part is now, taking this data and putting it together with the card database:
dbfid | cardIter | name | cost |
---|---|---|---|
113 | 2 | Counterspell | 3 |
192 | 1 | Ice Block | 3 |
195 | 2 | Mirror Entity | 3 |
315 | 2 | Fireball | 4 |
405 | 2 | Mana Wyrm | 1 |
555 | 2 | Arcane Intellect | 3 |
637 | 0 | Jaina Proudmoore | NA |
662 | 2 | Frostbolt | 2 |
748 | 2 | Kirin Tor Mage | 3 |
39715 | 2 | Firelands Portal | 7 |
39767 | 2 | Medivh’s Valet | 2 |
39841 | 1 | Medivh, the Guardian | 8 |
40297 | 2 | Volcanic Potion | 3 |
40583 | 2 | Kabal Crystal Runner | 6 |
41153 | 2 | Arcanologist | 2 |
41496 | 2 | Primordial Glyph | 2 |
42718 | 1 | Ghastly Conjurer | 4 |
42790 | 1 | Bonemare | 7 |
Whats left now is to sort this for final display:
Jaina Proudmoore
Card.Count | Cost | Name |
---|---|---|
2 | 1 | Mana Wyrm |
2 | 2 | Arcanologist |
2 | 2 | Frostbolt |
2 | 2 | Medivh’s Valet |
2 | 2 | Primordial Glyph |
1 | 3 | Ice Block |
2 | 3 | Arcane Intellect |
2 | 3 | Counterspell |
2 | 3 | Kirin Tor Mage |
2 | 3 | Mirror Entity |
2 | 3 | Volcanic Potion |
1 | 4 | Ghastly Conjurer |
2 | 4 | Fireball |
2 | 6 | Kabal Crystal Runner |
1 | 7 | Bonemare |
2 | 7 | Firelands Portal |
1 | 8 | Medivh, the Guardian |
Whats left would be to add in enum types for the heros and game format. But this is enough to get what I originally had wanted.