Page 1 of 1

confirm]Tragic Arrogance doesn't sac right & sac RulesEngine

PostPosted: 29 Mar 2017, 13:17
by Aswan jaguar
Describe the Bug:
AI cast Tragic Arrogance and had in play 1 creature, Iroas's Champion and 1 artifact, Angel's Tomb.I had 3 creatures in play and 2 artifacts.After resolution AI had no creature, no artifact and no Rules Engine.I had correctly 1 creature and 1 artifact but my Rules Engine was also sacrificed. fix

Which card did behave improperly?
Tragic Arrogance

Which update are you using? (date, name)Which type? (duel, gauntlet, sealed deck)
Manalink 2016/08/27: Eldritch Moon v2, duel

What exactly should be the correct behavior/interaction?
Tragic Arrogance doesn't make AI sac it's only creature and it's only artifact or enchantment or planeswalker if it has only 1.It doesn't affect cards not in game like Rules Engine.

Are any other cards possibly affected by this bug?
-

Re: Tragic Arrogance doesn't sac right & sacs Rules Engine

PostPosted: 06 Apr 2017, 20:04
by stassy
It also sac anything non MTG standard, like Avatar, Planes...

Re: confirm]Tragic Arrogance doesn't sac right & sac RulesEn

PostPosted: 27 Mar 2019, 11:33
by Aswan jaguar
Fixed sacrifice also special cards in commit 27a7e713.
Found that in fact when AI plays it when it should select which permanent of it's own to select it selects opponent's ones.
However the code is very difficult to understand so I can't fix this.
code | Open
Code: Select all
static const char* target_is_unmarked_nonland(int who_chooses, int player, int card, int targeting_player, int targeting_card)
{
  return !((get_card_instance(player, card)->state & STATE_TARGETTED) || is_what(player, card, TYPE_LAND)) ? NULL : "AI prefers to pick nonredundant nonland";
}
static const char* target_is_marked_or_land(int who_chooses, int player, int card, int targeting_player, int targeting_card)
{
  return ((get_card_instance(player, card)->state & STATE_TARGETTED) || is_what(player, card, TYPE_LAND)) ? NULL : "AI prefers to pick redundant or land";
}

void tragic_arrogance_effect(int player, int card, int who_chooses){
   type_t typs[4] = { TYPE_ARTIFACT, TYPE_CREATURE, TYPE_ENCHANTMENT, TARGET_TYPE_PLANESWALKER };
   const char* prompts[2][4] =
   {
      {
         "Select an artifact you control.",
         "Select a creature you control.",
         "Select an enchantment you control.",
         "Select a planeswalker you control."
      },
      {
         "Select an artifact an opponent controls.",
         "Select a creature an opponent controls.",
         "Select an enchantment an opponent controls.",
         "Select a planeswalker an opponent controls."
      }
   };

   target_definition_t td;
   base_target_definition(player, card, &td, 0);
   td.allow_cancel = 0;

   target_definition_t td_unmarked_nonland;
   base_target_definition(player, card, &td_unmarked_nonland, 0);
   td_unmarked_nonland.extra = (int)target_is_unmarked_nonland;
   td_unmarked_nonland.special = TARGET_SPECIAL_EXTRA_FUNCTION;
   td_unmarked_nonland.allowed_controller = td_unmarked_nonland.preferred_controller = 1-player;
   td_unmarked_nonland.allow_cancel = 0;

   target_definition_t td_marked_or_land;
   base_target_definition(player, card, &td_marked_or_land, 0);
   td_marked_or_land.extra = (int)target_is_marked_or_land;
   td_marked_or_land.special = TARGET_SPECIAL_EXTRA_FUNCTION;
   td_marked_or_land.allowed_controller = td_marked_or_land.preferred_controller = player;
   td_marked_or_land.allow_cancel = 0;

   card_instance_t* inst = get_card_instance(player, card);
   inst->number_of_targets = 0;

   int i, p, t;
   for (i = 0, p = player; i <= 1; ++i, p = 1-p)
   {
      td.allowed_controller = td.preferred_controller = p;
      td.who_chooses = (who_chooses == ANYBODY ? p : player);
      target_definition_t* td_pref = p == player ? &td_unmarked_nonland : &td_marked_or_land;
      for (t = 0; t < 4; ++t)
      {
         td.required_type = td_pref->required_type = typs[t];
         if (can_target(&td))
         {
            pick_next_target_noload(IS_AI(player) && can_target(td_pref) ? td_pref : &td, prompts[i][t]);
            add_state(inst->targets[0].player, inst->targets[0].card, STATE_TARGETTED);
            inst->number_of_targets = 0;
         }
      }
   }

   int can_cause[2] = { can_cause_sacrifice(player, 0), can_cause_sacrifice(player, 1) };

   char marked[2][151] = {{0}};
   int c;
   for (p = 0; p <= 1; ++p){
      for (c = 0; c < active_cards_count[p]; ++c){
         if (in_play(p, c))
         {
            if (check_state(p, c, STATE_TARGETTED)){
               remove_state(p, c, STATE_TARGETTED);
            }
            else if (can_cause[p] && !is_what(p, c, TYPE_LAND | TYPE_EFFECT) && !check_special_flags2(p, c, SF2_CANNOT_BE_SACRIFICED)){
               marked[p][c] = 1;
            }
         }
      }
   }

   for(i = 0, p = player; i <= 1; ++i, p = 1-p){
      for (c = 0; c < active_cards_count[p]; ++c){
         if( marked[p][c] && in_play(p, c) ){
            kill_card(p, c, KILL_SACRIFICE);
         }
      }
   }
}

int card_tragic_arrogance(int player, int card, event_t event)
{
  /* Tragic Arrogance   |3|W|W   0x200e1f2
   * Sorcery
   * For each player, you choose from among the permanents that player controls an artifact, a creature, an enchantment, and a planeswalker. Then each player sacrifices all other nonland permanents he or she controls. */

   if (event == EVENT_RESOLVE_SPELL){
      tragic_arrogance_effect(player, card, player);
      kill_card(player, card, KILL_DESTROY);
   }

   return basic_spell(player, card, event);
}