Hearthranger - How to understand json config ?

 

sample file: EX1_604.json

 

{

         "GameCardId":"EX1_604",    

         "ConfigComment":"Frothing Berserker :  Whenever a minion takes damage, gain +1 Attack.",   

        

         "BeforePlayCardBonus":

          {

                                              "values":

                                              [

                                                             {

                                                             "comment":"don't play this card if our own minions on board ==0",             

                                                                    "condition": "my_minions(count()) == 0",

                                                                    "value":"-100",

                                                           },

                                                           {                                                  

                                                             "comment":"set some minus bonus value when this card is played if our own minions on board < 2",              

                                                                    "condition": "my_minions(count()) <= 1",

                                                                    "value":"-8",

                                                           },

 

                                              ],

                    }, 

        

}

 

GameCardId should be the same as json file name.

 

In the sample, it means when bot tries to rollout Frothing Berserker, it'll check the board is matched with any of the values (from top to bottom), once it's matched, the bonus value will be calculated into whole board value.

 

 

A card's value can be adjusted when it's inhand, or onboard, or before being played, or before end turn, here is all the keywords can adjust its value:

 

InHandBonus,   (set a card's bonus if it's inhand)

OnBoardBonus,  (set a card's bonus if it's played and on board (minion + weapon + heropower + hero) )

 

BeforePlayCardBonus,  (set a card's bonus before it's going to be played.)

BeforeBattlecryTargetBonus,  (set a card's battlecry bonus if it has battlecry and it has target.)

 

BeforeUseHeroPowerBonus,  (set hero power's bonus before using it)

BeforePhysicalAttackBonus,  (set minion/hero attack bonus before it attacks.)

 

BeforeOverkilledBonus, (set overkill bonus before a minion is overkilled.)

 

BeforeEndTurnBonus,  (set bonus before end turn)

 

OnDiscoverCardBonus, (set bonus when discovering a card)

OnChooseOneCardBonus, (set bonus when choosing a card, from Choose One card)  (*Please read more details with sample explained in this document if you want to customize ChooseOne card)

OnAdaptCardBonus, (set bonus when adapting a card)

 

BeforeUpgradeCardBonus, (set bonus when upgrading a card) (v.10.3.0.0 or higher)

 

Bot best move is calculated by board value.

 

board value = (my hand card value) + (my hero value) + (my hero power value) + (my hero weapon value) + (my secret value) + ( my minions value) + ( my deck value)

           -(opponent hand card value) - (opponent hero value) - (opponent hero power value) - (opponent hero weapon value) - (opponent secret value) - (opponent minions value) - (opponent deck value)

 

 

While searching the best board value, search priority can be adjusted by the following two keywords:

 

InHandPlayPriority,

OnBoardPlayPriority,

 

Priority value doesn't affect the final board value, it affects search process, suitable priority value can get best move faster.

 

The most important part of json config is "condition" and "value".

 

syntax:

 

"condition": "EXP1 AND EXP2 AND EXP3... ",

"condition": "EXP1 OR EXP2 OR EXP3 OR EXP4... ",

"condition": "*", (any condition)

 

 

An expression function is defined as:

 

entity_collection_expr(count_value, filter1, filter2, filter3, …)

 

entity_collection_expr can be :

 

my_deck

my_graveyard

my_hand

my_heropower

my_heroweapon

my_hero

my_minions

my_secret

my_target

my_discover

my_played

my_self

my_player

 

and 'my_' can be replaced by 'opp_' to represent opponent's entities.

 

count_value can be:

 

min(),  min(attack),  min(health),  min(cost), min(durability),  min(armor)

max(),  max(attack),  max(health),  max(cost), max(durability),  max(armor)

avg(),  avg(attack),  avg(health),  avg(cost), avg(durability),  avg(armor)

sum(),  sum(attack),  sum(health),  sum(cost), sum(durability),  sum(armor)

turn()

count()

 

filter can be:

 

battlecry,

charge,

combo,

deathrattle,

divineshield,

enrage,

healthmin,

overload,

silence,

spellpower,

spellpowerdoulbe,

taunt,

windfury,

damaged,

enraged,

tired,

frozen,

immune,

poisonous,

spell,

silenced,

stealthed,

turn,

played_turn,

played_duplicate,

attack,

health,

cost,

durability,

armor,

cardid,

mana,

max_mana,

weapon,

secret,

murloc,

pirate,

beast,

totem,

demon,

dragon,

mech,

elemental, (v.10.6.3.3 or higher)

mage,

warrior,

druid,

paladin,

rogue,

shaman,

warlock,

hunter,

priest,

minion,

hero, (v.9.4.0 or higher)

inspire,

decktype,

minioncard,

spellcard,

hero_class, (v.9.6.0.0 or higher)

jade_buff, (v.9.6.0.0 or higher)

quest_progress, (v.9.6.0.0 or higher)

lifesteal, (v.9.8.5.0 or higher)

friendly, (v.10.5.5.0 or higher)

rush, (v.10.6.0.0 or higher)

echo, (v.10.6.0.0 or higher)

magnetic, (v.10.7.0.0 or higher)

reborn,(v.11.0.0.0 or higher)

function samples:

 

get hand card number:  my_hand(count())

 

get beast card number in my hand: my_hand(count(), beast=true)

 

get minion card number in my hand: my_hand(count(), minioncard=true)

 

get strongest (max hp) minion's health point:  my_minions(max(health))

 

get opponent's minion number whose hp <=2, and is murloc:  opp_minions(count(), health<=2,murloc=true)

 

get opponent's minion number whose hp ==2, and is murloc:  opp_minions(count(), health=2,murloc=true)

 

get opponent's minion number whose hp <=2, and is murloc, and is not damaged:  opp_minions(count(), health<=2,murloc=true, damaged=false)

 

filter's operator can be:

=

>=

<=

!=

 

 

condition samples:

condition: if opponent is warior

         --> opp_hero(count(), warrior=true)

 

condition: if my hero is warrior and hp > 10

         --> my_hero(max(health), warrior=true) > 10

         --> my_hero(count(), warrior=true, health>10) > 0

 

 

condition: if my minions with deathrattle number > 2

         --> my_minions(count(), deathrattle=true) > 2

 

condition: if opponent low health minion onboard number > 2 and my hand has Forked Lightning(EX1_251) or Lightning Storm (EX1_259)

         --> opp_minions(count(), health<=3, divineshield=false) > 2 AND my_hand(count(), cardid= EX1_251 | EX1_259) > 0

 

condition: if oppoent played Patches the Pirate (CFM_637), it maybe in graveyard or on board

         --> opp_played(count(), cardid=CFM_637) > 0

 

condition's operator can be:

>=

<=

==  ( *filter's operator for equal is = )

!=

 

value samples:

 

value: set value as multiply 2 by health

      --> my_self(max(health)) * 2

 

 

value: set value as the difference of my minions number and opponent minions number

     --> my_minions(count()) - opp_minions(count())

 

 

other samples

 

OnChooseOneCardBonus (needs v.9.6.0.0 or higher)

 

In a Jade druid deck, Jade Idol usually choose second option [Shuffle 3 Jade Idols into your deck.], here is how to set it always to choose the second option.

 

For each choose one card, usually it has 3 different card id, the card id in hand, and the other two card ids when options shows up.

 

So Jade Idol has its own card id [CFM_602], and [CFM_602a] for the first option, [CFM_602b] for the second option, usually suffix 'a' link to Choose One card's first option, it can be wrong, you can check the id via https://hearthstonejson.com/docs/cards.html

 

All you need is to create [CFM_602b.json] in your custom config dir, then edit it like bellow:

 

{

         "GameCardId":"CFM_602b",

         "ConfigComment":"Jade Idol : Choose One - Summon a Jade Golem; or Shuffle 3 copies of this card into your deck.",      

        

         "OnChooseOneCardBonus":

         {

                  "values":

                  [

                          {      

                                   "comment":" Prefer to option 2 when jade buff is less than 5: Shuffle 3 copies of this card into your deck",

                                   "condition": "my_player(count(), jade_buff < 5) > 0",

                                   "value":"20",

                          }

                  ],

         },

}

 

*If a card is a minion card with 'Choose One' keyword, the first option is fixed to 'CardIDa', the second option is fixed to 'CardIDb'.

 For example, Druid of the Swarm's first option json card id is 'ICC_051a', the second option json card id is 'ICC_051b'.

 (v.9.8.8.0 or higher)

 

 

Keyword: quest_progress (needs v.9.6.0.0 or higher)

 

{

         "GameCardId":"UNG_809",  

         "ConfigComment":"Fire Fly :  Battlecry: Add a 1/2 Elemental to your hand.",        

        

                 

         "BeforePlayCardBonus":

                                            {

                                              "values":

                                              [

                                                           {                                                  

                                                             "comment":"if rogue quest is undergoing, play this card aggressively",                 

                                                                    "condition": "my_player(count(),quest_progress >=0) > 0 ",

                                                                    "value":"10",

                                                           }

                                              ],

                                            },     

}

 

To judge a bot quest is in progress:

 

when a quest card is played, quest_progress value is no less than zero (>=0), if quest card is not played, this value is (-1).