Page 1 of 1

Challenge Cards?

PostPosted: 19 Mar 2013, 22:58
by AlphaMagnum
I'm looking to build a Birthing Pod deck in-game but I'm not sure about the best way to obtain the card.

The "Into the Pod" Challenge (found in DECK_0018_CH.wad) contains a Birthing Pod with the following effect code:

Code: Select all
    <COST type="Mana" cost="{1}{G/P}" />
    <COST type="TapSelf" />
    <COST type="generic">
      <TARGET_DEFINITION id="6">
      local filter = Object():GetFilter()
      filter:Clear()
      filter:AddCardType( CARD_TYPE_CREATURE )
      filter:SetPlayer( EffectController() )
      filter:SetZone( ZONE_IN_PLAY )
      filter:SetHint( HINT_ENEMY, EffectController() )
      filter:NotTargetted()
      </TARGET_DEFINITION>
      <TARGET_DETERMINATION>
      return AtLeastOneTargetFromDefinition(6)
      </TARGET_DETERMINATION>
      <PLAY_TIME_ACTION>
        EffectController():ChooseTarget( 6, "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", EffectDC():Make_Targets(0) )
      </PLAY_TIME_ACTION>
      <RESOLUTION_TIME_ACTION>
      local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
      if target ~= nil then
            EffectDC():Get_Targets(0):LKIShield_CardPtr(0)
            EffectController():Sacrifice(target) 
      end
      </RESOLUTION_TIME_ACTION></COST>
    <RESOLUTION_TIME_ACTION>
    if EffectDC() ~= nil then
       local sacrifice = EffectDC():Get_Targets(0):Get_CardPtr(0)
       if sacrifice ~= nil then
          local Sac_CMC = (sacrifice:GetConvertedManaCost()) + 1
          local filter = Object():GetFilter()
          local player = EffectController()
          
          player:MarkSearchedLibrary()
          filter:Clear()
          filter:SetZone( ZONE_LIBRARY )
          filter:SetPlayer( player )
          filter:AddCardType(CARD_TYPE_CREATURE)
          filter:SetConvertedCostValue(Sac_CMC)
          filter:NotTargetted()
          player:SetTargetCount( 1 )
          player:ChooseTarget( NO_VALIDATION, "CARD_QUERY_CHOOSE_CREATURE_TO_PUT_ONTO_BATTLEFIELD", EffectDC():Make_Targets(1) )
       end
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    if EffectDC() ~= nil then
       local target = EffectDC():Get_Targets(1):Get_CardPtr(0)
       if  target ~= nil then
          target:PutIntoPlay( EffectController() )
       end
    end
    </RESOLUTION_TIME_ACTION>
...I also found BlindWillow's DLC to include a version of Birthing Pod, with the following code:

Code: Select all
    <COST type="Mana" cost="{1}{G/P}" />
    <COST type="TapSelf" />
    <COST type="generic">
      <TARGET_DEFINITION id="6">
      local filter = Object():GetFilter()
      filter:Clear()
      filter:AddCardType( CARD_TYPE_CREATURE )
      filter:SetPlayer( EffectController() )
      filter:SetZone( ZONE_IN_PLAY )
      filter:SetHint( HINT_ENEMY, EffectController() )
      filter:NotTargetted()
      </TARGET_DEFINITION>
      <TARGET_DETERMINATION>
      return AtLeastOneTargetFromDefinition(6)
      </TARGET_DETERMINATION>
      <PLAY_TIME_ACTION>
      EffectController():ChooseTarget( 6, "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", EffectDC():Make_Targets(0) )
      </PLAY_TIME_ACTION>
      <RESOLUTION_TIME_ACTION>
      local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
      if target ~= nil then
      local cost = target:GetConvertedManaCost()+1
            EffectDC():Set_Int( 0, cost )
            EffectController():Sacrifice(target) 
      end
      </RESOLUTION_TIME_ACTION></COST>
    <RESOLUTION_TIME_ACTION>
    local filter = Object():GetFilter()
    local player = EffectController()
    local cost = EffectDC():Get_Int(0)
    -- The first if-then prevents the AI stupidly putting two Meliras into play.
    if player:IsAI() ~= 0 and cost == 2 then
   filter:Clear()
   filter:NotTargetted()
   filter:SetZone( ZONE_IN_PLAY )
   filter:SetController( player )
   filter:AddCardName( "MELIRA_SYLVOK_OUTCAST" )
   if filter:CountStopAt(1) ~= 0 then
      player:MarkSearchedLibrary()
      filter:Clear()
      filter:NotTargetted()
      filter:AddCardType( CARD_TYPE_CREATURE )
      filter:SetConvertedCostValue( cost )
      filter:SetZone( ZONE_LIBRARY )
      filter:SetPlayer( player )
      filter:AddCardName( "MELIRA_SYLVOK_OUTCAST" )
      filter:AddExtra( FILTER_EXTRA_FLIP_NAMES )
      player:ChooseTarget( NO_VALIDATION, "CARD_QUERY_CHOOSE_CREATURE_TO_PUT_ONTO_BATTLEFIELD", EffectDC():Make_Targets(1) )
   else
      player:MarkSearchedLibrary()
      filter:Clear()
      filter:NotTargetted()
      filter:AddCardType( CARD_TYPE_CREATURE )
      filter:SetConvertedCostValue( cost )
      filter:SetZone( ZONE_LIBRARY )
      filter:SetPlayer( player )
      player:ChooseTarget( NO_VALIDATION, "CARD_QUERY_CHOOSE_CREATURE_TO_PUT_ONTO_BATTLEFIELD", EffectDC():Make_Targets(1) )
   end
    else
   player:MarkSearchedLibrary()
   filter:Clear()
   filter:NotTargetted()
   filter:AddCardType( CARD_TYPE_CREATURE )
   filter:SetConvertedCostValue( cost )
   filter:SetZone( ZONE_LIBRARY )
   filter:SetPlayer( player )
   player:ChooseTarget( NO_VALIDATION, "CARD_QUERY_CHOOSE_CREATURE_TO_PUT_ONTO_BATTLEFIELD", EffectDC():Make_Targets(1) )
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    if EffectDC() ~= nil then
       local target = EffectDC():Get_Targets(1):Get_CardPtr(0)
       if  target ~= nil then
          target:PutIntoPlay( EffectController() )
       end
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    EffectController():ShuffleLibrary()
    </RESOLUTION_TIME_ACTION>
I'm a total novice so I can't really find the meaningful differences between these two implementations, especially since my only coding experience is an introductory University-level course in Java. I'm not sure if Wizards' version is just a hack-job meant to satisfy the requirements of the Challenge, or if it is actually a fully-functional card. BlindWillow's code is obviously intended to be fully functional, but once again I don't know if that is actually the case.

Which of these two cards is best implemented, in your opinion?

Also, where would you suggest I go to learn the language used in coding these cards? If there are no meaningful changes between DotP 2013 and 2014, I could carry my new knowledge over to create cards in the new game when it comes out.

Re: Challenge Cards?

PostPosted: 19 Mar 2013, 23:36
by thefiremind
AlphaMagnum wrote:I'm a total novice so I can't really find the meaningful differences between these two implementations, especially since my only coding experience is an introductory University-level course in Java. I'm not sure if Wizards' version is just a hack-job meant to satisfy the requirements of the Challenge, or if it is actually a fully-functional card. BlindWillow's code is obviously intended to be fully functional, but once again I don't know if that is actually the case.
As far as I can see, in this case Wizards didn't use hacks, but BlindWillow used one because he probably saw the AI using Birthing Pod to make Melira, Sylvok Outcast enter the battlefield while it was already controlling a copy of Melira... which is plain dumb of course. With a bit of work, the code could be modified so that the AI can't choose any legendary creature for which it already controls a copy, but it seems a bit exaggerated to me: I'd say, test your deck with a "base version" of Birthing Pod and see if you really need to guide the AI so much. Apart from that, BlindWillow also chose to store the converted mana cost in a register instead of storing a pointer to the sacrificed creature and retrieve the cmc later, which is an easier and safer approach.

So my advice would be to use a mix of the two implementations:
Code: Select all
    <COST type="Mana" cost="{1}{G/P}" />
    <COST type="TapSelf" />
    <COST type="generic">
      <TARGET_DEFINITION id="6">
      local filter = Object():GetFilter()
      filter:Clear()
      filter:AddCardType( CARD_TYPE_CREATURE )
      filter:SetPlayer( EffectController() )
      filter:SetZone( ZONE_IN_PLAY )
      filter:SetHint( HINT_ENEMY, EffectController() )
      filter:NotTargetted()
      </TARGET_DEFINITION>
      <TARGET_DETERMINATION>
      return AtLeastOneTargetFromDefinition(6)
      </TARGET_DETERMINATION>
      <PLAY_TIME_ACTION>
        EffectController():ChooseTarget( 6, "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", EffectDC():Make_Targets(0) )
      </PLAY_TIME_ACTION>
      <RESOLUTION_TIME_ACTION>
      local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
      if target ~= nil then
            EffectDC():Set_Int( 2, target:GetConvertedManaCost()+1 )
            EffectController():Sacrifice(target) 
      end
      </RESOLUTION_TIME_ACTION></COST>
    <RESOLUTION_TIME_ACTION>
    if EffectDC() ~= nil then
       local Sac_CMC = EffectDC():Get_Int(2)
       local filter = Object():GetFilter()
       local player = EffectController()

       player:MarkSearchedLibrary()
       filter:Clear()
       filter:SetZone( ZONE_LIBRARY )
       filter:SetPlayer( player )
       filter:AddCardType( CARD_TYPE_CREATURE )
       filter:SetConvertedCostValue( Sac_CMC )
       filter:NotTargetted()
       player:ChooseTarget( NO_VALIDATION, "CARD_QUERY_CHOOSE_CREATURE_TO_PUT_ONTO_BATTLEFIELD", EffectDC():Make_Targets(1) )
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    local target = EffectDC() and EffectDC():Get_Targets(1) and EffectDC():Get_Targets(1):Get_CardPtr(0)
    if target ~= nil then
       target:PutIntoPlay( EffectController() )
    end
    </RESOLUTION_TIME_ACTION>
Just for your information, on the last action I used the power of the logical operators in Lua to remove the exceeding "if" checks: (A and B and C) returns C if no operand is nil, otherwise it returns nil, and even if both B and C need the previous operands to be called, the "short-circuit rule" stops the evaluation at the first nil it meets because there's no reason to look at the other operands. This prevents nil-pointer exceptions from firing with no reason.
On a side note, the "short-circuit rule" is effective also in Java, which you already know: when A is false in (A && B), the interpreter doesn't bother B at all because the result of the logical operation has been already decided.

AlphaMagnum wrote:Also, where would you suggest I go to learn the language used in coding these cards? If there are no meaningful changes between DotP 2013 and 2014, I could carry my new knowledge over to create cards in the new game when it comes out.
The changes between DotP2012 and 2013 weren't that many, so you can definitely carry your knowledge over.
I didn't know about Lua language before starting to mod DotP2012, and I learned how it works just by looking at the existing cards' code. After all, it's a sort of C++ with a lot of freedom on variables (you don't need to declare the data type, any variable can contain any type), and I already knew enough of C++ (and Java which is similar as well). If you programmed in Java you shouldn't have problems understanding the code, you just have to become familiar with the functions offered by the game executable, but it's just like learning the contents of a new C++/Java/whatever-language library. :wink:

Re: Challenge Cards?

PostPosted: 20 Mar 2013, 03:32
by AlphaMagnum
Thanks for the heads up! I'm trying to work in a Phantasmal Image-based Birthing Pod chain, so I have one question about that:

I know in paper MTG that clones should copy their target's converted mana cost. One of the key elements of this chain is the following:

Phantasmal Image (CMC 2) ETBs and copies Deceiver Exarch (CMC 3).
The "Phantasmal Exarch" (should be CMC 3) untaps Birthing Pod, and we use the Pod to sacrifice it for a Restoration Angel (CMC 4).
Resto Angel then blinks the original Deceiver Exarch, which untaps Birthing Pod upon re-entry so we can use it again to sac the Angel for Kiki-Jiki.

The above is only possible if:
1) Clone effects in DotP 2013 copy CMC as intended.
2) The copied CMC is retained in code somehow once the creature is sacrificed to Birthing Pod.

Do you know if things would work that way in-game?

Re: Challenge Cards?

PostPosted: 20 Mar 2013, 03:48
by sumomole
AlphaMagnum wrote:1) Clone effects in DotP 2013 copy CMC as intended.
2) The copied CMC is retained in code somehow once the creature is sacrificed to Birthing Pod.
1) Yes
2) Yes

Re: Challenge Cards?

PostPosted: 20 Mar 2013, 10:02
by thefiremind
This is a perfect way to re-test what pcastellazzi found some time ago: after a duel where you brought a Clone or similar creature in play through Birthing Pod, could you please check if a SCRIPT_LOG.TXT appeared in your game directory? I'm curious to see if that apparently nonsense nil-pointer exception is still raised with your (our? :lol:) implementation of Birthing Pod.

Re: Challenge Cards?

PostPosted: 21 Mar 2013, 22:16
by AlphaMagnum
thefiremind wrote:This is a perfect way to re-test what pcastellazzi found some time ago: after a duel where you brought a Clone or similar creature in play through Birthing Pod, could you please check if a SCRIPT_LOG.TXT appeared in your game directory? I'm curious to see if that apparently nonsense nil-pointer exception is still raised with your (our? :lol:) implementation of Birthing Pod.
Um...I have a SCRIPT_LOG.TXT file full of the following:

[lua] ?:0: attempt to index field '?' (a nil value)

It's literally a 600kb txt file that consists of repeats of the above line.

Additionally, for some reason this new implementation of Birthing Pod doesn't seem to let me use the ability on my opponent's turn. The first time I thought it was like 'summoning sickness' for artifacts, but there were no swirlies (which usually indicate summoning sickness) over the card and my inability to use it on my opponent's turn persisted, despite having more than enough mana to use the ability. The card only gains the orange highlighting on my turn.

What do you think is wrong?

Re: Challenge Cards?

PostPosted: 21 Mar 2013, 22:51
by thefiremind
AlphaMagnum wrote:Um...I have a SCRIPT_LOG.TXT file full of the following:

[lua] ?:0: attempt to index field '?' (a nil value)
This isn't the error I was talking about, and finding the source of this error is really hard since there is no clue at all... you should make a test deck and include only a small part of the cards, so you can find the culprit by exclusion.

AlphaMagnum wrote:Additionally, for some reason this new implementation of Birthing Pod doesn't seem to let me use the ability on my opponent's turn.
There's nothing wrong... have you read the last sentence of the ability? :roll: :mrgreen:

Re: Challenge Cards?

PostPosted: 22 Mar 2013, 02:37
by AlphaMagnum
thefiremind wrote:
AlphaMagnum wrote:Um...I have a SCRIPT_LOG.TXT file full of the following:

[lua] ?:0: attempt to index field '?' (a nil value)
This isn't the error I was talking about, and finding the source of this error is really hard since there is no clue at all... you should make a test deck and include only a small part of the cards, so you can find the culprit by exclusion.

AlphaMagnum wrote:Additionally, for some reason this new implementation of Birthing Pod doesn't seem to let me use the ability on my opponent's turn.
There's nothing wrong... have you read the last sentence of the ability? :roll: :mrgreen:
I will try and make a test deck to investigate this issue further.

And thanks for the reminder! I can't believe I missed that...I feel really silly lol.