It is currently 11 Sep 2025, 06:37
   
Text Size

New keyword: spDestroyAll

Post MTG Forge Related Programming Questions Here

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

New keyword: spDestroyAll

Postby Sloth » 15 Aug 2010, 17:24

I've added a new keyword: spDestroyAll

spDestroyAll:<AffectedType>:<Options>

<AffectedType>: takes all the restrictions of spDestroyTgt.

<Options>: Only NoRegen is supported at the moment.

The AI will use these spells if at least 2 more human permanents will be destroyed. That means that some spells like Armageddon should not be converted, but most of the other spells have the same restrictions (Wrath of God) or none at all (Purify).

Here is the code:
Code: Select all
        // Generic destroy all card
        if(hasKeyword(card, "spDestroyAll") != -1) {
            int n = hasKeyword(card, "spDestroyAll");
           
            String parse = card.getKeyword().get(n).toString();
            card.removeIntrinsicKeyword(parse);
           
            String k[] = parse.split(":");
            String Targets = k[1]; // Artifact, Creature, Enchantment, Land, Permanent, White, Blue, Black, Red, Green, Colorless, MultiColor
            // non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent,
            //non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor
            final String Tgts[] = Targets.split(",");
           
            final boolean NoRegen = (k.length == 3);
           
            card.clearSpellAbility();
           
            final SpellAbility spDstryAll = new Spell(card) {
                private static final long serialVersionUID = 132554543614L;
               
                @Override
                public boolean canPlayAI() {
                    CardList human = new CardList(AllZone.Human_Play.getCards());
                    CardList computer = new CardList(AllZone.Computer_Play.getCards());
                   
                    human = human.getValidCards(Tgts);
                    human = human.getNotKeyword("Indestructible");
                    computer = computer.getValidCards(Tgts);
                    computer = computer.getNotKeyword("Indestructible");
                   
                    // the computer will at least destroy 2 more human permanents
                    return  AllZone.Phase.getPhase().equals(Constant.Phase.Main2) &&
                          (computer.size() < human.size() - 1);
                }

                @Override
                public void resolve() {
                    CardList all = new CardList();
                    all.addAll(AllZone.Human_Play.getCards());
                    all.addAll(AllZone.Computer_Play.getCards());
                    all = all.getValidCards(Tgts);
                   
                    CardListUtil.sortByIndestructible(all);
                    CardListUtil.sortByDestroyEffect(all);
                   
                    for(int i = 0; i < all.size(); i++) {
                        Card c = all.get(i);
                        if(NoRegen) AllZone.GameAction.destroyNoRegeneration(c); else AllZone.GameAction.destroy(c);
                    }
                }// resolve()

            }; //SpDstryAll
           
           
            card.setSVar("PlayMain1", "TRUE");
            card.addSpellAbility(spDstryAll);           

        }//spDestroyAll
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: New keyword: spDestroyAll

Postby Rob Cashwalker » 16 Aug 2010, 00:18

Nice work.

I would suggest changing
final boolean NoRegen = (k.length == 3);
to actually check for "NoRegen" so other options can be added without changing much code.

Edit - For example, add Drawback as an option.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: New keyword: spDestroyAll

Postby Chris H. » 17 Aug 2010, 20:14

Sloth wrote:I've added a new keyword: spDestroyAll

spDestroyAll:<AffectedType>:<Options>

<AffectedType>: takes all the restrictions of spDestroyTgt.

<Options>: Only NoRegen is supported at the moment.

The AI will use these spells if at least 2 more human permanents will be destroyed. That means that some spells like Armageddon should not be converted, but most of the other spells have the same restrictions (Wrath of God) or none at all (Purify).
`
I converted 4 spells to the spDestroyAll keyword.

Acid Rain
Boil
Boiling Seas
Flashfires

These spells use a different AI test. It only checks to see if the human has > 3 of the affected land type in play. I thought about it and decided that we humans are likely to play multi-color decks more often than single color decks. And these four cards will not appear in a randomly generated deck.

So, the spDestroyAll AI test may be enough. What do other people think?
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: New keyword: spDestroyAll

Postby Chris H. » 17 Aug 2010, 23:39

We have a code block with a number of spells:

Akroma's Vengeance
Devastation
Jokulhaups
Purify
Shatterstorm
Obliterate

I commented out the code block and tried to convert Akroma's Vengeance. The card now looks like this:

Akroma's Vengeance
4 W W
Sorcery
Destroy all artifacts, creatures, and enchantments.
spDestroyAll:Artifact,Creature,Enchantment
Cycling:3
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/akromas_vengeance.jpg
`
It worked in a test game, except for one thing. When this spell is cast, it brings up a choose window where we get to select the spDestroyAll or the Cycling SpellAbility. Having the spell description on the fourth line, well, the spDestroyAll spell description will not appear in the choose window. In the original code block there is a test for this card and it sets the spell description via:

Code: Select all
spell.setDescription("Destroy all artifacts, creatures, and enchantments.");
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: New keyword: spDestroyAll

Postby Rob Cashwalker » 18 Aug 2010, 00:21

The original spDestroyTgt that Sloth has based these keywords on, assumed very simple spells using just the normal card text.

I am revising spDestroyTgt right now to support Drawback. I will also look into making sure these spells set their descriptions.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: New keyword: spDestroyAll

Postby Sloth » 18 Aug 2010, 07:54

Rob Cashwalker wrote:I am revising spDestroyTgt right now to support Drawback. I will also look into making sure these spells set their descriptions.
Thanks Rob!

I just converted Rebuild to keyword and the Cycling choice works fine.

I will now start to improve canPlayAI for spDestroyAll.

My first draft is:

X = number of permanents + total CMC + number of lands (human)

and if the computers life is below 7 add the total power of the human creatures (which should make a huge difference).

Y = number of permanents + total CMC + number of lands (computer)

canPlayAI returns true if Y < X - 3.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: New keyword: spDestroyAll

Postby Chris H. » 18 Aug 2010, 13:11

Rob Cashwalker wrote:The original spDestroyTgt that Sloth has based these keywords on, assumed very simple spells using just the normal card text.

I am revising spDestroyTgt right now to support Drawback. I will also look into making sure these spells set their descriptions.
`
I merged Rob's work into my local copy and was able to convert over a few more spells.

However, Obliterate does not display it's "CARDNAME can't be countered." keyword. We had in the past several other keywords that failed to show up in the text panel. I should be able to add this additional keyword to the proper section in card.getText(), or at least I think that I can fix it this way. We will see. :D
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: New keyword: spDestroyAll

Postby Rob Cashwalker » 18 Aug 2010, 13:32

I originally assigned card.getText to the spell description, then card.setText("").
Now, I noticed that there's card.getSpellText, which seems like it should return the "printed" text, as opposed to the parsed, generated text.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: New keyword: spDestroyAll

Postby Chris H. » 18 Aug 2010, 16:38

Rob Cashwalker wrote:I originally assigned card.getText to the spell description, then card.setText("").
Now, I noticed that there's card.getSpellText, which seems like it should return the "printed" text, as opposed to the parsed, generated text.
`
That might solve the problem. We should check into this and see if it makes a difference at some point.
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: New keyword: spDestroyAll

Postby Rob Cashwalker » 18 Aug 2010, 17:28

The code I submitted last night uses it. So if it's not working now, then I don't know what it should do.

The DestroyTgt and BounceTgt code relies on the wording "Destroy/Return target ____" being at the beginning of the printed text. The "____" is inserted into the input prompt.
Without using the card text (relying on the description coming from the keyword line itself, then I would need another parameter of SVar to provide the "____".
After using the card.getSpellText for the spellDescription, it uses card.setText("") to clear it. (so it doesn't appear twice from card.getText() - once from the printed text and then from the SpellAbility)

The DestroyAll and BounceAll code just sucks up the card.getSpellText, and then clears it. It doesn't need the printed text for anything else.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: New keyword: spDestroyAll

Postby Chris H. » 19 Aug 2010, 00:46

I had problems converting Guan Yu's 1,000-Li March to keyword. It would not display the spell text. The card worked and would kill tapped creatures. I looked at your message and realized that I would have to change the cards.txt entry to this:

Guan Yu's 1,000-Li March
4 W W
Sorcery
Destroy all creatures that are tapped.
spDestroyAll:Creature.tapped
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/guan_yus_1000_li_march.jpg
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: New keyword: spDestroyAll

Postby Rob Cashwalker » 21 Aug 2010, 03:31

I just added drawback handling to spDestroyAll.

This was my test card:
Code: Select all
Hellfire
2 B B B
Sorcery
Destroy all nonblack creatures. Hellfire deals X plus 3 damage to you, where X is the number of creatures put into all graveyards this way.
spDestroyAll:Creature.nonBlack:Drawback$DamageYou/X.Plus.3
SVar:Rarity:Rare
There are a handful of cards with drawbacks we can handle. I think all or almost all of them involve the number of cards the spell actually destroyed, so that is the number being passed as "X".

To actually count some other criteria, use "dX" and an SVar to define the Count$.

Doing this card also revealed some bugs in the doDrawback math handling code, so I had to debug those before proving the actual functionality.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: New keyword: spDestroyAll

Postby Chris H. » 07 Sep 2010, 19:20

Rob Cashwalker wrote:I just added drawback handling to spDestroyAll.

This was my test card:
Code: Select all
Hellfire
2 B B B
Sorcery
Destroy all nonblack creatures. Hellfire deals X plus 3 damage to you, where X is the number of creatures put into all graveyards this way.
spDestroyAll:Creature.nonBlack:Drawback$DamageYou/X.Plus.3
SVar:Rarity:Rare
There are a handful of cards with drawbacks we can handle. I think all or almost all of them involve the number of cards the spell actually destroyed, so that is the number being passed as "X".

To actually count some other criteria, use "dX" and an SVar to define the Count$.

Doing this card also revealed some bugs in the doDrawback math handling code, so I had to debug those before proving the actual functionality.
`
I spent some time trying to figure out the SVar for Hellfire. I assume that this would do it:

SVar:X:Count$TypeOnBattlefield.Creature.nonBlack
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: New keyword: spDestroyAll

Postby friarsol » 07 Sep 2010, 19:30

Chris H. wrote:I spent some time trying to figure out the SVar for Hellfire. I assume that this would do it:

SVar:X:Count$TypeOnBattlefield.Creature.nonBlack
That doesn't account for Indestructible creatures or creatures that regenerated from the Hellfire (and possibly others).
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: New keyword: spDestroyAll

Postby Chris H. » 07 Sep 2010, 20:03

friarisol wrote:That doesn't account for Indestructible creatures or creatures that regenerated from the Hellfire (and possibly others).
`
I had considered:

SVar:X:Count$TypeInAllYards.Creature.nonBlack

but this version also has problems determining the correct number of X. And I am not sure when X is calculated, although I assume that it is equal to the number of cards in the list of valid targets.
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Next

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 20 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 20 users online :: 0 registered, 0 hidden and 20 guests (based on users active over the past 10 minutes)
Most users ever online was 7967 on 09 Sep 2025, 23:08

Users browsing this forum: No registered users and 20 guests

Login Form