Re-structured AbilityFactory. AbilityFactory actually provides interfaces to reference universal parameters.

Moved DealDamage ability code to dedicated class, DealDamage.
Picked apart DealDamage Ability_Activated code into helper methods common to both the Spell version and Ability version.
This commit is contained in:
jendave
2011-08-06 08:55:28 +00:00
parent a5d624e1a5
commit e85abcc5ba
4 changed files with 302 additions and 182 deletions

1
.gitattributes vendored
View File

@@ -5102,6 +5102,7 @@ src/forge/Constant.java svneol=native#text/plain
src/forge/CopyFiles.java -text svneol=native#text/plain
src/forge/Cost_Payment.java -text svneol=native#text/plain
src/forge/Counters.java svneol=native#text/plain
src/forge/DealDamage.java -text svneol=native#text/plain
src/forge/Deck.java svneol=native#text/plain
src/forge/DeckIO.java svneol=native#text/plain
src/forge/DefaultPlayerZone.java svneol=native#text/plain

View File

@@ -1,15 +1,83 @@
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};
private static Card hostC = null;
final HashMap<String,String> mapParams = new HashMap<String,String>();
public Card getHostCard()
{
return hostC;
}
private static HashMap<String,String> mapParams = new HashMap<String,String>();
public HashMap<String,String> getMapParams()
{
return mapParams;
}
private static boolean isAb = false;
private static boolean isSp = false;
public boolean isAbility()
{
return isAb;
}
public boolean isSpell()
{
return isSp;
}
private static Ability_Cost abCost = null;
public Ability_Cost getAbCost()
{
return abCost;
}
private static boolean isTargeted = false;
private static boolean hasValid = false;
private static Target abTgt = null;
public boolean isTargeted()
{
return isTargeted;
}
public boolean hasValid()
{
return hasValid;
}
public Target getAbTgt()
{
return abTgt;
}
private static boolean hasSubAb = false;
public boolean hasSubAbility()
{
return hasSubAb;
}
private static boolean hasSpDesc = false;
public boolean hasSpDescription()
{
return hasSpDesc;
}
public SpellAbility getAbility(String abString, final Card hostCard){
SpellAbility SA = null;
//final HashMap<String,String> mapParams = new HashMap<String,String>();
hostC = hostCard;
if (!(abString.length() > 0))
throw new RuntimeException("AbilityFactory : getAbility -- abString too short in " + hostCard.getName());
@@ -30,19 +98,19 @@ public class AbilityFactory {
}
final boolean isAb[] = {false};
final boolean isSp[] = {false};
//final boolean isAb[] = {false};
//final boolean isSp[] = {false};
String abAPI = "";
String spAPI = "";
// additional ability types here
if (mapParams.containsKey("AB"))
{
isAb[0] = true;
isAb = true;
abAPI = mapParams.get("AB");
}
else if (mapParams.containsKey("SP"))
{
isSp[0] = true;
isSp = true;
spAPI = mapParams.get("SP");
}
else
@@ -51,44 +119,44 @@ public class AbilityFactory {
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]);
abCost = new Ability_Cost(mapParams.get("Cost"), hostCard.getName(), isAb);
final boolean isTargeted[] = {false};
final boolean hasValid[] = {false};
final Target abTgt[] = {null};
//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"));
hasValid = true;
isTargeted = true;
abTgt = new Target("TgtV");
abTgt.setValidTgts(mapParams.get("ValidTgts").split(","));
abTgt.setVTSelection(mapParams.get("TgtPrompt"));
}
if (mapParams.containsKey("ValidCards"))
hasValid[0] = true;
hasValid = true;
if (mapParams.containsKey("Tgt"))
{
isTargeted[0] = true;
abTgt[0] = new Target(mapParams.get("Tgt"));
isTargeted = true;
abTgt = new Target(mapParams.get("Tgt"));
}
//final String SubAbility[] = {"none"};
final boolean hasSubAb[] = {false};
//final boolean hasSubAb[] = {false};
if (mapParams.containsKey("SubAbility"))
hasSubAb[0] = true;
hasSubAb = true;
//SubAbility[0] = mapParams;
final String spDescription[] = {"none"};
final boolean hasSpDesc[] = {false};
//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");
hasSpDesc = true;
//spDescription[0] = abCost.toString() + mapParams.get("SpellDescription");
}
@@ -106,166 +174,27 @@ public class AbilityFactory {
NumDmg[0] = Integer.parseInt(tmpND);
}
final SpellAbility abDamage = new Ability_Activated(hostCard, abCost, abTgt[0])
{
private static final long serialVersionUID = -7560349014757367722L;
if (isAb)
SA = DealDamage.getAbility(this, NumDmg[0], NumDmgX[0]);
else if (isSp)
SA = DealDamage.getSpell(this);
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(){
return (Cost_Payment.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];
// set universal properties of the SpellAbility
if (isTargeted)
SA.setTarget(abTgt);
SA.setPayCosts(abCost);
if (hasSpDesc)
SA.setDescription(abCost.toString() + mapParams.get("SpellDescription"));
return SA;
}

View File

@@ -11083,6 +11083,7 @@ public class CardFactory implements NewConstants {
c.setManaCost(sim.getManaCost());
c.addColor(sim.getManaCost());
c.setSVars(sim.getSVars());
c.setIntrinsicAbilities(sim.getIntrinsicAbilities());
return c;
}// copyStats()

189
src/forge/DealDamage.java Normal file
View File

@@ -0,0 +1,189 @@
package forge;
import java.util.Random;
public class DealDamage {
private static AbilityFactory AF = null;
private static int nDamage = -1;
private static String XDamage = "none";
public static SpellAbility getAbility(final AbilityFactory af, final int NumDmg, final String NumDmgX)
{
AF = af;
nDamage = NumDmg;
XDamage = NumDmgX;
final SpellAbility abDamage = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt())
{
private static final long serialVersionUID = -7560349014757367722L;
int damage = 0;
@Override
public boolean canPlay(){
return (Cost_Payment.canPayAdditionalCosts(AF.getAbCost(), this)
&& CardFactoryUtil.canUseAbility(AF.getHostCard())
&& super.canPlay());
}
@Override
public boolean canPlayAI() {
return doCanPlayAI(this);
}
@Override
public void resolve() {
doResolve(this);
AF.getHostCard().setAbilityUsed(AF.getHostCard().getAbilityUsed() + 1);
}
};//Ability_Activated
return abDamage;
}
public static SpellAbility getSpell(AbilityFactory AF)
{
SpellAbility spDealDamage = null;
return spDealDamage;
}
private static int getNumDamage() {
if(nDamage != -1) return nDamage;
if(!XDamage.equals("none"))
return CardFactoryUtil.xCount(AF.getHostCard(), XDamage);
return 0;
}
private static boolean shouldTgtP(int d) {
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() - d < 10) // if damage from this spell would drop the human to less than 10 life
return true;
return false;
}
private static Card chooseTgtC(final int d) {
// 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()) <= d)
&& CardFactoryUtil.canTarget(AF.getHostCard(), 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;
}
private static boolean doCanPlayAI(SpellAbility saMe)
{
// temporarily disabled until better AI
if (AF.getAbCost().getSacCost()) return false;
if (AF.getAbCost().getSubCounter()) return false;
if (AF.getAbCost().getLifeCost()) return false;
if (!ComputerUtil.canPayCost(saMe))
return false;
int damage = getNumDamage();
Random r = new Random(); // prevent run-away activations
boolean rr = false;
if(r.nextFloat() <= Math.pow(.6667, AF.getHostCard().getAbilityUsed()))
rr = true;
if(AF.getAbTgt().canTgtCreaturePlayer()) {
if(shouldTgtP(damage)) {
saMe.setTargetPlayer(Constant.Player.Human);
return rr;
}
Card c = chooseTgtC(damage);
if(c != null) {
saMe.setTargetCard(c);
return rr;
}
}
if(AF.getAbTgt().canTgtPlayer()/* || TgtOpp[0] == true */) {
saMe.setTargetPlayer(Constant.Player.Human);
return rr;
}
if(AF.getAbTgt().canTgtCreature()) {
Card c = chooseTgtC(damage);
if(c != null) {
saMe.setTargetCard(c);
return rr;
}
}
return false;
}
private static void doResolve(SpellAbility saMe)
{
int damage = getNumDamage();
String tgtP = "";
//if(TgtOpp[0] == true) {
// tgtP = AllZone.GameAction.getOpponent(card.getController());
// setTargetPlayer(tgtP);
//}
Card c = saMe.getTargetCard();
if(c != null) {
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(AF.getHostCard(), c)) {
AllZone.GameAction.addDamage(c, AF.getHostCard(), damage);
tgtP = c.getController();
if(AF.hasSubAbility())
CardFactoryUtil.doDrawBack(AF.getMapParams().get("SubAbility"), damage,
AF.getHostCard().getController(), AllZone.GameAction.getOpponent(AF.getHostCard().getController()),
tgtP, AF.getHostCard(), c, saMe);
}
} else {
tgtP = saMe.getTargetPlayer();
AllZone.GameAction.addDamage(tgtP, AF.getHostCard(), damage);
if(AF.hasSubAbility())
CardFactoryUtil.doDrawBack(AF.getMapParams().get("SubAbility"), damage,
AF.getHostCard().getController(), AllZone.GameAction.getOpponent(AF.getHostCard().getController()),
tgtP, AF.getHostCard(), null, saMe);
}
}
}