It is currently 18 Apr 2024, 15:11
   
Text Size

[fixed] Betrayal of Flesh wrong etwine cost & etwine for all

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

[fixed] Betrayal of Flesh wrong etwine cost & etwine for all

Postby Aswan jaguar » 31 Mar 2018, 10:53

Describe the Bug:
1- Betrayal of Flesh it asks for etwine cost for all 3 options.
2- Betrayal of Flesh etwine cost is wrong it is sacrifice 3 creatures. It needs you to have more than 6 lands and select all your lands in order to sacrifice 3.
Which card did behave improperly?
Betrayal of Flesh or etwine ability cost.

Which update are you using? (date, name)Which type? (duel, gauntlet, sealed deck)
Manalink dev 778ccb5 version - duel

What exactly should be the correct behavior/interaction?
1- Betrayal of Flesh asks for etwine cost only for etwine ability.
2- Betrayal of Flesh etwine cost (select 3 lands) sacrifice 3 lands.

Are any other cards possibly affected by this bug?
-
Attachments
betrayal of flesh-targets only owner-no open gy,no resolution.rar
(2.24 KiB) Downloaded 188 times
Last edited by drool66 on 30 Jul 2020, 22:17, edited 4 times in total.
Reason: edited correct info
---
Trying to squash some bugs and playtesting.
User avatar
Aswan jaguar
Super Tester Elite
 
Posts: 8078
Joined: 13 May 2010, 12:17
Has thanked: 730 times
Been thanked: 458 times

Re: Betrayal of Flesh wrong etwine cost & etwine for all

Postby FastEddie » 25 Jul 2020, 10:20

I just answered to the wrong (archived) post...

Attached is a partial fix. Put it in the cards directory and apply

Code: Select all
patch mirrodin.c mirrodin.diff
The issue was the usage of the & operator. For example

Code: Select all
if (instance->info_slot & CHOICE_ENTWINE)
evaluates the brackets to 1, 2 or 3, depending on the choice stored in instance->info_slot, but this will always be at least 1, i.e. true. Therefore you always had to pay the Entwine cost.

Geek note: applying bitwise and with mask 0b11 (0b says that the following figures will be binary) on 0b01, 0b10 or 0b11 always preserves the input value.

Now the issue is that both kill and reanimate produce a get_card_instance(255,255) dump. Can it be that the stored target is overwritten? :?

As a sidenote, the following also looks fishy to me:

Code: Select all
count_subtype(player, TYPE_LAND, -1) > 6 ? 15 : 1
This counts the number of lands if I understand it correctly (my save game had 7 and I got 7). Since the casting cost if 5B it will be 1 if you have the exact amount of lands needed or less (e.g. if you have a Sol Ring) otherwise 15. But why?
Attachments
mirrodin.zip
(1.08 KiB) Downloaded 136 times
---
Argivian Archaeologist in the Library of Leng studying the Spells of the Ancients
User avatar
FastEddie
 
Posts: 246
Joined: 24 Dec 2019, 10:59
Has thanked: 15 times
Been thanked: 19 times

Re: Betrayal of Flesh wrong etwine cost & etwine for all

Postby drool66 » 30 Jul 2020, 22:16

Fixed in 4990ec9dc ("Fix Betrayal of Flesh", 2020-07-30)
User avatar
drool66
Programmer
 
Posts: 1163
Joined: 25 Nov 2010, 22:38
Has thanked: 186 times
Been thanked: 267 times

Re: [fixed] Betrayal of Flesh wrong etwine cost & etwine for

Postby FastEddie » 31 Jul 2020, 12:21

Can you quickly elaborate what the issue was? I would like to understand where I went astray.
---
Argivian Archaeologist in the Library of Leng studying the Spells of the Ancients
User avatar
FastEddie
 
Posts: 246
Joined: 24 Dec 2019, 10:59
Has thanked: 15 times
Been thanked: 19 times

Re: [fixed] Betrayal of Flesh wrong etwine cost & etwine for

Postby drool66 » 31 Jul 2020, 15:34

Several things. Here's the diff:
Code: Select all
 
    if( event == EVENT_CAST_SPELL && affect_me(player, card) ){
       instance->number_of_targets = 0;
-      int sacced[3] = {-1};
+      char marked_for_sacrifice[151];
       if( ! check_special_flags2(player, card, SF2_COPIED_FROM_STACK) ){
          instance->info_slot = 0;
          test_definition_t test2;
@@ -481,68 +481,58 @@ Entwine
                      generic_spell(player, card, EVENT_CAN_CAST, GS_GRAVE_RECYCLER, NULL, NULL, 1, &test),
                      new_can_sacrifice_as_cost(player, card, &test2)
          };
-         int choice = DIALOG(player, card, event, DLG_RANDOM,
+         int choice = DIALOG(player, card, event, DLG_RANDOM, //DLG_AUTOCHOOSE_IF_1
                         "Kill a creature", abils[1], 10,
                         "Reanimate a creature", abils[2], 5,
-                        "Entwine", abils[1] && abils[2] && abils[3], count_subtype(player, TYPE_LAND, -1) > 6 ? 15 : 1);
+                        "Entwine", abils[1] && abils[2] && abils[3], count_subtype(player, TYPE_LAND, -1)*2);
          if( ! choice ){
             spell_fizzled = 1;
             return 0;
          }
-         if( instance->info_slot & CHOICE_ENTWINE ){
-            int i;
-            for(i=0; i<3; i++){
-               int sac = new_sacrifice(player, card, player, SAC_JUST_MARK | SAC_AS_COST | SAC_RETURN_CHOICE, &test2);
-               if( sac ){
-                  sacced[i] = sac;
-               }
-               else{
-                  spell_fizzled = 1;
-                  break;
-               }
-            }
-            for(i=0; i<3; i++){
-               if( sacced[i] != -1 ){
-                  state_untargettable(BYTE2(sacced[i]), BYTE3(sacced[i]), 0);
-               }
-            }
-            if( spell_fizzled == 1 ){
+         if( choice == CHOICE_ENTWINE ){
+            scnprintf(test2.message, 100, "Select land to sacrifice.");
+            if( mark_sacrifice(player, card, player, SAC_JUST_MARK | SAC_AS_COST | SAC_ALL_OR_NONE, &test2, marked_for_sacrifice) < 3 ){
+               spell_fizzled = 1;
                return 0;
             }
          }
       }
       instance->number_of_targets = 0;
       int base_target = 0;
-      if( instance->info_slot & CHOICE_KILL ){
-         if( pick_target(&td, "TARGET_CREATURE") ){
+      if( (instance->info_slot == CHOICE_KILL) || (instance->info_slot == CHOICE_ENTWINE) ){
+         if( new_pick_target(&td, "TARGET_CREATURE", 0, 1) ){
             base_target++;
          }
          else{
             return 0;
          }
       }
-      if( instance->info_slot & CHOICE_REANIMATE ){
+      if( (instance->info_slot == CHOICE_REANIMATE) || (instance->info_slot == CHOICE_ENTWINE) ){
          if( ! select_target_from_grave_source(player, card, player, 0, AI_MAX_CMC, &test, base_target) ){
             return 0;
          }
       }
-      if( ! check_special_flags2(player, card, SF2_COPIED_FROM_STACK) ){
-         int i;
-         for(i=0; i<3; i++){
-            kill_card(BYTE2(sacced[i]), BYTE3(sacced[i]), KILL_SACRIFICE);
+      if( ! check_special_flags2(player, card, SF2_COPIED_FROM_STACK) && instance->info_slot == CHOICE_ENTWINE ){
+         int c;
+         for (c = 0; c < active_cards_count[player]; ++c){
+            if (marked_for_sacrifice[c]){
+               get_card_instance(player, c)->state &= ~STATE_CANNOT_TARGET;
+               if (cancel != 1 && in_play(player, c))
+                  kill_card(player, c, KILL_SACRIFICE);
+            }
          }
       }
    }
 
    if(event == EVENT_RESOLVE_SPELL ){
       int base_target = 0;
-      if( instance->info_slot & CHOICE_KILL ){
-         if( valid_target(&td) ){
+      if( (instance->info_slot == CHOICE_KILL) || (instance->info_slot == CHOICE_ENTWINE) ){
+         if( validate_target(player, card, &td, 0) ){
             kill_card(instance->targets[0].player, instance->targets[0].card, KILL_DESTROY);
          }
          base_target++;
       }
-      if( instance->info_slot & CHOICE_REANIMATE ){
+      if( (instance->info_slot == CHOICE_REANIMATE) || (instance->info_slot == CHOICE_ENTWINE) ){
          int selected = validate_target_from_grave_source(player, card, player, base_target);
          if( selected != -1 ){
             reanimate_permanent(player, card, player, selected, REANIMATE_DEFAULT);
The biggest problem was that using SAC_JUST_MARK with new_sacrifice() when there is more than one thing to sacrifice will only give you the last card sacrificed in (BYTE2, BYTE3) to use them together you need to use mark_sacrifice() (which is only used on one other card). This is documented at SAC_JUST_MARK in defs.h.
But also, it used "if(valid_target())" instead of validate_target(), its sacced[] array was memset wrong, and the sacrifice prompt was just "select a card" I also made the AI selection a little less binary.
Thank you for the correction on the bitwise operators =D>
User avatar
drool66
Programmer
 
Posts: 1163
Joined: 25 Nov 2010, 22:38
Has thanked: 186 times
Been thanked: 267 times

Re: [fixed] Betrayal of Flesh wrong etwine cost & etwine for

Postby FastEddie » 31 Jul 2020, 16:16

Oh my gosh... good that you had a look at it. This would have cost me ages to figure out.
---
Argivian Archaeologist in the Library of Leng studying the Spells of the Ancients
User avatar
FastEddie
 
Posts: 246
Joined: 24 Dec 2019, 10:59
Has thanked: 15 times
Been thanked: 19 times


Return to Archived Reports

Who is online

Users browsing this forum: No registered users and 39 guests


Who is online

In total there are 39 users online :: 0 registered, 0 hidden and 39 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 39 guests

Login Form