It is currently 04 Sep 2025, 21:04
   
Text Size

AI check all possible attackers together then dismiss?

Discuss Upcoming Releases, Coding New Cards, Etc.
PLEASE DO NOT REPORT BUGS HERE!

Moderators: BAgate, drool66, Aswan jaguar, gmzombie, stassy, CCGHQ Admins

AI check all possible attackers together then dismiss?

Postby 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.
User avatar
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?

Postby 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:
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;
and Cavalry Pegasus would instead add:
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;
         }
      }
   }
No idea if this would work or if it's a good idea, you'll have to check yourself. Luckily you're a great tester :D Also not sure if the loop in Cavalry Pegasus is necessary since STATE_ATTACKING is already checked.
User avatar
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?

Postby Aswan jaguar » 09 Jan 2023, 08:51

drool66 wrote:No idea if this would work or if it's a good idea, you'll have to check yourself.
I tested this and some variations of this but with no luck.
---
Trying to squash some bugs and playtesting.
User avatar
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?

Postby 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.
User avatar
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?

Postby drool66 » 04 Jun 2024, 18:30

Isn't this already done in setup_ai_combat_data()?
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? 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.
User avatar
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?

Postby 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?
User avatar
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?

Postby 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.
User avatar
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?

Postby Aswan jaguar » 28 Jun 2024, 14:23

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().
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:So it would seem to me this change is redundant and effectively doubles the effects of check_abilities_power / _toughness.
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:but I would still be very careful modifying how some of these basic functions work, especially without checking how Shandalar does it
Shandalar doesn't have AI code for these cards and such clause so I can't get any help from there.
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.
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.
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.

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?
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?
---
Trying to squash some bugs and playtesting.
User avatar
Aswan jaguar
Super Tester Elite
 
Posts: 8131
Joined: 13 May 2010, 12:17
Has thanked: 748 times
Been thanked: 479 times


Return to Development

Who is online

Users browsing this forum: No registered users and 28 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 28 users online :: 0 registered, 0 hidden and 28 guests (based on users active over the past 10 minutes)
Most users ever online was 7303 on 15 Jul 2025, 20:46

Users browsing this forum: No registered users and 28 guests

Login Form