AI check all possible attackers together then dismiss?
Discuss Upcoming Releases, Coding New Cards, Etc.
PLEASE DO NOT REPORT BUGS HERE!
PLEASE DO NOT REPORT BUGS HERE!
Moderators: BAgate, drool66, Aswan jaguar, gmzombie, stassy, CCGHQ Admins
8 posts
• Page 1 of 1
AI check all possible attackers together then dismiss?
by Aswan jaguar » 06 Jan 2023, 09:51
Is it possible to force AI in EVENT_CHECK_ABILITIES or AI assign attackers maybe (though it needs a lot more testing then) when checking which creatures to assign as attackers to also check them all for attacking together and not only one by one and only then dismiss the ones that are not beneficial to attack with especially when AI could make the attack for the win. I am trying to make AI get how cards like Cavalry Pegasus work. The problem is that when AI checks Cavalry Pegasus as a potential attacker and sees that it will die in combat from human defender then it will not attack with it making his other creatures gain flying and go for the win (when human can't block so many fliers).
---
Trying to squash some bugs and playtesting.
Trying to squash some bugs and playtesting.
-
Aswan jaguar - Super Tester Elite
- Posts: 8131
- Joined: 13 May 2010, 12:17
- Has thanked: 748 times
- Been thanked: 479 times
Re: AI check all possible attackers together then dismiss?
by drool66 » 07 Jan 2023, 00:34
I think the closest we can get using existing architecture is:
if( event == EVENT_CHECK_ABILITIES && affected_card_controller == player && current_turn == player )
check_abilities_keywords |= KEYWORD_FLYING;
The ai already checks attackers in groups, but it doesn't check abilities for the whole group like you're saying. Look at engine.c::ai_declare_attackers() for where int combo is declared. The following loop is where each combo is checked.
Just to spitball an idea - you could possibly dispatch another EVENT_CHECK_ABILITIES there, but only read and augment abilities, since power and toughness were already added in setup_ai_combat_data(). You would have to cache and restore the abilities after each loop so they didn't carry over.
So ai_declare_attackers would add after what is currently line 3423, just before the first inner loop is closed:
Also not sure if the loop in Cavalry Pegasus is necessary since STATE_ATTACKING is already checked.
if( event == EVENT_CHECK_ABILITIES && affected_card_controller == player && current_turn == player )
check_abilities_keywords |= KEYWORD_FLYING;
The ai already checks attackers in groups, but it doesn't check abilities for the whole group like you're saying. Look at engine.c::ai_declare_attackers() for where int combo is declared. The following loop is where each combo is checked.
Just to spitball an idea - you could possibly dispatch another EVENT_CHECK_ABILITIES there, but only read and augment abilities, since power and toughness were already added in setup_ai_combat_data(). You would have to cache and restore the abilities after each loop so they didn't carry over.
So ai_declare_attackers would add after what is currently line 3423, just before the first inner loop is closed:
- Code: Select all
int old_check_abilities_keywords = check_abilities_keywords;
check_abilities_keywords = KEYWORD_0;
{
int old_activating_player = activating_player;
activating_player = player;
dispatch_event(player, attack_indices[i], EVENT_CHECK_ABILITIES);
activating_player = old_activating_player;
}
ai_combat_attack_abils[num_attackers] |= check_abilities_keywords;
check_abilities_keywords = old_check_abilities_keywords;
- Code: Select all
if( event == EVENT_CHECK_ABILITIES && affected_card_controller == player && (get_card_instance(player, card)->state & STATE_ATTACKING) ){
int i;
for(i=0; i<num_attackers; i++){
if( ai_combat_attack_card[i] == card ){
check_abilities_keywords |= KEYWORD_FLYING;
break;
}
}
}

The latest images for Manalink will be here.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
-
drool66 - Programmer
- Posts: 1185
- Joined: 25 Nov 2010, 22:38
- Has thanked: 187 times
- Been thanked: 280 times
Re: AI check all possible attackers together then dismiss?
by Aswan jaguar » 09 Jan 2023, 08:51
I tested this and some variations of this but with no luck.drool66 wrote:No idea if this would work or if it's a good idea, you'll have to check yourself.
---
Trying to squash some bugs and playtesting.
Trying to squash some bugs and playtesting.
-
Aswan jaguar - Super Tester Elite
- Posts: 8131
- Joined: 13 May 2010, 12:17
- Has thanked: 748 times
- Been thanked: 479 times
Re: AI check all possible attackers together then dismiss?
by Aswan jaguar » 02 Jun 2024, 11:21
I have this coded added in ai_choose_attackers() and seems mostly fine in my tests but I might run inadequate tests. Can you please see obvious mistake and tell me what to expect in certain testing scenarios. I have been fiddling with this for over a month and because of other issues that I managed to fix and already commit I had been changing and testing this a zilion times.
- | Open
- Code: Select all
if (combo & (1 << i))
{
inst->state |= STATE_ATTACKING;
//added by aswan: makes AI check_abilities while thinking for combo especially usefull for clause:
// "whenever ~ attacks creatures( or ~ ) get for each attacking" while checking EVENT_CHECK_ABILITIES
int old_check_abilities_keywords = check_abilities_keywords;
int old_check_abilities_toughness = check_abilities_toughness;
int old_check_abilities_power = check_abilities_power;
check_abilities_keywords = get_abilities(player, attack_indices[i], EVENT_ABILITIES, -1);;
check_abilities_power = get_attack_power(player, attack_indices[i]);
check_abilities_toughness = get_abilities(player, attack_indices[i], EVENT_TOUGHNESS, -1);
{
int old_activating_player = activating_player;
activating_player = player;
dispatch_event(player, attack_indices[i], EVENT_CHECK_ABILITIES);
activating_player = old_activating_player;
}
ai_combat_attack_card[num_attackers] = attack_indices[i];
ai_combat_attack_power[num_attackers] = local_ai_combat_attack_power[i] |= check_abilities_power;
ai_combat_attack_toughness[num_attackers] = local_ai_combat_attack_toughness[i] |= check_abilities_toughness;
ai_combat_attack_abils[num_attackers] = local_ai_combat_attack_abils[i] |= check_abilities_keywords;
ai_combat_attack_attack_rating[num_attackers] = local_ai_combat_attack_rating[i];
ai_combat_blocking_choices_bitmask[num_attackers] = local_ai_combat_blocking_choices_bitmask[i];
ai_combat_attack_defensive_modifier[num_attackers] = local_ai_combat_attack_defensive_modifier[i];
ai_combat_block_defensive_modifier[num_attackers] = local_ai_combat_block_defensive_modifier[i];
check_abilities_keywords = old_check_abilities_keywords;
check_abilities_toughness = old_check_abilities_toughness;
check_abilities_power = old_check_abilities_power;
if (csvid == CARD_ID_COCKATRICE || csvid == CARD_ID_LURE)
attack_destroys_if_blocked_bitmask |= 1 << num_attackers;
++num_attackers;
}
---
Trying to squash some bugs and playtesting.
Trying to squash some bugs and playtesting.
-
Aswan jaguar - Super Tester Elite
- Posts: 8131
- Joined: 13 May 2010, 12:17
- Has thanked: 748 times
- Been thanked: 479 times
Re: AI check all possible attackers together then dismiss?
by drool66 » 04 Jun 2024, 18:30
EDIT wrong indices - this one is done in TENTATIVE_ai_speculate_on_combat()
EDIT2: It is done in setup_ai_combat_data() and written to ai_combat_data[ ][ ], then copied from there to ai_combat_attack_power[ ] and modified with pumpable_power[ ] in TENTATIVE_ai_speculate_on_combat(). So it would seem to me this change is redundant and effectively doubles the effects of check_abilities_power / _toughness.
You're a much better tester than I, but I would still be very careful modifying how some of these basic functions work, especially without checking how Shandalar does it - see the comment under gain_control_and_legend_rule.c::gain_control_implied().
With that said, check_abilities_power / _toughness are integers and not bitfields, so is there a reason you're combining them using bitwise OR?
The latest images for Manalink will be here.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
-
drool66 - Programmer
- Posts: 1185
- Joined: 25 Nov 2010, 22:38
- Has thanked: 187 times
- Been thanked: 280 times
Re: AI check all possible attackers together then dismiss?
by drool66 » 05 Jun 2024, 18:16
I'm also wondering why pumpable_power and pumpable_toughness are added up from among all creatures for each player, and then the total for all creatures is applied to the power & toughness (in ai_combat_attack_power / _toughness) for each creature. Am I missing something?
The latest images for Manalink will be here.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
The latest Manalink installation directory will be here. Well, not quite, anymore. Check the latest patches.
-
drool66 - Programmer
- Posts: 1185
- Joined: 25 Nov 2010, 22:38
- Has thanked: 187 times
- Been thanked: 280 times
Re: AI check all possible attackers together then dismiss?
by Aswan jaguar » 05 Jun 2024, 19:57
Thanks, for taking the time to check this. I don't have any time to check or reply as I wont have access to manalink for the following 2 weeks. I will still check what's going on here.
---
Trying to squash some bugs and playtesting.
Trying to squash some bugs and playtesting.
-
Aswan jaguar - Super Tester Elite
- Posts: 8131
- Joined: 13 May 2010, 12:17
- Has thanked: 748 times
- Been thanked: 479 times
Re: AI check all possible attackers together then dismiss?
by Aswan jaguar » 28 Jun 2024, 14:23
For cards like Fervent Charge "Whenever a creature you control attacks, it gets" it can be done like you say, using existing EVENT_CHECK_PUMP and pumpable_power[] and pumpable_toughness[]. But for cards like Kavu Mauler "Whenever ~ attacks, it gets ... until end of turn for each other attacking" , or Rubblebelt Raiders "Whenever ~ attacks, put a +1/+1 counter on it for each attacking creature you control", or Marton Stromgald "Whenever ~ attacks, other attacking creatures get +1/+1 until end of turn for each attacking creature other than ~." or Fangren Pathcutter which pumps abilities "Whenever ~ attacks, attacking creatures gain trample until end of turn." what we have already doesn't work.drool66 wrote:It is done in setup_ai_combat_data() and written to ai_combat_data[ ][ ], then copied from there to ai_combat_attack_power[ ] and modified with pumpable_power[ ] in TENTATIVE_ai_speculate_on_combat().
With my changes the above cards and other similar work for AI. In my tests I didn't see any doubling effect for check_abilities_power / _toughness, or EVENT_CHECK_PUMP and EVENT_POW_BOOST / EVENT_TOU_BOOST.drool66 wrote:So it would seem to me this change is redundant and effectively doubles the effects of check_abilities_power / _toughness.
Shandalar doesn't have AI code for these cards and such clause so I can't get any help from there.drool66 wrote:but I would still be very careful modifying how some of these basic functions work, especially without checking how Shandalar does it
I just tried any idea that came into my mind and this happened to work (mostly) so I don't know how it works, but it mostly works as I want it to work. That's the reason why I asked for your help and test scenarios that this code would fail because my tests revealed not so good behaviour rarely and only by AI thinking it had 1 more point of power than it would really get. And I prefer this far from not having AI get these cards at all.drool66 wrote:With that said, check_abilities_power / _toughness are integers and not bitfields, so is there a reason you're combining them using bitwise OR? I'm not sure I know how "a = b |= c" is computed I don't think a = b |= c does what you want it to do.
With that said I will still keep an eye for weird AI attack decisions / behaviors while I play-test as I always do and if we proceed for an update maybe others can chip in and report weird AI attacks.
Where do you see this as I don't see any code for pumpable_power and pumpable_toughness in engine.c or in main.c?drool66 wrote:I'm also wondering why pumpable_power and pumpable_toughness are added up from among all creatures for each player, and then the total for all creatures is applied to the power & toughness (in ai_combat_attack_power / _toughness) for each creature. Am I missing something?
---
Trying to squash some bugs and playtesting.
Trying to squash some bugs and playtesting.
-
Aswan jaguar - Super Tester Elite
- Posts: 8131
- Joined: 13 May 2010, 12:17
- Has thanked: 748 times
- Been thanked: 479 times
8 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 28 guests