Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

[TUTO] Programming custom API: General discussion
Golddieb
#1 Posted : Tuesday, January 13, 2015 4:12:45 PM(UTC)

Rank: Advanced Member

Groups: Registered
Posts: 147

Thanks: 39 times
Was thanked: 49 time(s) in 38 post(s)
I didn't see a post for this, so I decided to start a new one.
This topic is for all questions related to programming a custom HR AI.

Would be good if other posts follow the same scheme, so this topic becomes some kind of FAQ.

Had a look at the API and first of all it's really a pain. ;)
I like the way it is written, but the missing code docs make it hard to understand what's really going on there.
Thus, we can't have a look at the internal HR code, at least a description what the BotBase methods should do and when they are called would be great.
Some expenations about special states (see below OnQueryBestMove) could help a lot.


I was able to make some educated guesses from the example code and silverfish integration but I still have questions.

Q: How can I call HR's original functions?
e.g.: OnGameArenaDraft
I want to change the hero priority but use the default behavior for card picking.
I would override OnGameArenaDraft, set e.handled=true, do my hero handling there and call base, right?


Q: How does OnQueryBestMove interact with the event list and when is it called?
The EventArgs contain a list and an empty list equals end turn.
The list indicates that you can have a sequence of moves (think that's what HR's default AI does).
Silverfish only adds one move to the list (that's the reason for recalculation after every move?!?) but performs multiple moves per turn.
Putting this together my guesses are:
- at the start of the turn the list is empty. This calls OnQuerryBestMove
- the list is executed in sequential order (why isn't it a queue?)
- an empty list after an action recalls OnQueryBestMove (only way to force recalculation? eg: do some actions, play card with random effect, recalculate based on random effect)
- an empty list after OnQueryBestMove ends the turn
Am I missing something there?

1 user thanked Golddieb for this useful post.
micmil on 12/4/2015(UTC)
JoyAdmin
#2 Posted : Tuesday, January 13, 2015 11:25:15 PM(UTC)
Rank: Administration

Groups: Administrators
Posts: 4,845

Thanks: 805 times
Was thanked: 4538 time(s) in 1636 post(s)
Q: How can I call HR's original functions?
e.g.: OnGameArenaDraft

if (e.is_hero_choices)
{
//must set e.handled to true if you handle draft in this function.
e.handled = true;

//choose hero here
e.draft_pick_id = GetBestHeroCardId(e);

return;
}else
{
//other cards drafting use default A.I.
e.handled = false;
return;
}

Q: How does OnQueryBestMove interact with the event list and when is it called?

Everytime when any card status changed will call this function, not only at the start of the turn, since there is random effect card, for example, after random attack card attacked, bot must get the updated game status and re-calculate.

Silverfish only can calculate the first move of any given game status, that's why the list every time only can add one action.

Sure you can add action 1, action 2, action 3 ... to the list, bot will execute it one by one, but you must make sure the action is accurate and executable. if action 2 has random effect, then action 3 should not be added to the list.

If you return empty list, bot will ends the turn since there is no executable move, but botbase class will query multiple times to ensure it, it's a bit strange but there is latency to transfer the game state data.




1 user thanked JoyAdmin for this useful post.
Golddieb on 1/13/2015(UTC)
Golddieb
#4 Posted : Friday, January 16, 2015 1:37:55 PM(UTC)

Rank: Advanced Member

Groups: Registered
Posts: 147

Thanks: 39 times
Was thanked: 49 time(s) in 38 post(s)
Q: How is int index of BotAction counted? What is the base value?

Q: Questions about Entity class:
How is int EntityId counted? Does it depend on the draworder or the playorder?
What is List<Entity> Attachments used for? Is it for auras? How is the reference resolved? Is it bidirectional?
What is bool IsElite mean and what is it used for?
What happens to an Entity when it is silenced?

Q: When is BotBase.updateGameState called?

Q: Can I see the cards played by the enemy?
If so, can I see targets of battlecries, too?
e.g.: Enemy plays Shattered Sun Cleric and buffes minion. How is this resolved by the bot engine?
What is the Entity representation of the buffed minion?

Q: OnQueryBestMove can "return" a list of actions. When OnQueryBestMove is recalled due to state changes before all actions are performed, does the new call contain this list or is it a new empty list?
JoyAdmin
#5 Posted : Saturday, January 17, 2015 1:08:08 AM(UTC)
Rank: Administration

Groups: Administrators
Posts: 4,845

Thanks: 805 times
Was thanked: 4538 time(s) in 1636 post(s)
Q: How is int index of BotAction counted? What is the base value?

A: All index is based on zero.


Q: Questions about Entity class:
How is int EntityId counted? Does it depend on the draworder or the playorder?

A: EntityId is given by game's server, bot only simulate to generate a entityid for spawned card, it's calculated as max entity id on the board + 1.


Q: What is List<Entity> Attachments used for? Is it for auras? How is the reference resolved? Is it bidirectional?

A: If a card has ability/buff given from other cards, then an entity called attachment will be added to its attachment list.

There is no reference, all is copied entity instance.


Q: What is bool IsElite mean and what is it used for?

A: IsElite is used for game's special visual effect, for example [firelord], usually you don't need to care about it.


Q: What happens to an Entity when it is silenced?

A: Entity.IsSilenced will be true.

Q: When is BotBase.updateGameState called?

A: Wheneven new gamestate data is received.

Q: Can I see the cards played by the enemy?
If so, can I see targets of battlecries, too?
e.g.: Enemy plays Shattered Sun Cleric and buffes minion. How is this resolved by the bot engine?
What is the Entity representation of the buffed minion?

A: Not public yet, but you can store all the info by yourself if you think it's necessary.

Q: OnQueryBestMove can "return" a list of actions. When OnQueryBestMove is recalled due to state changes before all actions are performed, does the new call contain this list or is it a new empty list?

A: new call means bot already executed all the actions and query for next move, the list is empty.

1 user thanked JoyAdmin for this useful post.
Golddieb on 1/17/2015(UTC)
Golddieb
#6 Posted : Wednesday, January 28, 2015 1:31:05 PM(UTC)

Rank: Advanced Member

Groups: Registered
Posts: 147

Thanks: 39 times
Was thanked: 49 time(s) in 38 post(s)
It's been a while and I thought it's time for new questions. ;)

Q: What is bool Entity.IsMagnet used for?

Q: Where can I get information like "Feugen died" from?

Q: Enemy turn again: Where can I recive data of enemy cards played from?
If you had Feugen on the board and your enemy removed it somehow, it is important to know if Feugen died or was Hexed and then removed.
What is the best way to access the data?
JoyAdmin
#7 Posted : Monday, February 2, 2015 1:17:29 AM(UTC)
Rank: Administration

Groups: Administrators
Posts: 4,845

Thanks: 805 times
Was thanked: 4538 time(s) in 1636 post(s)
Q: What is bool Entity.IsMagnet used for?

A: It's used for special visual effect, no need to care about it.

Q: Where can I get information like "Feugen died" from?

Q: Enemy turn again: Where can I recive data of enemy cards played from?
If you had Feugen on the board and your enemy removed it somehow, it is important to know if Feugen died or was Hexed and then removed.
What is the best way to access the data?

A: Feugen is special, you have to store every played turns data, then extract information from it.
1 user thanked JoyAdmin for this useful post.
Golddieb on 2/2/2015(UTC)
xytrix
#3 Posted : Thursday, October 1, 2015 6:39:00 AM(UTC)

Rank: Advanced Member

Groups: Registered
Posts: 40

Was thanked: 11 time(s) in 8 post(s)
JoyAdmin;22764 wrote:

Q: How does OnQueryBestMove interact with the event list and when is it called?

Everytime when any card status changed will call this function, not only at the start of the turn, since there is random effect card, for example, after random attack card attacked, bot must get the updated game status and re-calculate.


Sorry JoyAdmin, I just sent you a PM with the same question and then I found this FAQ after :D

Question: When you say OnQueryBestMove is called "everytime when any card status changed", is an exact list of what changes that is? I know for example, Sludge Belcher dies, and Slime spawns, or a new card is drawn. But what other cases can there be?

JoyAdmin;22764 wrote:

If you return empty list, bot will ends the turn since there is no executable move, but botbase class will query multiple times to ensure it, it's a bit strange but there is latency to transfer the game state data.


Question: When you say botbase class will query multiple times, does it update game state data between each query? Or is it same query?
botmaker
#8 Posted : Thursday, October 1, 2015 8:31:21 AM(UTC)

Rank: Advanced Member

Groups: Registered
Posts: 177

Thanks: 2 times
Was thanked: 196 time(s) in 75 post(s)
@xytrix ofc, the game-state is updated
xytrix
#9 Posted : Thursday, October 1, 2015 6:37:19 PM(UTC)

Rank: Advanced Member

Groups: Registered
Posts: 40

Was thanked: 11 time(s) in 8 post(s)
botmaker;30308 wrote:
@xytrix ofc, the game-state is updated


Yeah, I can confirm this now. I thought it was the same query because of the bug where Muster for Battle would still show hero with no weapon after multiple OnQueryBestMove's. But I see the state is updated with a new Silver Hand Recruit spawned in each callback, just not the weapon because it's last.
xytrix
#10 Posted : Saturday, October 3, 2015 6:39:03 PM(UTC)

Rank: Advanced Member

Groups: Registered
Posts: 40

Was thanked: 11 time(s) in 8 post(s)
xytrix;30360 wrote:
the bug where Muster for Battle would still show hero with no weapon after multiple OnQueryBestMove


So I decided to look into this further and found that there are 2 entries in the GameState that can be used to detect callbacks that may have incomplete board states:

bool IsBlockingServer
and
bool IsProcessingPowers

When Muster for Battle is played, both values are true until the action is completed.
When Divine Favor is played (but all drawn cards are not known yet), only IsProcessingPowers is true.

I would like to ignore incomplete board states to prevent misplays (i.e. not knowing some cards you had in hand), so returning no action when IsBlockingServer == true, seems to fix misplays with Muster for Battle being incomplete (seems you always get another callback when IsBlockingServer == false, so taking no action is fine here)

However, returning no action when IsProcessingPowers == true, sometimes makes the bot end turn without taking action. Seems we're not guaranteed another callback when "powers" are finished processing?

Can JoyAdmin (or anyone with experience with these variables) comment on how they actually work? Also, in the Divine Favor example, is there any way to make the bot simply wait and perform no action until IsProcessingPowers == false or we know all the cards that are drawn?
Fret13103
#11 Posted : Friday, October 9, 2015 3:32:52 PM(UTC)
Rank: Newbie

Groups: Registered
Posts: 1
Location: London

Q) What are the properties of entity, as a list?

Is there a way of telling if a Card has buffs, example: "Give adjacent minions +2 damage", or "Give adjacent minions +2 health and Taunt"?

Q) Is there a webpage or doc where you can see at least some of the Hearth Ranger callbacks, the only one I know is getHandCards(HSRangerLib.BotBase rangerlib)
mvegter197
#12 Posted : Monday, May 15, 2017 4:54:55 AM(UTC)
Rank: Member

Groups: Registered
Posts: 16

Was thanked: 18 time(s) in 6 post(s)
Q) Is the deck_name from GameStartEventArgs broken?
As I'm only getting empty string if I use it.
R4setsu
#13 Posted : Friday, February 2, 2018 2:28:10 PM(UTC)
Rank: Newbie

Groups: Registered
Posts: 3

Q: How to set a rule for Skull of the Man'ari (LOOT_420) to play it highest priority when I had a demon cards in my hand?

I set a json file in my directory LOOT_420.json

Code:
{
        "GameCardId":"LOOT_420",    
        "ConfigComment":"Skull of the Man'ari",   
 
    "InHandPlayPriority": 
               
        {
 
            "values":
 
            [
                                 
                {                                 
                             
                "condition": "my_hand(count(), demon=true) > 0",
 
                "value":"1000",
                                 
                }
 
            ],
 
        },
 
    "InHandBonus": 
               
        {
 
            "values":
 
            [
                                 
                {   
                "condition": "my_hand(count(), demon=true) > 0",
 
                "value":"1000",
                                                
                }


            ],
 
        },
}


BUT the bot is acting weird. And not playing it in the first place.
scottbreak
#14 Posted : Friday, February 2, 2018 7:29:02 PM(UTC)
scottbreak


Rank: Advanced Member

Groups: Registered, HSModerator
Posts: 429

Thanks: 291 times
Was thanked: 469 time(s) in 153 post(s)
R4setsu;54267 wrote:
Q: How to set a rule for Skull of the Man'ari (LOOT_420) to play it highest priority when I had a demon cards in my hand?

I set a json file in my directory LOOT_420.json

Code:
{
        "GameCardId":"LOOT_420",    
        "ConfigComment":"Skull of the Man'ari",   
 
    "InHandPlayPriority": 
               
        {
 
            "values":
 
            [
                                 
                {                                 
                             
                "condition": "my_hand(count(), demon=true) > 0",
 
                "value":"1000",
                                 
                }
 
            ],
 
        },
 
    "InHandBonus": 
               
        {
 
            "values":
 
            [
                                 
                {   
                "condition": "my_hand(count(), demon=true) > 0",
 
                "value":"1000",
                                                
                }


            ],
 
        },
}


BUT the bot is acting weird. And not playing it in the first place.

Use BeforePlayCardBonus instead of InHandBonus
R4setsu
#15 Posted : Tuesday, February 6, 2018 5:21:49 AM(UTC)
Rank: Newbie

Groups: Registered
Posts: 3

Thanks I got it. But what is the difference between "BeforePlayCardBonus" and "InHandPlayPriority" ? What I should use?
mixarms
#16 Posted : Saturday, April 21, 2018 8:50:24 AM(UTC)

Rank: Advanced Member

Groups: Registered
Posts: 57
Location: Brazil

Thanks: 7 times
Was thanked: 17 time(s) in 7 post(s)
R4setsu;54322 wrote:
Thanks I got it. But what is the difference between "BeforePlayCardBonus" and "InHandPlayPriority" ? What I should use?


InHand bonus = Bonus to keep it on your hand.
BeforePlay bonus = Bonus before deciding to play the card.

Idk about the InHandPlayPriority though
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Powered by YAF | YAF © 2003-2011, Yet Another Forum.NET
This page was generated in 0.176 seconds.