Page 2 of 2

Re: abPump[Tgt] Keyword

PostPosted: 15 Feb 2010, 01:25
by Chris H.
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.

Re: abPump[Tgt] Keyword

PostPosted: 15 Feb 2010, 03:49
by Rob Cashwalker
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.

Re: abPump[Tgt] Keyword

PostPosted: 20 Feb 2010, 04:18
by Rob Cashwalker
Fixed in today's commit of CardFactory.

Re: abPump[Tgt] Keyword

PostPosted: 08 May 2010, 02:22
by Rob Cashwalker
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

Re: abPump[Tgt] Keyword

PostPosted: 08 May 2010, 05:01
by DennisBergkamp
Good stuff Rob, thanks :mrgreen:

Re: abPump[Tgt] Keyword

PostPosted: 08 May 2010, 09:32
by Chris H.
The two new cards that this allows look very interesting. :)

Re: abPump[Tgt] Keyword

PostPosted: 09 May 2010, 06:09
by Rob Cashwalker
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.

Re: abPump[Tgt] Keyword

PostPosted: 10 May 2010, 13:29
by Chris H.
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.

Re: abPump[Tgt] Keyword

PostPosted: 10 May 2010, 15:07
by DennisBergkamp
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).

Re: abPump[Tgt] Keyword

PostPosted: 10 May 2010, 16:11
by Chris H.
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: