Initial development of AbilityFactory.

Only implemented "DealDamage" ability.
Prodigal Pyromancer is first card to get the makeover.
This commit is contained in:
jendave
2011-08-06 08:54:25 +00:00
parent 6a9cefa2e9
commit 202f029a2b
5 changed files with 312 additions and 1 deletions

1
.gitattributes vendored
View File

@@ -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/cloudgarden/layout/AnchorLayout.java -text svneol=native#text/plain
src/com/esotericsoftware/minlog/Log.java svneol=native#text/plain src/com/esotericsoftware/minlog/Log.java svneol=native#text/plain
src/forge/Ability.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_Activated.java svneol=native#text/plain
src/forge/Ability_Cost.java -text svneol=native#text/plain src/forge/Ability_Cost.java -text svneol=native#text/plain
src/forge/Ability_Hand.java svneol=native#text/plain src/forge/Ability_Hand.java svneol=native#text/plain

View File

@@ -3,7 +3,8 @@ ManaCost:2 R
Types:Creature Human Wizard Types:Creature Human Wizard
Text:no text Text:no text
PT:1/1 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:Rarity:Common
SVar:Picture:http://resources.wizards.com/magic/cards/plc/en-us/card122338.jpg SVar:Picture:http://resources.wizards.com/magic/cards/plc/en-us/card122338.jpg
End End

View File

@@ -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<String,String> mapParams = new HashMap<String,String>();
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<a.length; i++)
{
String aa[] = a[i].split("\\$");
if (!(aa.length == 2))
throw new RuntimeException("AbilityFactory : getAbility -- aa.length not 2 in " + hostCard.getName());
mapParams.put(aa[0], aa[1]);
}
final boolean isAb[] = {false};
final boolean isSp[] = {false};
String abAPI = "";
String spAPI = "";
// additional ability types here
if (mapParams.containsKey("AB"))
{
isAb[0] = true;
abAPI = mapParams.get("AB");
}
else if (mapParams.containsKey("SP"))
{
isSp[0] = true;
spAPI = mapParams.get("SP");
}
else
throw new RuntimeException("AbilityFactory : getAbility -- no API in " + hostCard.getName());
if (!mapParams.containsKey("Cost"))
throw new RuntimeException("AbilityFactory : getAbility -- no Cost in " + hostCard.getName());
final Ability_Cost abCost = new Ability_Cost(mapParams.get("Cost"), hostCard.getName(), isAb[0]);
final boolean isTargeted[] = {false};
final boolean hasValid[] = {false};
final Target abTgt[] = {null};
if (mapParams.containsKey("ValidTgts"))
{
hasValid[0] = true;
isTargeted[0] = true;
abTgt[0] = new Target("V");
abTgt[0].setValidTgts(mapParams.get("ValidTgts").split(","));
abTgt[0].setVTSelection(mapParams.get("TgtPrompt"));
}
if (mapParams.containsKey("ValidCards"))
hasValid[0] = true;
if (mapParams.containsKey("Tgt"))
{
isTargeted[0] = true;
abTgt[0] = new Target(mapParams.get("Tgt"));
}
//final String SubAbility[] = {"none"};
final boolean hasSubAb[] = {false};
if (mapParams.containsKey("SubAbility"))
hasSubAb[0] = true;
//SubAbility[0] = mapParams;
final String spDescription[] = {"none"};
final boolean hasSpDesc[] = {false};
//String tmpSpDesc = mapParams.get("SpellDescription");
if (mapParams.containsKey("SpellDescription"))
{
hasSpDesc[0] = true;
spDescription[0] = abCost.toString() + mapParams.get("SpellDescription");
}
if (abAPI.equals("DealDamage"))
{
final int NumDmg[] = {-1};
final String NumDmgX[] = {"none"};
String tmpND = mapParams.get("NumDmg");
if (tmpND.length() > 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];
}
}

View File

@@ -21,6 +21,7 @@ public class Card extends MyObservable {
//private Collection keyword = new TreeSet(); //private Collection keyword = new TreeSet();
//private ArrayList<String> keyword = new ArrayList<String>(); //private ArrayList<String> keyword = new ArrayList<String>();
private ArrayList<String> intrinsicAbility = new ArrayList<String>();
private ArrayList<String> intrinsicKeyword = new ArrayList<String>(); private ArrayList<String> intrinsicKeyword = new ArrayList<String>();
private ArrayList<String> extrinsicKeyword = new ArrayList<String>(); private ArrayList<String> extrinsicKeyword = new ArrayList<String>();
private ArrayList<String> otherExtrinsicKeyword = new ArrayList<String>(); private ArrayList<String> otherExtrinsicKeyword = new ArrayList<String>();
@@ -1814,6 +1815,11 @@ public class Card extends MyObservable {
return a1; return a1;
} }
public ArrayList<String> getIntrinsicAbilities()
{
return intrinsicAbility;
}
//public void setKeyword(ArrayList a) {keyword = new ArrayList(a); this.updateObservers();} //public void setKeyword(ArrayList a) {keyword = new ArrayList(a); this.updateObservers();}
//public void addKeyword(String s) {keyword.add(s); this.updateObservers();} //public void addKeyword(String s) {keyword.add(s); this.updateObservers();}
//public void removeKeyword(String s) {keyword.remove(s); this.updateObservers();} //public void removeKeyword(String s) {keyword.remove(s); this.updateObservers();}
@@ -1830,11 +1836,22 @@ public class Card extends MyObservable {
this.updateObservers(); this.updateObservers();
} }
public void setIntrinsicAbilities(ArrayList<String> a)
{
intrinsicAbility = new ArrayList<String>(a);
}
public void addIntrinsicKeyword(String s) {/*if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s){}); else*/ public void addIntrinsicKeyword(String s) {/*if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s){}); else*/
if (s.trim().length()!=0) if (s.trim().length()!=0)
intrinsicKeyword.add((getName().trim().length()== 0 ? s :s.replaceAll(getName(), "CARDNAME"))); 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*/ public void addNonStackingIntrinsicKeyword(String s) {/*if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s){}); else*/
if(!getIntrinsicKeyword().contains(s)){ if(!getIntrinsicKeyword().contains(s)){
if (s.trim().length()!=0) if (s.trim().length()!=0)

View File

@@ -5999,7 +5999,25 @@ public class CardFactory implements NewConstants {
AbUntapTgt.setDescription(abDesc[0]); AbUntapTgt.setDescription(abDesc[0]);
card.addSpellAbility(AbUntapTgt); card.addSpellAbility(AbUntapTgt);
}//End abUntapTgt }//End abUntapTgt
//**************************************************
// AbilityFactory cards
ArrayList<String> IA = card.getIntrinsicAbilities();
if (IA.size() > 0)
{
AbilityFactory AF = new AbilityFactory();
if (card.isInstant() || card.isSorcery())
card.clearSpellAbility();
for (int i=0; i<IA.size(); i++)
card.addSpellAbility(AF.getAbility(IA.get(i), card));
}
//****************************************************************** //******************************************************************
//************** Link to different CardFactories ******************* //************** Link to different CardFactories *******************
Card card2 = null; Card card2 = null;