diff --git a/.gitattributes b/.gitattributes index 12bef0df241..ad6d5b42ce4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5039,6 +5039,7 @@ src/com/cloudgarden/layout/AnchorConstraint.java -text svneol=native#text/plain src/com/cloudgarden/layout/AnchorLayout.java -text svneol=native#text/plain src/com/esotericsoftware/minlog/Log.java svneol=native#text/plain src/forge/Ability.java svneol=native#text/plain +src/forge/AbilityFactory.java -text svneol=native#text/plain src/forge/Ability_Activated.java svneol=native#text/plain src/forge/Ability_Cost.java -text svneol=native#text/plain src/forge/Ability_Hand.java svneol=native#text/plain diff --git a/res/cardsfolder/prodigal_pyromancer.txt b/res/cardsfolder/prodigal_pyromancer.txt index 230184e16de..b508c508385 100644 --- a/res/cardsfolder/prodigal_pyromancer.txt +++ b/res/cardsfolder/prodigal_pyromancer.txt @@ -3,7 +3,8 @@ ManaCost:2 R Types:Creature Human Wizard Text:no text PT:1/1 -K:abDamageTgtCP T:1 +# K:abDamageTgtCP T:1 +A:AB$DealDamage|Cost$T|Tgt$TgtCP|NumDmg$1|SpellDescription$Deal 1 damage to target creature or player. SVar:Rarity:Common SVar:Picture:http://resources.wizards.com/magic/cards/plc/en-us/card122338.jpg End diff --git a/src/forge/AbilityFactory.java b/src/forge/AbilityFactory.java new file mode 100644 index 00000000000..596b4e90cc0 --- /dev/null +++ b/src/forge/AbilityFactory.java @@ -0,0 +1,274 @@ +package forge; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +public class AbilityFactory { + + public SpellAbility getAbility(String abString, final Card hostCard){ + final SpellAbility SA[] = {null}; + + final HashMap mapParams = new HashMap(); + + if (!(abString.length() > 0)) + throw new RuntimeException("AbilityFactory : getAbility -- abString too short in " + hostCard.getName()); + + String a[] = abString.split("\\|"); + + if (!(a.length > 1)) + throw new RuntimeException("AbilityFactory : getAbility -- a[] too short in " + hostCard.getName()); + + for (int i=0; i 0) + { + if (tmpND.matches("X")) + NumDmgX[0] = hostCard.getSVar(tmpND.substring(1)); + + else if (tmpND.matches("[0-9][0-9]?")) + NumDmg[0] = Integer.parseInt(tmpND); + } + + final SpellAbility abDamage = new Ability_Activated(hostCard, abCost, abTgt[0]) + { + private static final long serialVersionUID = -7560349014757367722L; + + int damage = 0; + + public int getNumDamage() { + if(NumDmg[0] != -1) return NumDmg[0]; + + if(!NumDmgX[0].equals("none")) return CardFactoryUtil.xCount(hostCard, NumDmgX[0]); + + return 0; + } + + boolean shouldTgtP() { + PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); + CardList hand = new CardList(compHand.getCards()); + + if(hand.size() > 7) // anti-discard-at-EOT + return true; + + if(AllZone.Human_Life.getLife() - damage < 10) // if damage from this spell would drop the human to less than 10 life + return true; + + return false; + } + + Card chooseTgtC() { + // Combo alert!! + PlayerZone compy = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList cPlay = new CardList(compy.getCards()); + if(cPlay.size() > 0) for(int i = 0; i < cPlay.size(); i++) + if(cPlay.get(i).getName().equals("Stuffy Doll")) return cPlay.get(i); + + PlayerZone human = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human); + CardList hPlay = new CardList(human.getCards()); + hPlay = hPlay.filter(new CardListFilter() { + public boolean addCard(Card c) { + // will include creatures already dealt damage + return c.isCreature() && ((c.getNetDefense() + c.getDamage()) <= damage) + && CardFactoryUtil.canTarget(hostCard, c); + } + }); + + if(hPlay.size() > 0) { + Card best = hPlay.get(0); + + if(hPlay.size() > 1) { + for(int i = 1; i < hPlay.size(); i++) { + Card b = hPlay.get(i); + // choose best overall creature? + if(b.getSpellAbility().length > best.getSpellAbility().length + || b.getKeyword().size() > best.getKeyword().size() + || b.getNetAttack() > best.getNetAttack()) best = b; + } + } + return best; + } + return null; + } + + @Override + public boolean canPlay(){ + Cost_Payment pay = new Cost_Payment(abCost, this); + return (pay.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(hostCard) && super.canPlay()); + } + + @Override + public boolean canPlayAI() { + // temporarily disabled until better AI + if (abCost.getSacCost()) return false; + if (abCost.getSubCounter()) return false; + if (abCost.getLifeCost()) return false; + + if (!ComputerUtil.canPayCost(this)) + return false; + + damage = getNumDamage(); + + Random r = new Random(); // prevent run-away activations + boolean rr = false; + if(r.nextFloat() <= Math.pow(.6667, hostCard.getAbilityUsed())) + rr = true; + + if(abTgt[0].canTgtCreaturePlayer()) { + if(shouldTgtP()) { + setTargetPlayer(Constant.Player.Human); + return rr; + } + + Card c = chooseTgtC(); + if(c != null) { + setTargetCard(c); + return rr; + } + } + + if(abTgt[0].canTgtPlayer()/* || TgtOpp[0] == true */) { + setTargetPlayer(Constant.Player.Human); + return rr; + } + + if(abTgt[0].canTgtCreature()) { + Card c = chooseTgtC(); + if(c != null) { + setTargetCard(c); + return rr; + } + } + return false; + } + + @Override + public void resolve() { + int damage = getNumDamage(); + String tgtP = ""; + + //if(TgtOpp[0] == true) { + // tgtP = AllZone.GameAction.getOpponent(card.getController()); + // setTargetPlayer(tgtP); + //} + Card c = getTargetCard(); + if(c != null) { + if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(hostCard, c)) { + AllZone.GameAction.addDamage(c, hostCard, damage); + tgtP = c.getController(); + + if(hasSubAb[0]) + CardFactoryUtil.doDrawBack(mapParams.get("SubAbility"), damage, + hostCard.getController(), AllZone.GameAction.getOpponent(hostCard.getController()), + tgtP, hostCard, c, this); + + } + } else { + tgtP = getTargetPlayer(); + AllZone.GameAction.addDamage(tgtP, hostCard, damage); + + if(hasSubAb[0]) + CardFactoryUtil.doDrawBack(mapParams.get("SubAbility"), damage, + hostCard.getController(), AllZone.GameAction.getOpponent(hostCard.getController()), + tgtP, hostCard, null, this); + + } + + }//resolve() + };//Ability_Activated + + if (isTargeted[0]) + abDamage.setTarget(abTgt[0]); + + abDamage.setPayCosts(abCost); + + if (hasSpDesc[0]) + abDamage.setDescription(spDescription[0]); + + SA[0] = abDamage; + } + + // additional keywords here + + return SA[0]; + } + + +} + diff --git a/src/forge/Card.java b/src/forge/Card.java index d21f0b255ff..066870df9a6 100644 --- a/src/forge/Card.java +++ b/src/forge/Card.java @@ -21,6 +21,7 @@ public class Card extends MyObservable { //private Collection keyword = new TreeSet(); //private ArrayList keyword = new ArrayList(); + private ArrayList intrinsicAbility = new ArrayList(); private ArrayList intrinsicKeyword = new ArrayList(); private ArrayList extrinsicKeyword = new ArrayList(); private ArrayList otherExtrinsicKeyword = new ArrayList(); @@ -1814,6 +1815,11 @@ public class Card extends MyObservable { return a1; } + public ArrayList getIntrinsicAbilities() + { + return intrinsicAbility; + } + //public void setKeyword(ArrayList a) {keyword = new ArrayList(a); this.updateObservers();} //public void addKeyword(String s) {keyword.add(s); this.updateObservers();} //public void removeKeyword(String s) {keyword.remove(s); this.updateObservers();} @@ -1830,11 +1836,22 @@ public class Card extends MyObservable { this.updateObservers(); } + public void setIntrinsicAbilities(ArrayList a) + { + intrinsicAbility = new ArrayList(a); + } + public void addIntrinsicKeyword(String s) {/*if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s){}); else*/ if (s.trim().length()!=0) intrinsicKeyword.add((getName().trim().length()== 0 ? s :s.replaceAll(getName(), "CARDNAME"))); } + public void addIntrinsicAbility(String s) + { + if (s.trim().length() != 0) + intrinsicAbility.add(s); + } + public void addNonStackingIntrinsicKeyword(String s) {/*if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s){}); else*/ if(!getIntrinsicKeyword().contains(s)){ if (s.trim().length()!=0) diff --git a/src/forge/CardFactory.java b/src/forge/CardFactory.java index 3aa1f681eb6..dbe4d4c2af6 100644 --- a/src/forge/CardFactory.java +++ b/src/forge/CardFactory.java @@ -5999,7 +5999,25 @@ public class CardFactory implements NewConstants { AbUntapTgt.setDescription(abDesc[0]); card.addSpellAbility(AbUntapTgt); }//End abUntapTgt + + + //************************************************** + // AbilityFactory cards + ArrayList IA = card.getIntrinsicAbilities(); + if (IA.size() > 0) + { + AbilityFactory AF = new AbilityFactory(); + if (card.isInstant() || card.isSorcery()) + card.clearSpellAbility(); + + for (int i=0; i