It is currently 14 Jul 2025, 02:18
   
Text Size

spPumpTgt - Targeted Pump Spells

Post MTG Forge Related Programming Questions Here

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

spPumpTgt - Targeted Pump Spells

Postby Rob Cashwalker » 17 Jul 2009, 14:06

Spells which follow the syntax "Target creature [gets | gains] [+p/+t | keyword] [and gains keyword] until end of turn.

In other words, it supports p/t pumps:

Giant Growth
G
Instant
Target creature gets +3/+3 until end of turn.
spPumpTgt:+3/+3

Or p/t/k pumps:

Wildsize
2 G
Instant
Target creature gets +2/+2 and gains trample until end of turn.
spPumpTgt:+2/+2/Trample

or just keyword pumps:

Accelerate
1 R
Instant
Target creature gains haste until end of turn.#Draw a card.
spPumpTgt:Haste
Cantrip

Code: Select all
    private final int shouldSpPumpTgt(Card c){
       ArrayList<String> a = c.getKeyword();
       for (int i = 0; i < a.size(); i++)
          if (a.get(i).toString().startsWith("spPumpTgt"))
             return i;
       
       return -1;
    }
Code: Select all
    // Generic target creature pump
    if (shouldSpPumpTgt(card) != -1)
    {
       int n = shouldSpPumpTgt(card);
       
       String parse = card.getKeyword().get(n).toString();
       card.removeIntrinsicKeyword(parse);
       
       String k[] = parse.split(":");
       String ptk[] = k[1].split("/");
       
       final int attack[] = {0};
       final int defense[] = {0};
       final String keyword[] = {"none"};
       
       if (ptk.length == 1)
          keyword[0] = ptk[0];
       
       if (ptk.length >= 2)
       {
          attack[0] = Integer.parseInt(ptk[0].replace("+", ""));
          defense[0] = Integer.parseInt(ptk[1].replace("+", ""));
       }
       
       if (ptk.length == 3)
          keyword[0] = ptk[2];
       
/*        String Desc = new String();
        Desc = "Target creature ";
        if (attack[0] != 0 || defense[0] != 0)
        {
           Desc = Desc + "gets ";
           if (attack[0] > 0)
              Desc = Desc + "+" + attack[0];
           else
              Desc = Desc + attack[0];
           Desc = Desc + "/";
           if (defense[0] > 0)
              Desc = Desc + "+" + defense[0];
           else
              Desc = Desc + defense[0];
           
           if (! keyword[0].equals("none"))
              Desc = Desc + " and ";
        }
        if (! keyword[0].equals("none"))
           Desc = Desc + "gains " + keyword;
       
        Desc = Desc + " until end of turn.";
*/       
       SpellAbility spPump = new Spell(card)
       {
          private static final long serialVersionUID = 42244224L;
          
          public boolean canPlayAI()
          {
             Card c = getAttacker();
             if (c != null)
             {
                setTargetCard(c);
                return true;
             }
             else
                return false;
          }
          
          public Card getAttacker()
          {
             Combat c = ComputerUtil.getAttackers();
             
             CardList list = new CardList(c.getAttackers());
             CardListUtil.sortFlying(list);
             
             list = list.filter(new CardListFilter()
             {
                public boolean addCard(Card c)
                {
                        return (CardFactoryUtil.canTarget(card, c)) &&
                        (! c.getKeyword().contains(keyword[0])) &&
                        (! c.hasSickness() && keyword[0].equals("Haste"));
                }
             });
             
             if (list.size() > 0)
                return list.get(0);
             else
                return null;
          }
          
          public void resolve()
          {
             final Card[] target = new Card[1];
             
             final Command untilEOT = new Command()
             {
                private static final long serialVersionUID = -42244224L;
                
                public void execute()
                {
                   if (AllZone.GameAction.isCardInPlay(target[0]))
                   {
                      target[0].addTempAttackBoost(-attack[0]);
                      target[0].addTempDefenseBoost(-defense[0]);
                      
                      if (!keyword[0].equals("none"))
                         target[0].removeExtrinsicKeyword(keyword[0]);
                   }
                }
             };
             
             target[0] = getTargetCard();
             if (AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0]))
                {
                   target[0].addTempAttackBoost(attack[0]);
                   target[0].addTempDefenseBoost(defense[0]);
                   if (!keyword[0].equals("none"))
                      target[0].addExtrinsicKeyword(keyword[0]);
                   
                   AllZone.EndOfTurn.addUntil(untilEOT);
                }
          }
       };
       
       spPump.setBeforePayMana(CardFactoryUtil.input_targetCreature(spPump));
       //spPump.setDescription(Desc);
       card.clearSpellAbility();
       card.addSpellAbility(spPump);
    }
I commented out the Description generation because I don't think it's necessary, because the card text is there, but just in case, it's included if necessary.

I've tested it a little bit with Giant Growth and Wildsize both human and AI.
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: spPumpTgt - Targeted Pump Spells

Postby Sloth » 18 Jul 2009, 14:59

Great! A lot new cards can be added!

I'm not finished checking but here are some instants I found, that can now be added to cards.txt:

Code: Select all
Silk Net
G
Instant
Target creature gets +1/+1 and gains reach until end of turn.
spPumpTgt:+1/+1/Reach

Predator's Strike
1 G
Instant
Target creature gets +3/+3 and gains trample until end of turn.
spPumpTgt:+3/+3/Trample

Kindled Fury
R
Instant
Target creature gets +1/+0 and gains first strike until end of turn.
spPumpTgt:+1/+0/First Strike

Fists of the Anvil
1 R
Instant
Target creature gets +4/+0 until end of turn.
spPumpTgt:+4/+0

Fanatical Fever
2 G G
Instant
Target creature gets +3/+0 and gains trample until end of turn.
spPumpTgt:+3/+0/Trample

Colossal Might
R G
Instant
Target creature gets +4/+2 and gains trample until end of turn.
spPumpTgt:+4/+2/Trample
I will try to find some more and hope that abTgtPTPump gets fixed in the next version.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: spPumpTgt - Targeted Pump Spells

Postby DennisBergkamp » 19 Jul 2009, 10:38

Nice one Rob, I'm adding this stuff in right now :)
And thank you Sloth for those extra cards!
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: spPumpTgt - Targeted Pump Spells

Postby Rob Cashwalker » 20 Jul 2009, 04:54

Cool. Like I said I only did some limited testing, and the AI might not fully appreciate all the possibilities. It certainly (as with all "pumps") doesn't do negative-only pumps. In fact, now that I think about it, (and look down at the post) I forgot to put in the usual check to see with the defense would be reduced below zero.

Dennis - do you know what the abTgtPump bug is that Sloth mentioned?
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: spPumpTgt - Targeted Pump Spells

Postby Sloth » 20 Jul 2009, 12:42

Here are a few more for cards.txt:

Code: Select all
Wielding the Green Dragon
1 G
Sorcery
Target creature gets +4/+4 until end of turn.
spPumpTgt:+4/+4

Screaming Fury
2 R
Sorcery
Target creature gets +5/+0 and gains haste until end of turn.
spPumpTgt:+5/+0/Haste

Sangrite Surge
4 R G
Sorcery
Target creature gets +3/+3 and gains double strike until end of turn.
spPumpTgt:+3/+3/Double Strike

Monstrous Growth
1 G
Sorcery
Target creature gets +4/+4 until end of turn.
spPumpTgt:+4/+4

Howling Fury
2 B
Sorcery
Target creature gets +4/+0 until end of turn.
spPumpTgt:+4/+0

Fit of Rage
1 R
Sorcery
Target creature gets +3/+3 and gains first strike until end of turn.
spPumpTgt:+3/+3/First Strike

Sudden Strength
3 G
Instant
Target creature gets +3/+3 until end of turn.#Draw a card.
spPumpTgt:+3/+3
Cantrip
This time I figured that negative-only pumps are not AI-friendly and omitted them.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: spPumpTgt - Targeted Pump Spells

Postby Sloth » 20 Jul 2009, 12:58

I found even more:
Code: Select all
Cloak of Feathers
U
Sorcery
Target creature gains flying until end of turn.#Draw a card.
spPumpTgt:Flying
Cantrip

Unnatural Speed
R
Instant
Target creature gains haste until end of turn.
spPumpTgt:Haste

Shriek of Dread
1 B
Instant
Target creature gains fear until end of turn.
spPumpTgt:Fear

Shadow Rift
U
Instant
Target creature gains shadow until end of turn.#Draw a card.
spPumpTgt:Shadow
Cantrip

Leap
U
Instant
Target creature gains flying until end of turn.#Draw a card.
spPumpTgt:Flying
Cantrip

Lace with Moonglove
2 G
Instant
Target creature gains deathtouch until end of turn.#Draw a card.
spPumpTgt:Deathtouch
Cantrip

Jump
U
Instant
Target creature gains flying until end of turn.
spPumpTgt:Flying

Double Cleave
1 RW
Instant
Target creature gains double strike until end of turn.
spPumpTgt:Double Strike

Breach
2 B
Instant
Target creature gets +2/+0 and gains fear until end of turn.
spPumpTgt:+2/+0/Fear

Accelerate
R
Instant
Target creature gains haste until end of turn.#Draw a card.
spPumpTgt:Haste
Cantrip
I guess multiple keywords is not implemented, but what's with cycling spells - do they work now?
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: spPumpTgt - Targeted Pump Spells

Postby Rob Cashwalker » 20 Jul 2009, 15:57

The trick with multiple keywords, like spPumpTgt and Cycling is that the order of processing in CardFactory.java needs to be changed. The permanent ability keywords need to be first. Then the spell keywords need to be second. Then the "tack-on" keywords need to be processed last, possibly at the very end of CardFactory, allowing for "tack-ons" to be used for explicitly coded cards.

Cantrip isn't implemented like the others. It's checked upon resolution of any spell - if the card contains the keyword, then it just draws a card. Quite separately from any other card code.

The tricky part I've been trying to think about lately, is the Charms or Commands. Each individual ability of Chaos Charm for example, is something that we have keywords for. But we can't just do it like this:

Chaos Charm
R
Instant
Choose one - Destroy target Wall; or Chaos Charm deals 1 damage to target creature; or target creature gains haste until end of turn.
spDestroyTgt:Creature.Wall
spDamageC:1 (OK, we don't have creature-only damage yet, but it's easy enough)
spPumpTgt:Haste

Because each of the sp___ code blocks clears out the spell abilities of the card. (because all cards are assumed to be permanents, and given a default spell ability to be put into play).
So it would process spDestroyTgt (never mind the fact that the code needs the text formatted a certain way in order to extract the input dialog text) removing the default ability.
Then it would process the spDamageC ability, removing the spDestroyTgt abilty.
Then it would process the spPumpTgt ability, removing the spDamageC ability.
And that's just a rough example, because that's not the order of code blocks... spDamageC would be first, up by the spDamageCP and spDamageP blocks; then spDestroyTgt, and spPumpTgt would probably be inserted last when Dennis merges it.

I think the best way to handle this may be something like the following:
Code: Select all
public boolean hasSpKeyword()
{
  ArrayList k = card.getKeywords();
  for (i = 0; i < k.length; i++)
    if (k(i).startsWith("sp")
      return true;
  return false;
}
Code: Select all
if (hasSpKeyword)
{
   card.clearSpellAbility();

   if (shouldSpDamageCP)
   {
      ...
   }
   if (shouldSpDamageP)
   {
      ...
   }
   if (shouldSpDestroyTgt)
   {
      ...
   }
   if (shouldSpPumpTgt)
   {
      ...
   }
   ...
      etc
   ...
}
Then remove the clearSpellAbility() from each individual code block. Oh, and make sure each one has a spell.setDescription().

When you go to play the spell, the game will now present each spell option. This won't work for the Commands, which want two choices... but that's OK... for now.
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: spPumpTgt - Targeted Pump Spells

Postby MageKing17 » 20 Jul 2009, 17:44

That's really not the way you want to do choice spells. What if you had a spell that said "Destroy target wall. CARDNAME deals 1 damage to target creature. Target creature gains haste"? You couldn't make it do all those things just by using spDestroyTgt, spDamageC, and spPumpTgt. In Incantus, modal spells are handled a bit oddly... since all abilities are declared with the help of decorators, we just add another decorator to the effects block that defines it as modal and lists all the various modes (with each mode's doc text determining what text it displays, and the decorator having a "choose" argument to determine how many modes can be selected). The annoying thing is that "choose one or both" can't be done... instead, we have to add a third mode saying "both", and make sure to put a timestep inbetween each action (because if you choose two modes, each one happens one after the other, not simultaneously).
User avatar
MageKing17
Programmer
 
Posts: 473
Joined: 12 Jun 2008, 20:40
Has thanked: 5 times
Been thanked: 9 times

Re: spPumpTgt - Targeted Pump Spells

Postby DennisBergkamp » 20 Jul 2009, 21:52

Dennis - do you know what the abTgtPump bug is that Sloth mentioned?
I have no idea, I was hoping you would :(
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: spPumpTgt - Targeted Pump Spells

Postby Rob Cashwalker » 21 Jul 2009, 05:00

MageKing17 wrote:That's really not the way you want to do choice spells. What if you had a spell that said "Destroy target wall. CARDNAME deals 1 damage to target creature. Target creature gains haste"? You couldn't make it do all those things just by using spDestroyTgt, spDamageC, and spPumpTgt. In Incantus, modal spells are handled a bit oddly... since all abilities are declared with the help of decorators, we just add another decorator to the effects block that defines it as modal and lists all the various modes (with each mode's doc text determining what text it displays, and the decorator having a "choose" argument to determine how many modes can be selected). The annoying thing is that "choose one or both" can't be done... instead, we have to add a third mode saying "both", and make sure to put a timestep inbetween each action (because if you choose two modes, each one happens one after the other, not simultaneously).
I know, I know. But here's the thing - the way MTGForge is right now, simple choice spells are super easy. The hard ones are where a sequence of simple actions are done... if only there was a way to take an existing object's resolve method and "add to it"....

Frankly, there's probably a way to do this, if the actual code weren't tied directly into the object definitions... so there's one spell object definition, but it could dynamically include code from other methods....

Most mechanics will have some basic implementation and then variants with additional actions. Some mechanics have more variations than others.
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: spPumpTgt - Targeted Pump Spells

Postby zerker2000 » 26 Jul 2009, 12:35

I think I experimented with something like
Code: Select all
ArrayList<Command> onResolveCommands
in Ability_Mana, which could be added to SpellAbility ... in fact, I think the optimal way to code SpellAbilities would be one big ArrayList<Command>, with the possibility of modular coices implemented through a Command that had the e.g."Choose on or both" Input in its execute().
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.


--Eladamri, the Seed of Freyalise
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: spPumpTgt - Targeted Pump Spells

Postby Chris H. » 06 Aug 2009, 12:36

`
spPumpTgt and negative buffs


As a test, I added the following card to cards.txt:

Last Gasp
1 B
Instant
Target creature gets -3/-3 until end of turn.
spPumpTgt:-3/-3

I created a test deck with Last Gasp, Moor Fiend and Mox Jet. I assigned this deck to both the computer and to myself.

I can cast the Last Gasp and kill the computer's Moor Fiend. The spPumpTgt keyword code can handle negative buffs.

The computer will not cast the Last Gasp on it's own Moor Fiend or on my Moor Fiend. The card just sits unused in the computer's hand as a dead card. I originally suspected that the computer might target it's own creature.

While I have spent a lot of time looking at the source code, most of it is beyond my comprehension. I have seen the messages stating that the code base does not have the framework/hooks that would allow the computer to use these types of spells/abilities to the best effect.


We could add the following cards via keywords:

Afflict
Bewilder
Disorient
Flowstone Strike
Last Gasp
Pull Under
Shrink

and include the names of these cards in the listing of cards that will not be included in randomly constructed decks for the computer. This is the best compromise that I can come up with at this time.
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: spPumpTgt - Targeted Pump Spells

Postby Rob Cashwalker » 06 Aug 2009, 16:53

The basic pump code works fine for negative values for the human. But the AI doesn't know what to do with it.

The AI could be tweaked to just take a look at the numbers and choose a human creature accordingly. However, I see one reason not to do this: there is almost no point to applying a negative attack value, since the computer can't do it on the human's turn. Only if it's a negative defense value would it be useful right now. Because of this, I'd rather give the ability a new name, not "pump". Maybe take a page from M10 - Degrade.
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: spPumpTgt - Targeted Pump Spells

Postby Chris H. » 07 Aug 2009, 00:11

Thank you Rob for the explanation. We can hold off of adding the negative value power pumps for this moment. :)


On a related note, I tested a deck with Giant Growth and the computer will not cast it on it's own Kird Ape.

It appears that the spPumpTgt keyword creates a dead card that the computer can not play, whether or not the Power buff/boost is negative or positive. :?:
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: spPumpTgt - Targeted Pump Spells

Postby mtgrares » 07 Aug 2009, 17:29

It appears that the spPumpTgt keyword creates a dead card that the computer can not play, whether or not the Power buff/boost is negative or positive
I don't know about the spPumpTgt directly but the computer plays cards if SpellAbility.canPlay() returns true and if SpellAbility.canPlayAI() returns true. More than likely your problem is somewhere in there.
mtgrares
DEVELOPER
 
Posts: 1352
Joined: 08 Sep 2008, 22:10
Has thanked: 3 times
Been thanked: 12 times

Next

Return to Developer's Corner

Who is online

Users browsing this forum: Edwardfab and 36 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 37 users online :: 1 registered, 0 hidden and 36 guests (based on users active over the past 10 minutes)
Most users ever online was 5050 on 26 Jun 2025, 06:02

Users browsing this forum: Edwardfab and 36 guests

Login Form