It is currently 09 Sep 2025, 04:45
   
Text Size

abPump[Tgt] Keyword

Post MTG Forge Related Programming Questions Here

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

Re: abPump[Tgt] Keyword

Postby Chris H. » 15 Feb 2010, 01:25

I noticed something strange recently with the abPumpTgt keyword. I have not had a chance to examine the code. I added the Granger Guildmage and when I looked at the text description I saw the word "gains" appear twice.

W, tap: Target creature gains gains First Strike until end of turn.
Granger Guildmage deals 1 damage to target creature or player and 1 damage to you.
`
Stun Sniper does not have a text description and instead states "none". Yet the Storm Spirit is very similar and displays the text description. Both of these cards have "no text" in cards.txt and they do not include data in the card description and stack description fields.
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: abPump[Tgt] Keyword

Postby Rob Cashwalker » 15 Feb 2010, 03:49

Stun Sniper - I just forgot the description, definitely needs it.
Storm Spirit - is a simple damage ability, and the abDamageTgt code will build the description.

Granger Guildmage - I see where the problem is. Missing some braces for the else:
Code: Select all
          if (Tgt[0] == true)
              sbD.append("Target creature gains ");
           else
              sbD.append(cardName);
              sbD.append(" gains ");
I could fix it, but committing will have to wait until I'm done with abDrawCards, which will probably be in the next day or so.
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: abPump[Tgt] Keyword

Postby Rob Cashwalker » 20 Feb 2010, 04:18

Fixed in today's commit of CardFactory.
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: abPump[Tgt] Keyword

Postby Rob Cashwalker » 08 May 2010, 02:22

abPump now supports multiple keywords.

Cards to be added:
Code: Select all
Power Matrix
4
Artifact
no text
abPumpTgt T:+1/+1/Flying & First Strike & Trample

Scornful AEther-Lich
3 U
Artifact Creature - Zombie Wizard
no text
2/4
abPump W B:Fear & Vigilance
CardFactory
Code: Select all
        while(hasKeyword(card, "abPump") != -1) {
            int n = hasKeyword(card, "abPump");
            if(n != -1) {
                String parse = card.getKeyword().get(n).toString();
                card.removeIntrinsicKeyword(parse);
               
                String k[] = parse.split(":");
               
                final boolean Tgt[] = {false};
                Tgt[0] = k[0].contains("Tgt");
               
                String tmpCost;
                if(Tgt[0]) tmpCost = k[0].substring(9);
                else tmpCost = k[0].substring(6);
               
                boolean tapCost = false;
                boolean tapOnlyCost = false;
               
                if(tmpCost.contains("T")) {
                    tapCost = true;
                    tmpCost = tmpCost.replace("T", "");
                    tmpCost = tmpCost.trim();
                    if(tmpCost.length() == 0) tapOnlyCost = true;
                }
                final String manaCost = tmpCost.trim();
               
                final int NumAttack[] = {-1138};
                final String AttackX[] = {"none"};
                final int NumDefense[] = {-1138};
                final String DefenseX[] = {"none"};
                final String Keyword[] = {"none"};
               
                String ptk[] = k[1].split("/");
               
                if(ptk.length == 1) // keyword only
                Keyword[0] = ptk[0];
               
                if(ptk.length >= 2) // power/toughness
                {
                    if(ptk[0].matches("[\\+\\-][XY]")) {
                        String xy = card.getSVar(ptk[0].replaceAll("[\\+\\-]", ""));
                        if(xy.startsWith("Count$")) {
                            String kk[] = xy.split("\\$");
                            AttackX[0] = kk[1];
                           
                            if(ptk[0].contains("-")) // handle "-X" or "-Y"
                            if(AttackX[0].contains("/")) // already contains math element
                            AttackX[0] = AttackX[0].replace("/", "/Negative"); // insert into existing math element
                            else AttackX[0] += "/Negative"; // add math element
                        }
                    } else if(ptk[0].matches("[\\+\\-][0-9]"))
                       NumAttack[0] = Integer.parseInt(ptk[0].replace("+", ""));
                   
                    if(ptk[1].matches("[\\+\\-][XY]")) {
                        String xy = card.getSVar(ptk[1].replaceAll("[\\+\\-]", ""));
                        if(xy.startsWith("Count$")) {
                            String kk[] = xy.split("\\$");
                            DefenseX[0] = kk[1];
                           
                            if(ptk[1].contains("-")) //handle "-X" or "-Y"
                            if(DefenseX[0].contains("/")) // already contains math element
                            DefenseX[0] = DefenseX[0].replace("/", "/Negative"); // insert into existing math element
                            else DefenseX[0] += "/Negative"; // add math element
                        }
                    } else if(ptk[1].matches("[\\+\\-][0-9]")) NumDefense[0] = Integer.parseInt(ptk[1].replace(
                            "+", ""));
                }
               
                if(ptk.length == 3) // power/toughness/keyword
                Keyword[0] = ptk[2];
               
                String dK = Keyword[0];
                if (Keyword[0].contains(" & "))
                {
                   int amp = Keyword[0].lastIndexOf("&");
                   StringBuffer sbk = new StringBuffer(Keyword[0]);
                   sbk.replace(amp, amp + 1, "and");
                   dK = sbk.toString();
                   dK = dK.replace(" & ", ", ");
                }
               
                final String DrawBack[] = {"none"};
                final String spDesc[] = {"none"};
                final String stDesc[] = {"none"};
                String d = "none";
                StringBuilder sbD = new StringBuilder();
               
                if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
                        && (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && Keyword[0].equals("none")) {
                    // pt boost
                    if(Tgt[0] == true) sbD.append("Target creature gets ");
                    else {
                        sbD.append(cardName);
                        sbD.append(" gets ");
                    }
                   
                    if(NumAttack[0] > 0 || (NumAttack[0] == 0 && NumDefense[0] > 0)) // +0/+1
                       sbD.append("+");
                    else if(NumAttack[0] < 0 || (NumAttack[0] == 0 && NumDefense[0] < 0)) // -0/-1
                       sbD.append("-");
                   
                    sbD.append(Math.abs(NumAttack[0]) + "/");
                   
                    if(NumDefense[0] > 0 || (NumDefense[0] == 0 && NumAttack[0] > 0)) // +1/+0
                    sbD.append("+");
                    else if(NumDefense[0] < 0 || (NumDefense[0] == 0 && NumAttack[0] < 0)) // -1/-0
                    sbD.append("-");
                   
                    sbD.append(Math.abs(NumDefense[0]));
                    sbD.append(" until end of turn.");
                }
                if((AttackX[0].equals("none") && NumAttack[0] == -1138)
                        && (DefenseX[0].equals("none") && NumDefense[0] == -1138) && !Keyword[0].equals("none")) {
                    // k boost
                    if(Tgt[0] == true) sbD.append("Target creature gains ");
                    else {
                        sbD.append(cardName);
                        sbD.append(" gains ");
                    }
                   
                    sbD.append(dK);
                    sbD.append(" until end of turn.");
                }
                if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
                        && (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && !Keyword[0].equals("none")) {
                    // ptk boost
                    if(Tgt[0] == true) sbD.append("Target creature gets ");
                    else {
                        sbD.append(cardName);
                        sbD.append(" gets ");
                    }
                   
                    if(NumAttack[0] > 0 || (NumAttack[0] == 0 && NumDefense[0] > 0)) // +0/+1
                    sbD.append("+");
                    else if(NumAttack[0] < 0 || (NumAttack[0] == 0 && NumDefense[0] < 0)) // -0/-1
                    sbD.append("-");
                   
                    sbD.append(Math.abs(NumAttack[0]) + "/");
                   
                    if(NumDefense[0] > 0 || (NumDefense[0] == 0 && NumAttack[0] > 0)) // +1/+0
                    sbD.append("+");
                    else if(NumDefense[0] < 0 || (NumDefense[0] == 0 && NumAttack[0] < 0)) // -1/-0
                    sbD.append("-");
                   
                    sbD.append(Math.abs(NumDefense[0]));
                    sbD.append(" and gains ");
                    sbD.append(dK);
                    sbD.append(" until end of turn.");
                }
                //if (!sbD.toString().isEmpty())
                if(sbD.toString().trim().length() != 0) d = sbD.toString();
               
                if(k.length > 2) {
                    if(k[2].contains("Drawback$")) {
                        String kk[] = k[2].split("\\$");
                        DrawBack[0] = kk[1];
                        if(k.length > 3) d = k[3];
                    } else if(k.length > 2) d = k[2];
                }
               
                if(!d.equals("none")) {
                    if(tapOnlyCost == true) spDesc[0] = "Tap: " + d;
                    else if(tapCost == true) spDesc[0] = manaCost + ", tap: " + d;
                    else spDesc[0] = manaCost + ": " + d;
                   
                    stDesc[0] = d;
                }
               
                if(!tapCost) {
                    final SpellAbility ability = new Ability_Activated(card, manaCost) {
                        private static final long serialVersionUID = -1118592153328758083L;
                       
                        private int               defense;
                        private String            keyword;
                       
                        private int getNumAttack() {
                            if(NumAttack[0] != -1138) return NumAttack[0];
                           
                            if(!AttackX[0].equals("none")) return CardFactoryUtil.xCount(card, AttackX[0]);
                           
                            return 0;
                        }
                       
                        private int getNumDefense() {
                            if(NumDefense[0] != -1138) return NumDefense[0];
                           
                            if(!DefenseX[0].equals("none")) return CardFactoryUtil.xCount(card, DefenseX[0]);
                           
                            return 0;
                        }
                       
                        @Override
                        public boolean canPlayAI() {
                            defense = getNumDefense();
                            keyword = Keyword[0];
                           
                            if(AllZone.Phase.getPhase().equals(Constant.Phase.Main2)) return false;
                           
                            if(Tgt[0] == false) {
                                setTargetCard(card);
                               
                                if((card.getNetDefense() + defense > 0) && (!card.getKeyword().contains(keyword))) if(card.hasSickness()
                                        && keyword.contains("Haste")) return true;
                                else if((card.hasSickness() && (!keyword.contains("Haste")))
                                        || ((!card.hasSickness()) && keyword.contains("Haste"))) return false;
                                else {
                                    Random r = new Random();
                                    if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) return CardFactoryUtil.AI_doesCreatureAttack(card);
                                }
                            }
                           
                            CardList list = getCreatures();
                            if(!list.isEmpty()) {
                                boolean goodt = false;
                                Card t = new Card();
                                while(goodt == false && !list.isEmpty()) // loop until we find a target that is best and won't die when targeted or until no more creatures
                                {
                                    t = CardFactoryUtil.AI_getBestCreature(list);
                                    if((t.getNetDefense() + defense) > 0) // handle negative defense pumps
                                    goodt = true;
                                    else list.remove(t);
                                }
                                if(goodt == true) {
                                    Random r = new Random();
                                    if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) {
                                        setTargetCard(t);
                                        return true;
                                    }
                                }
                            }
                           
                            return false;
                        }
                       
                        @Override
                        public boolean canPlay() {
                            return (CardFactoryUtil.canUseAbility(card))
                                    && (AllZone.GameAction.isCardInPlay(card)) && (!card.isFaceDown());
                        }
                       
                        private CardList getCreatures() {
                            CardList list = new CardList(AllZone.Computer_Play.getCards());
                            list = list.filter(new CardListFilter() {
                                public boolean addCard(Card c) {
                                    if(c.isCreature()) {
                                        if(c.hasSickness() && keyword.contains("Haste")) // AI_doesCreatureAttack would have prevented the effect from granting haste, because it assumes the creature would already have it
                                        return CardFactoryUtil.canTarget(card, c);
                                       
                                        return (CardFactoryUtil.AI_doesCreatureAttack(c))
                                                && (CardFactoryUtil.canTarget(card, c))
                                                && (!keyword.equals("none") && !c.hasAnyKeyword(keyword.split(" & ")))
                                                && (!(!c.hasSickness()) && keyword.contains("Haste")); // if creature doesn't have sickness, the haste keyword won't help
                                    }
                                    return false;
                                }
                            });
                            // list.remove(card);      // if mana-only cost, allow self-target
                            return list;
                        }//getCreatures()
                       
                        @Override
                        public void resolve() {
                            if(AllZone.GameAction.isCardInPlay(getTargetCard())
                                    && (CardFactoryUtil.canTarget(card, getTargetCard()) || !Tgt[0] )) {
                                final Card[] creature = new Card[1];
                                if(Tgt[0] == true) creature[0] = getTargetCard();
                                else creature[0] = card;
                               
                                final int a = getNumAttack();
                                final int d = getNumDefense();
                               
                                final Command EOT = new Command() {
                                    private static final long serialVersionUID = -8840812331316327448L;
                                   
                                    public void execute() {
                                        if(AllZone.GameAction.isCardInPlay(creature[0])) {
                                            creature[0].addTempAttackBoost(-1 * a);
                                            creature[0].addTempDefenseBoost(-1 * d);
                                            if(!Keyword[0].equals("none"))
                                            {
                                               String[] kws = Keyword[0].split(" & ");
                                               for (int i=0; i<kws.length; i++)
                                                  creature[0].removeExtrinsicKeyword(kws[i]);
                                            }
                                        }
                                       
                                    }
                                };
                               
                                creature[0].addTempAttackBoost(a);
                                creature[0].addTempDefenseBoost(d);
                                if(!Keyword[0].equals("none"))
                                {
                                   String[] kws = Keyword[0].split(" & ");
                                   for (int i=0; i<kws.length; i++)
                                      creature[0].addExtrinsicKeyword(kws[i]);
                                }
                               
                                card.setAbilityUsed(card.getAbilityUsed() + 1);
                                AllZone.EndOfTurn.addUntil(EOT);
                               
                                if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], 0,
                                        card.getController(),
                                        AllZone.GameAction.getOpponent(card.getController()), null, card,
                                        creature[0]);
                               
                            }//if (card is in play)
                        }//resolve()
                    };//SpellAbility
                   
                    ability.setDescription(spDesc[0]);
                    ability.setStackDescription(stDesc[0]);
                   
                    if(Tgt[0] == true) ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability));
                    else ability.setTargetCard(card);
                    card.addSpellAbility(ability);
                }
                if(tapCost) {
                    final SpellAbility ability = new Ability_Tap(card) {
                        private static final long serialVersionUID = 5252594757468128739L;
                       
                        private int               defense;
                        private String            keyword;
                       
                        private int getNumAttack() {
                            if(NumAttack[0] != -1138) return NumAttack[0];
                           
                            if(!AttackX[0].equals("none")) return CardFactoryUtil.xCount(card, AttackX[0]);
                           
                            return 0;
                        }
                       
                        private int getNumDefense() {
                            if(NumDefense[0] != -1138) return NumDefense[0];
                           
                            if(!DefenseX[0].equals("none")) return CardFactoryUtil.xCount(card, DefenseX[0]);
                           
                            return 0;
                        }
                       
                        @Override
                        public boolean canPlayAI() {
                            defense = getNumDefense();
                            keyword = Keyword[0];
                           
                            if(CardFactoryUtil.AI_doesCreatureAttack(card)) return false;
                           
                            if(AllZone.Phase.getPhase().equals(Constant.Phase.Main2)) return false;
                           
                            CardList list = getCreatures();
                            if(!list.isEmpty()) {
                                boolean goodt = false;
                                Card t = new Card();
                                while(goodt == false && !list.isEmpty()) {
                                    t = CardFactoryUtil.AI_getBestCreature(list);
                                    if((t.getNetDefense() + defense) > 0) goodt = true;
                                    else list.remove(t);
                                }
                                if(goodt == true) {
                                    setTargetCard(t);
                                    return true;
                                }
                            }
                           
                            return false;
                        }
                       
                        @Override
                        public boolean canPlay() {
                            boolean sick = true;
                           
                            if(!card.hasSickness() || !card.isCreature()) sick = false;
                           
                            if(card.isUntapped() && AllZone.GameAction.isCardInPlay(card) && !sick
                                    && !card.isFaceDown()) return true;
                            else return false;
                        }
                       
                        private CardList getCreatures() {
                            CardList list = new CardList(AllZone.Computer_Play.getCards());
                            list = list.filter(new CardListFilter() {
                                public boolean addCard(Card c) {
                                    if(c.isCreature()) {
                                        if(c.hasSickness() && keyword.contains("Haste"))
                                           return CardFactoryUtil.canTarget(card, c);
                                       
                                        return (CardFactoryUtil.AI_doesCreatureAttack(c))
                                                && (CardFactoryUtil.canTarget(card, c))
                                                && (!keyword.equals("none") && !c.hasAnyKeyword(keyword.split(" & ")))
                                                && (!(!c.hasSickness()) && keyword.contains("Haste"));
                                    }
                                    return false;
                                }
                            });
                            list.remove(card);
                            return list;
                        }//getCreature()
                       
                        @Override
                        public void resolve() {
                            if(AllZone.GameAction.isCardInPlay(getTargetCard())
                                    && CardFactoryUtil.canTarget(card, getTargetCard())) {
                                final Card[] creature = new Card[1];
                                if(Tgt[0] == true) creature[0] = getTargetCard();
                                else creature[0] = card;
                               
                                final int a = getNumAttack();
                                final int d = getNumDefense();
                               
                                final Command EOT = new Command() {
                                    private static final long serialVersionUID = 2134353417588894452L;
                                   
                                    public void execute() {
                                        if(AllZone.GameAction.isCardInPlay(creature[0])) {
                                            creature[0].addTempAttackBoost(-1 * a);
                                            creature[0].addTempDefenseBoost(-1 * d);
                                            if(!Keyword[0].equals("none"))
                                            {
                                               String[] kws = Keyword[0].split(" & ");
                                               for (int i=0; i<kws.length; i++)
                                                  creature[0].removeExtrinsicKeyword(kws[i]);
                                            }
                                        }
                                    }
                                };
                               
                                creature[0].addTempAttackBoost(a);
                                creature[0].addTempDefenseBoost(d);
                                if(!Keyword[0].equals("none"))
                                {
                                   String[] kws = Keyword[0].split(" & ");
                                   for (int i=0; i<kws.length; i++)
                                      creature[0].addExtrinsicKeyword(kws[i]);
                                }
                               
                                AllZone.EndOfTurn.addUntil(EOT);
                               
                                if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], 0,
                                        card.getController(),
                                        AllZone.GameAction.getOpponent(card.getController()), null, card,
                                        creature[0]);
                            }//if (card is in play)
                        }//resolve()
                    };//SpellAbility
                   
                    ability.setDescription(spDesc[0]);
                    ability.setStackDescription(stDesc[0]);
                   
                    if(Tgt[0] == true) ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability));
                    else ability.setTargetCard(card);
                   
                    if(!tapOnlyCost) ability.setManaCost(manaCost);
                   
                    card.addSpellAbility(ability);
                }
            }
        }//while
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: abPump[Tgt] Keyword

Postby DennisBergkamp » 08 May 2010, 05:01

Good stuff Rob, thanks :mrgreen:
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: abPump[Tgt] Keyword

Postby Chris H. » 08 May 2010, 09:32

The two new cards that this allows look very interesting. :)
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: abPump[Tgt] Keyword

Postby Rob Cashwalker » 09 May 2010, 06:09

Mind you that's ALL the cards that are added... there are very few abilities and spells that do multiple keywords. Plenty of Auras, global enchantments and some global pump spells that do.
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: abPump[Tgt] Keyword

Postby Chris H. » 10 May 2010, 13:29

Rob Cashwalker wrote:Mind you that's ALL the cards that are added... there are very few abilities and spells that do multiple keywords. Plenty of Auras, global enchantments and some global pump spells that do.
`
Understood. :D Some of our keywords will allow more cards than others.

I would like to include the Power Matrix in a new AI deck for quest mode. The Scornful AEther-Lich is another zombie and at some point it might be nice to also add a zombie deck.
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: abPump[Tgt] Keyword

Postby DennisBergkamp » 10 May 2010, 15:07

Hm, quest10.dck is some zombie deck I put together (it's really not that strong though - just has a bunch of random zombies and a couple Lord of the Undead + Cemetery Reaper).
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: abPump[Tgt] Keyword

Postby Chris H. » 10 May 2010, 16:11

DennisBergkamp wrote:Hm, quest10.dck is some zombie deck I put together (it's really not that strong though - just has a bunch of random zombies and a couple Lord of the Undead + Cemetery Reaper).
`
I suspected that one of the quest{num} decks might contain zombies or that you were working to accomplish this goal ... I was going to mention this but I did not want to twist your arm behind your back. :mrgreen:
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

Previous

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 32 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 32 users online :: 0 registered, 0 hidden and 32 guests (based on users active over the past 10 minutes)
Most users ever online was 7303 on 15 Jul 2025, 20:46

Users browsing this forum: No registered users and 32 guests

Login Form