mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
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:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -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
|
||||
|
||||
@@ -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,50 +119,50 @@ 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");
|
||||
}
|
||||
|
||||
|
||||
if (abAPI.equals("DealDamage"))
|
||||
{
|
||||
final int NumDmg[] = {-1};
|
||||
final int NumDmg[] = {-1};
|
||||
final String NumDmgX[] = {"none"};
|
||||
String tmpND = mapParams.get("NumDmg");
|
||||
if (tmpND.length() > 0)
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
189
src/forge/DealDamage.java
Normal 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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user