mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
AF: Cleanup, StoreSVar, Unattach
This commit is contained in:
9
.gitattributes
vendored
9
.gitattributes
vendored
@@ -12463,8 +12463,7 @@ src/main/java/forge/card/abilityfactory/AbilityFactory.java svneol=native#text/p
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactoryAttach.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactoryChangeZone.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactoryCharm.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactoryCleanup.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactoryStoreSVar.java -text
|
||||
src/main/java/forge/card/abilityfactory/CleanUpEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/CommonAbility.java -text
|
||||
src/main/java/forge/card/abilityfactory/CommonDrawback.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/CommonSpell.java -text
|
||||
@@ -12477,6 +12476,7 @@ src/main/java/forge/card/abilityfactory/ai/AnimateAllAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/BondAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/CanPlayAsDrawbackAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/CannotPlayAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/ChangeZoneAllAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/ChooseCardAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/ChooseCardNameAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/ChooseColorAi.java -text
|
||||
@@ -12544,12 +12544,14 @@ src/main/java/forge/card/abilityfactory/ai/ScryAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/SetStateAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/SetStateAllAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/ShuffleAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/StoreSVarAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/TapAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/TapAiBase.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/TapAllAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/TapOrUntapAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/TokenAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/TwoPilesAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/UnattachAllAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/UntapAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/UntapAllAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/AddTurnEffect.java -text
|
||||
@@ -12557,6 +12559,7 @@ src/main/java/forge/card/abilityfactory/effects/AnimateAllEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/AnimateEffectBase.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/effects/BondEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/ChangeZoneAllEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/ChooseCardEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/ChooseCardNameEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/ChooseColorEffect.java -text
|
||||
@@ -12629,11 +12632,13 @@ src/main/java/forge/card/abilityfactory/effects/ScryEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/SetStateAllEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/SetStateEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/ShuffleEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/StoreSVarEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/TapAllEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/TapEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/TapOrUntapEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/TokenEffect.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/effects/TwoPilesEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/UnattachAllEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/UntapAllEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/UntapEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/package-info.java svneol=native#text/plain
|
||||
|
||||
@@ -471,9 +471,8 @@ public class AbilityFactory {
|
||||
}
|
||||
|
||||
else if (this.api.equals("Cleanup")) {
|
||||
if (this.isDb) {
|
||||
spellAbility = AbilityFactoryCleanup.getDrawback(this);
|
||||
}
|
||||
ai = new AlwaysPlayAi();
|
||||
se = new CleanUpEffect();
|
||||
}
|
||||
|
||||
else if (this.api.equals("Clone")) {
|
||||
@@ -810,13 +809,8 @@ public class AbilityFactory {
|
||||
}
|
||||
|
||||
else if (this.api.equals("StoreSVar")) {
|
||||
if (this.isAb) {
|
||||
spellAbility = AbilityFactoryStoreSVar.createAbilityStoreSVar(this);
|
||||
} else if (this.isSp) {
|
||||
spellAbility = AbilityFactoryStoreSVar.createSpellStoreSVar(this);
|
||||
} else if (this.isDb) {
|
||||
spellAbility = AbilityFactoryStoreSVar.createDrawbackStoreSVar(this);
|
||||
}
|
||||
ai = new StoreSVarAi();
|
||||
se = new StoreSVarEffect();
|
||||
}
|
||||
|
||||
else if (this.api.equals("Tap")) {
|
||||
@@ -845,13 +839,8 @@ public class AbilityFactory {
|
||||
}
|
||||
|
||||
else if (this.api.equals("UnattachAll")) {
|
||||
if (this.isAb) {
|
||||
spellAbility = AbilityFactoryAttach.createAbilityUnattachAll(this);
|
||||
} else if (this.isSp) {
|
||||
spellAbility = AbilityFactoryAttach.createSpellUnattachAll(this);
|
||||
} else if (this.isDb) {
|
||||
spellAbility = AbilityFactoryAttach.createDrawbackUnattachAll(this);
|
||||
}
|
||||
ai = new UnattachAllAi();
|
||||
se = new UnattachAllEffect();
|
||||
}
|
||||
|
||||
else if (this.api.equals("Untap")) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
@@ -1446,402 +1447,5 @@ public class AbilityFactoryAttach {
|
||||
// ************************ UnattachAll *************************
|
||||
// **************************************************************
|
||||
|
||||
/**
|
||||
* Creates the ability unattachAll.
|
||||
*
|
||||
* @param af
|
||||
* the aF
|
||||
* @return the spell ability
|
||||
*/
|
||||
public static SpellAbility createAbilityUnattachAll(final AbilityFactory af) {
|
||||
class AbilityUnattachAll extends AbilityActivated {
|
||||
public AbilityUnattachAll(final Card ca, final Cost co, final Target t) {
|
||||
super(ca, co, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilityActivated getCopy() {
|
||||
AbilityActivated res = new AbilityUnattachAll(getSourceCard(),
|
||||
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 5946312226232487294L;
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return AbilityFactoryAttach.unattachAllCanPlayAI(getActivatingPlayer(), af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryAttach.unattachAllResolve(af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return AbilityFactoryAttach.unattachAllStackDescription(af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory) {
|
||||
return AbilityFactoryAttach.unattachAllDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
|
||||
}
|
||||
}
|
||||
final SpellAbility abUnattachAll = new AbilityUnattachAll(af.getHostCard(), af.getAbCost(), af.getAbTgt());
|
||||
|
||||
return abUnattachAll;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the spell unattachAll.
|
||||
*
|
||||
* @param af
|
||||
* the AbilityFactory
|
||||
* @return the spell ability
|
||||
*/
|
||||
public static SpellAbility createSpellUnattachAll(final AbilityFactory af) {
|
||||
final SpellAbility spUnattachAll = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
|
||||
private static final long serialVersionUID = 5531073401713526341L;
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return AbilityFactoryAttach.unattachAllCanPlayAI(getActivatingPlayer(), af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryAttach.unattachAllResolve(af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return AbilityFactoryAttach.unattachAllStackDescription(af, this);
|
||||
}
|
||||
};
|
||||
return spUnattachAll;
|
||||
}
|
||||
|
||||
// Attach Drawback
|
||||
/**
|
||||
* Creates the drawback unattachAll.
|
||||
*
|
||||
* @param af
|
||||
* the aF
|
||||
* @return the spell ability
|
||||
*/
|
||||
public static SpellAbility createDrawbackUnattachAll(final AbilityFactory af) {
|
||||
class DrawbackUnattachAll extends AbilitySub {
|
||||
public DrawbackUnattachAll(final Card ca, final Target t) {
|
||||
super(ca, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilitySub getCopy() {
|
||||
AbilitySub res = new DrawbackUnattachAll(getSourceCard(),
|
||||
getTarget() == null ? null : new Target(getTarget()));
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 9007743612927046143L;
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryAttach.unattachAllResolve(af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback() {
|
||||
return AbilityFactoryAttach.unattachAllPlayDrawbackAI(getActivatingPlayer(), af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return AbilityFactoryAttach.unattachAllStackDescription(af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory) {
|
||||
return AbilityFactoryAttach.unattachAllDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
|
||||
}
|
||||
}
|
||||
final SpellAbility dbUnattachAll = new DrawbackUnattachAll(af.getHostCard(), af.getAbTgt());
|
||||
|
||||
return dbUnattachAll;
|
||||
}
|
||||
|
||||
/**
|
||||
* UnattachAll stack description.
|
||||
*
|
||||
* @param af
|
||||
* the af
|
||||
* @param sa
|
||||
* the sa
|
||||
* @return the string
|
||||
*/
|
||||
private static String unattachAllStackDescription(final AbilityFactory af, final SpellAbility sa) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (sa instanceof AbilitySub) {
|
||||
sb.append(" ");
|
||||
} else {
|
||||
sb.append(sa.getSourceCard()).append(" - ");
|
||||
}
|
||||
|
||||
sb.append("Unattach all valid Equipment and Auras from ");
|
||||
|
||||
ArrayList<Object> targets;
|
||||
|
||||
// Should never allow more than one Attachment per card
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
targets = tgt.getTargets();
|
||||
} else {
|
||||
targets = AbilityFactory.getDefinedObjects(sa.getSourceCard(), af.getMapParams().get("Defined"), sa);
|
||||
}
|
||||
|
||||
for (final Object o : targets) {
|
||||
sb.append(o).append(" ");
|
||||
}
|
||||
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null) {
|
||||
sb.append(abSub.getStackDescription());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static boolean unattachAllCanPlayAI(final Player ai, final AbilityFactory af, final SpellAbility sa) {
|
||||
final Random r = MyRandom.getRandom();
|
||||
final Cost abCost = sa.getPayCosts();
|
||||
final Card source = sa.getSourceCard();
|
||||
|
||||
if (abCost != null) {
|
||||
// No Aura spells have Additional Costs
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
boolean chance = r.nextFloat() <= .9;
|
||||
|
||||
// Attach spells always have a target
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
tgt.resetTargets();
|
||||
}
|
||||
|
||||
if (abCost != null && abCost.getTotalMana().contains("X") && source.getSVar("X").equals("Count$xPaid")) {
|
||||
final int xPay = ComputerUtil.determineLeftoverMana(sa, ai);
|
||||
|
||||
if (xPay == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
source.setSVar("PayX", Integer.toString(xPay));
|
||||
}
|
||||
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)
|
||||
&& !"Curse".equals(af.getMapParams().get("AILogic"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return chance;
|
||||
}
|
||||
|
||||
private static boolean unattachAllDoTriggerAI(final Player ai, final AbilityFactory af, final SpellAbility sa, final boolean mandatory) {
|
||||
final Map<String, String> params = af.getMapParams();
|
||||
final Card card = sa.getSourceCard();
|
||||
|
||||
if (!ComputerUtil.canPayCost(sa, ai)) {
|
||||
// usually not mandatory
|
||||
return false;
|
||||
}
|
||||
|
||||
final Player opp = ai.getOpponent();
|
||||
// Check if there are any valid targets
|
||||
ArrayList<Object> targets = new ArrayList<Object>();
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt == null) {
|
||||
targets = AbilityFactory.getDefinedObjects(sa.getSourceCard(), params.get("Defined"), sa);
|
||||
}
|
||||
|
||||
if (!mandatory && card.isEquipment() && !targets.isEmpty()) {
|
||||
Card newTarget = (Card) targets.get(0);
|
||||
//don't equip human creatures
|
||||
if (newTarget.getController().equals(opp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//don't equip a worse creature
|
||||
if (card.isEquipping()) {
|
||||
Card oldTarget = card.getEquipping().get(0);
|
||||
if (CardFactoryUtil.evaluateCreature(oldTarget) > CardFactoryUtil.evaluateCreature(newTarget)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check SubAbilities DoTrigger?
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null) {
|
||||
return abSub.doTrigger(mandatory);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void unattachAllResolve(final AbilityFactory af, final SpellAbility sa) {
|
||||
final Map<String, String> params = af.getMapParams();
|
||||
Card source = sa.getSourceCard();
|
||||
|
||||
ArrayList<Object> targets;
|
||||
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
targets = tgt.getTargets();
|
||||
} else {
|
||||
targets = AbilityFactory.getDefinedObjects(source, params.get("Defined"), sa);
|
||||
}
|
||||
|
||||
// If Cast Targets will be checked on the Stack
|
||||
for (final Object o : targets) {
|
||||
String valid = params.get("UnattachValid");
|
||||
List<Card> unattachList = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
|
||||
unattachList = CardLists.getValidCards(unattachList, valid.split(","), source.getController(), source);
|
||||
for (final Card c : unattachList) {
|
||||
AbilityFactoryAttach.handleUnattachment(o, c, af);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleUnattachment(final Object o, final Card cardToUnattach, final AbilityFactory af) {
|
||||
|
||||
if (o instanceof Card) {
|
||||
final Card c = (Card) o;
|
||||
if (cardToUnattach.isAura()) {
|
||||
//final boolean gainControl = "GainControl".equals(af.getMapParams().get("AILogic"));
|
||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
|
||||
} else if (cardToUnattach.isEquipment()) {
|
||||
if (cardToUnattach.isEquipping() && c.getEquippedBy().contains(cardToUnattach)) {
|
||||
cardToUnattach.unEquipCard(cardToUnattach.getEquipping().get(0));
|
||||
}
|
||||
//TODO - unfortify would also be handled here
|
||||
}
|
||||
} else if (o instanceof Player) {
|
||||
final Player p = (Player) o;
|
||||
if (cardToUnattach.isAura() && p.getEnchantedBy().contains(cardToUnattach)) {
|
||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, p, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this isn't modifed to handled unattach yet, but should be for things like Remove Enchantments, etc.
|
||||
private static void handleUnattachAura(final Card card, final GameEntity tgt, final boolean gainControl) {
|
||||
if (card.isEnchanting()) {
|
||||
// If this Card is already Enchanting something
|
||||
// Need to unenchant it, then clear out the commands
|
||||
final GameEntity oldEnchanted = card.getEnchanting();
|
||||
card.removeEnchanting(oldEnchanted);
|
||||
card.clearEnchantCommand();
|
||||
card.clearUnEnchantCommand();
|
||||
card.clearTriggers(); // not sure if cleartriggers is needed?
|
||||
}
|
||||
|
||||
if (gainControl) {
|
||||
// Handle GainControl Auras
|
||||
final Player[] pl = new Player[1];
|
||||
|
||||
if (tgt instanceof Card) {
|
||||
pl[0] = ((Card) tgt).getController();
|
||||
} else {
|
||||
pl[0] = (Player) tgt;
|
||||
}
|
||||
|
||||
final Command onEnchant = new Command() {
|
||||
private static final long serialVersionUID = -2519887209491512000L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Card crd = card.getEnchantingCard();
|
||||
if (crd == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
pl[0] = crd.getController();
|
||||
|
||||
crd.addController(card);
|
||||
|
||||
} // execute()
|
||||
}; // Command
|
||||
|
||||
final Command onUnEnchant = new Command() {
|
||||
private static final long serialVersionUID = 3426441132121179288L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Card crd = card.getEnchantingCard();
|
||||
if (crd == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (AllZoneUtil.isCardInPlay(crd)) {
|
||||
crd.removeController(card);
|
||||
}
|
||||
|
||||
} // execute()
|
||||
}; // Command
|
||||
|
||||
final Command onChangesControl = new Command() {
|
||||
private static final long serialVersionUID = -65903786170234039L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Card crd = card.getEnchantingCard();
|
||||
if (crd == null) {
|
||||
return;
|
||||
}
|
||||
crd.removeController(card); // This looks odd, but will
|
||||
// simply refresh controller
|
||||
crd.addController(card);
|
||||
} // execute()
|
||||
}; // Command
|
||||
|
||||
// Add Enchant Commands for Control changers
|
||||
card.addEnchantCommand(onEnchant);
|
||||
card.addUnEnchantCommand(onUnEnchant);
|
||||
card.addChangeControllerCommand(onChangesControl);
|
||||
}
|
||||
|
||||
final Command onLeavesPlay = new Command() {
|
||||
private static final long serialVersionUID = -639204333673364477L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final GameEntity entity = card.getEnchanting();
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
card.unEnchantEntity(entity);
|
||||
}
|
||||
}; // Command
|
||||
|
||||
card.addLeavesPlayCommand(onLeavesPlay);
|
||||
card.enchantEntity(tgt);
|
||||
}
|
||||
*/
|
||||
|
||||
private static boolean unattachAllPlayDrawbackAI(final Player ai, final AbilityFactory af, final SpellAbility sa) {
|
||||
// AI should only activate this during Human's turn
|
||||
boolean chance = AbilityFactoryAttach.unattachAllCanPlayAI(ai, af, sa);
|
||||
|
||||
final AbilitySub subAb = sa.getSubAbility();
|
||||
if (subAb != null) {
|
||||
chance &= subAb.chkAIDrawback();
|
||||
}
|
||||
|
||||
return chance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.card.abilityfactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
|
||||
// Cleanup is not the same as other AFs, it is only used as a Drawback, and only used to Cleanup particular card states
|
||||
// That need to be reset. I'm creating this to clear Remembered Cards at the
|
||||
// end of an Effect so they don't get shown on a card
|
||||
// After the effect finishes resolving.
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_Cleanup class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public final class AbilityFactoryCleanup {
|
||||
|
||||
private AbilityFactoryCleanup() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getDrawback.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @return a {@link forge.card.spellability.AbilitySub} object.
|
||||
*/
|
||||
public static AbilitySub getDrawback(final AbilityFactory af) {
|
||||
class DrawbackCleanup extends AbilitySub {
|
||||
public DrawbackCleanup(final Card ca, final Target t) {
|
||||
super(ca, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilitySub getCopy() {
|
||||
AbilitySub res = new DrawbackCleanup(getSourceCard(),
|
||||
getTarget() == null ? null : new Target(getTarget()));
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 6192972525033429820L;
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryCleanup.doResolve(af, this);
|
||||
}
|
||||
}
|
||||
final AbilitySub drawback = new DrawbackCleanup(af.getHostCard(), af.getAbTgt());
|
||||
|
||||
return drawback;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* doResolve.
|
||||
* </p>
|
||||
*
|
||||
* @param AF
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
private static void doResolve(final AbilityFactory af, final SpellAbility sa) {
|
||||
final Map<String, String> params = af.getMapParams();
|
||||
Card source = sa.getSourceCard();
|
||||
|
||||
if (params.containsKey("ClearRemembered")) {
|
||||
source.clearRemembered();
|
||||
Singletons.getModel().getGame().getCardState(source).clearRemembered();
|
||||
}
|
||||
if (params.containsKey("ClearImprinted")) {
|
||||
source.clearImprinted();
|
||||
}
|
||||
if (params.containsKey("ClearChosenX")) {
|
||||
source.setSVar("ChosenX", "");
|
||||
}
|
||||
if (params.containsKey("ClearChosenY")) {
|
||||
source.setSVar("ChosenY", "");
|
||||
}
|
||||
if (params.containsKey("ClearTriggered")) {
|
||||
Singletons.getModel().getGame().getTriggerHandler().clearDelayedTrigger(source);
|
||||
}
|
||||
}
|
||||
|
||||
} // end class AbilityFactory_Cleanup
|
||||
@@ -1,352 +0,0 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.card.abilityfactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.phase.CombatUtil;
|
||||
import forge.game.player.ComputerUtil;
|
||||
import forge.game.player.Player;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactoryStoreSVar class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: AbilityFactoryStoreSVar.java 15090 2012-04-07 12:50:31Z Max mtg $
|
||||
*/
|
||||
public class AbilityFactoryStoreSVar {
|
||||
/**
|
||||
* <p>
|
||||
* createAbilityStoreSVar.
|
||||
* </p>
|
||||
*
|
||||
* @param abilityFactory
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public static SpellAbility createAbilityStoreSVar(final AbilityFactory abilityFactory) {
|
||||
class AbilityStoreSVar extends AbilityActivated {
|
||||
public AbilityStoreSVar(final Card ca, final Cost co, final Target t) {
|
||||
super(ca, co, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilityActivated getCopy() {
|
||||
AbilityActivated res = new AbilityStoreSVar(getSourceCard(),
|
||||
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -7299561150243337080L;
|
||||
private final AbilityFactory af = abilityFactory;
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return AbilityFactoryStoreSVar.storeSVarStackDescription(this.af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return AbilityFactoryStoreSVar.storeSVarCanPlayAI(this.af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryStoreSVar.storeSVarResolve(this.af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory) {
|
||||
return AbilityFactoryStoreSVar.storeSVarDoTriggerAI(getActivatingPlayer(), this.af, this, mandatory);
|
||||
}
|
||||
}
|
||||
final SpellAbility abStoreSVar = new AbilityStoreSVar(abilityFactory.getHostCard(), abilityFactory.getAbCost(),
|
||||
abilityFactory.getAbTgt());
|
||||
return abStoreSVar;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* createSpellStoreSVar.
|
||||
* </p>
|
||||
*
|
||||
* @param abilityFactory
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public static SpellAbility createSpellStoreSVar(final AbilityFactory abilityFactory) {
|
||||
final SpellAbility spStoreSVar = new Spell(abilityFactory.getHostCard(), abilityFactory.getAbCost(),
|
||||
abilityFactory.getAbTgt()) {
|
||||
private static final long serialVersionUID = 6631124959690157874L;
|
||||
|
||||
private final AbilityFactory af = abilityFactory;
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
// when getStackDesc is called, just build exactly what is
|
||||
// happening
|
||||
return AbilityFactoryStoreSVar.storeSVarStackDescription(this.af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return AbilityFactoryStoreSVar.storeSVarCanPlayAI(this.af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryStoreSVar.storeSVarResolve(this.af, this);
|
||||
}
|
||||
|
||||
};
|
||||
return spStoreSVar;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* createDrawbackStoreSVar.
|
||||
* </p>
|
||||
*
|
||||
* @param abilityFactory
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public static SpellAbility createDrawbackStoreSVar(final AbilityFactory abilityFactory) {
|
||||
class DrawbackStoreSVar extends AbilitySub {
|
||||
public DrawbackStoreSVar(final Card ca, final Target t) {
|
||||
super(ca, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilitySub getCopy() {
|
||||
AbilitySub res = new DrawbackStoreSVar(getSourceCard(),
|
||||
getTarget() == null ? null : new Target(getTarget()));
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 6631124959690157874L;
|
||||
|
||||
private final AbilityFactory af = abilityFactory;
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
// when getStackDesc is called, just build exactly what is
|
||||
// happening
|
||||
return AbilityFactoryStoreSVar.storeSVarStackDescription(this.af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return AbilityFactoryStoreSVar.storeSVarCanPlayAI(this.af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryStoreSVar.storeSVarResolve(this.af, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback() {
|
||||
boolean randomReturn = true;
|
||||
final AbilitySub subAb = this.getSubAbility();
|
||||
if (subAb != null) {
|
||||
randomReturn &= subAb.chkAIDrawback();
|
||||
}
|
||||
|
||||
return randomReturn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory) {
|
||||
return AbilityFactoryStoreSVar.storeSVarDoTriggerAI(getActivatingPlayer(), this.af, this, mandatory);
|
||||
}
|
||||
}
|
||||
final SpellAbility dbStoreSVar = new DrawbackStoreSVar(abilityFactory.getHostCard(), abilityFactory.getAbTgt());
|
||||
|
||||
return dbStoreSVar;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* storeSVarStackDescription.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public static String storeSVarStackDescription(final AbilityFactory af, final SpellAbility sa) {
|
||||
final Map<String, String> params = af.getMapParams();
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (sa instanceof AbilitySub) {
|
||||
sb.append(" ");
|
||||
} else {
|
||||
sb.append(sa.getSourceCard().getName()).append(" - ");
|
||||
}
|
||||
|
||||
if (params.containsKey("StackDescription")) {
|
||||
sb.append(params.get("StackDescription").replaceAll("CARDNAME", sa.getSourceCard().getName()));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
sb.append(sa.getDescription());
|
||||
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null) {
|
||||
sb.append(abSub.getStackDescription());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* storeSVarCanPlayAI.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean storeSVarCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
|
||||
//Tree of Redemption
|
||||
final Player ai = sa.getActivatingPlayer();
|
||||
final Card source = sa.getSourceCard();
|
||||
if (ComputerUtil.waitForBlocking(sa) || ai.getLife() + 1 >= source.getNetDefense()
|
||||
|| (ai.getLife() > 5 && !CombatUtil.lifeInSeriousDanger(ai, Singletons.getModel().getGame().getCombat()))) {
|
||||
return false;
|
||||
}
|
||||
final AbilitySub subAb = sa.getSubAbility();
|
||||
if (subAb != null && !subAb.chkAIDrawback()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* storeSVarDoTriggerAI.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param mandatory
|
||||
* a boolean.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean storeSVarDoTriggerAI(final Player ai, final AbilityFactory af, final SpellAbility sa, final boolean mandatory) {
|
||||
if (!ComputerUtil.canPayCost(sa, ai) && !mandatory) {
|
||||
// payment it's usually
|
||||
// not mandatory
|
||||
return false;
|
||||
}
|
||||
|
||||
// check SubAbilities DoTrigger?
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null) {
|
||||
return abSub.doTrigger(mandatory);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* storeSVarResolve.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public static void storeSVarResolve(final AbilityFactory af, final SpellAbility sa) {
|
||||
//SVar$ OldToughness | Type$ Count | Expression$ CardToughness
|
||||
final Map<String, String> params = af.getMapParams();
|
||||
Card source = sa.getSourceCard();
|
||||
|
||||
String key = null;
|
||||
String type = null;
|
||||
String expr = null;
|
||||
|
||||
if (params.containsKey("SVar")) {
|
||||
key = params.get("SVar");
|
||||
}
|
||||
|
||||
if (params.containsKey("Type")) {
|
||||
type = params.get("Type");
|
||||
}
|
||||
|
||||
if (params.containsKey("Expression")) {
|
||||
expr = params.get("Expression");
|
||||
}
|
||||
|
||||
if (key == null || type == null || expr == null) {
|
||||
System.out.println("SVar, Type and Expression paramaters required for StoreSVar. They are missing for " + source.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
|
||||
if (type.equals("Count")) {
|
||||
value = CardFactoryUtil.xCount(source, expr);
|
||||
}
|
||||
else if (type.equals("Number")) {
|
||||
value = Integer.valueOf(expr);
|
||||
}
|
||||
else if (type.equals("CountSVar")) {
|
||||
value = CardFactoryUtil.xCount(source, "SVar$" + expr);
|
||||
}
|
||||
//TODO For other types call a different function
|
||||
|
||||
StringBuilder numBuilder = new StringBuilder();
|
||||
numBuilder.append("Number$");
|
||||
numBuilder.append(value);
|
||||
|
||||
source.setSVar(key, numBuilder.toString());
|
||||
|
||||
SpellAbility root = sa.getRootSpellAbility();
|
||||
while(root != null) {
|
||||
root.setSVar(key, numBuilder.toString());
|
||||
root = root.getSubAbility();
|
||||
}
|
||||
}
|
||||
|
||||
} // end class AbilityFactorystoreSVar
|
||||
36
src/main/java/forge/card/abilityfactory/CleanUpEffect.java
Normal file
36
src/main/java/forge/card/abilityfactory/CleanUpEffect.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package forge.card.abilityfactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class CleanUpEffect extends SpellEffect {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellEffect#resolve(java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
public void resolve(Map<String, String> params, SpellAbility sa) {
|
||||
Card source = sa.getSourceCard();
|
||||
|
||||
if (params.containsKey("ClearRemembered")) {
|
||||
source.clearRemembered();
|
||||
Singletons.getModel().getGame().getCardState(source).clearRemembered();
|
||||
}
|
||||
if (params.containsKey("ClearImprinted")) {
|
||||
source.clearImprinted();
|
||||
}
|
||||
if (params.containsKey("ClearChosenX")) {
|
||||
source.setSVar("ChosenX", "");
|
||||
}
|
||||
if (params.containsKey("ClearChosenY")) {
|
||||
source.setSVar("ChosenY", "");
|
||||
}
|
||||
if (params.containsKey("ClearTriggered")) {
|
||||
Singletons.getModel().getGame().getTriggerHandler().clearDelayedTrigger(source);
|
||||
}
|
||||
}
|
||||
|
||||
} // end class AbilityFactory_Cleanup
|
||||
@@ -58,11 +58,10 @@ public class CommonAbility extends AbilityActivated {
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return ai.canPlayAI(getActivatingPlayer(), params, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory) {
|
||||
return ai.doTriggerAI(this.getActivatingPlayer(), params, this, mandatory);
|
||||
}
|
||||
|
||||
}
|
||||
297
src/main/java/forge/card/abilityfactory/ai/ChangeZoneAllAi.java
Normal file
297
src/main/java/forge/card/abilityfactory/ai/ChangeZoneAllAi.java
Normal file
@@ -0,0 +1,297 @@
|
||||
package forge.card.abilityfactory.ai;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.Singletons;
|
||||
import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.abilityfactory.SpellAiLogic;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
public class ChangeZoneAllAi extends SpellAiLogic {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
public boolean canPlayAI(Player ai, Map<String, String> params, SpellAbility sa) {
|
||||
// Change Zone All, can be any type moving from one zone to another
|
||||
final Cost abCost = sa.getAbilityFactory().getAbCost();
|
||||
final Card source = sa.getSourceCard();
|
||||
final ZoneType destination = ZoneType.smartValueOf(params.get("Destination"));
|
||||
final ZoneType origin = ZoneType.smartValueOf(params.get("Origin"));
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (!CostUtil.checkLifeCost(ai, abCost, source, 4, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CostUtil.checkDiscardCost(ai, abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final Random r = MyRandom.getRandom();
|
||||
// prevent run-away activations - first time will always return true
|
||||
boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
|
||||
|
||||
// TODO targeting with ChangeZoneAll
|
||||
// really two types of targeting.
|
||||
// Target Player has all their types change zones
|
||||
// or target permanent and do something relative to that permanent
|
||||
// ex. "Return all Auras attached to target"
|
||||
// ex. "Return all blocking/blocked by target creature"
|
||||
|
||||
final Player opp = ai.getOpponent();
|
||||
final List<Card> humanType = AbilityFactory.filterListByType(opp.getCardsIn(origin), params.get("ChangeType"), sa);
|
||||
List<Card> computerType = ai.getCardsIn(origin);
|
||||
computerType = AbilityFactory.filterListByType(computerType, params.get("ChangeType"), sa);
|
||||
final Target tgt = sa.getTarget();
|
||||
|
||||
// TODO improve restrictions on when the AI would want to use this
|
||||
// spBounceAll has some AI we can compare to.
|
||||
if (origin.equals(ZoneType.Hand) || origin.equals(ZoneType.Library)) {
|
||||
if (tgt != null) {
|
||||
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|
||||
|| !opp.canBeTargetedBy(sa)) {
|
||||
return false;
|
||||
}
|
||||
tgt.resetTargets();
|
||||
tgt.addTarget(opp);
|
||||
}
|
||||
} else if (origin.equals(ZoneType.Battlefield)) {
|
||||
// this statement is assuming the AI is trying to use this spell
|
||||
// offensively
|
||||
// if the AI is using it defensively, then something else needs to
|
||||
// occur
|
||||
// if only creatures are affected evaluate both lists and pass only
|
||||
// if human creatures are more valuable
|
||||
if (tgt != null) {
|
||||
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|
||||
|| !opp.canBeTargetedBy(sa)) {
|
||||
return false;
|
||||
}
|
||||
tgt.resetTargets();
|
||||
tgt.addTarget(opp);
|
||||
computerType.clear();
|
||||
}
|
||||
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||
if ((CardFactoryUtil.evaluateCreatureList(computerType) + 200) >= CardFactoryUtil
|
||||
.evaluateCreatureList(humanType)) {
|
||||
return false;
|
||||
}
|
||||
} // otherwise evaluate both lists by CMC and pass only if human
|
||||
// permanents are more valuable
|
||||
else if ((CardFactoryUtil.evaluatePermanentList(computerType) + 3) >= CardFactoryUtil
|
||||
.evaluatePermanentList(humanType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't cast during main1?
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.MAIN1, ai)) {
|
||||
return false;
|
||||
}
|
||||
} else if (origin.equals(ZoneType.Graveyard)) {
|
||||
if (tgt != null) {
|
||||
if (opp.getCardsIn(ZoneType.Graveyard).isEmpty()
|
||||
|| !opp.canBeTargetedBy(sa)) {
|
||||
return false;
|
||||
}
|
||||
tgt.resetTargets();
|
||||
tgt.addTarget(opp);
|
||||
}
|
||||
} else if (origin.equals(ZoneType.Exile)) {
|
||||
|
||||
} else if (origin.equals(ZoneType.Stack)) {
|
||||
// time stop can do something like this:
|
||||
// Origin$ Stack | Destination$ Exile | SubAbility$ DBSkip
|
||||
// DBSKipToPhase | DB$SkipToPhase | Phase$ Cleanup
|
||||
// otherwise, this situation doesn't exist
|
||||
return false;
|
||||
}
|
||||
|
||||
if (destination.equals(ZoneType.Battlefield)) {
|
||||
if (params.get("GainControl") != null) {
|
||||
// Check if the cards are valuable enough
|
||||
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||
if ((CardFactoryUtil.evaluateCreatureList(computerType) + CardFactoryUtil
|
||||
.evaluateCreatureList(humanType)) < 400) {
|
||||
return false;
|
||||
}
|
||||
} // otherwise evaluate both lists by CMC and pass only if human
|
||||
// permanents are less valuable
|
||||
else if ((CardFactoryUtil.evaluatePermanentList(computerType) + CardFactoryUtil
|
||||
.evaluatePermanentList(humanType)) < 6) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// don't activate if human gets more back than AI does
|
||||
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||
if (CardFactoryUtil.evaluateCreatureList(computerType) <= (CardFactoryUtil
|
||||
.evaluateCreatureList(humanType) + 100)) {
|
||||
return false;
|
||||
}
|
||||
} // otherwise evaluate both lists by CMC and pass only if human
|
||||
// permanents are less valuable
|
||||
else if (CardFactoryUtil.evaluatePermanentList(computerType) <= (CardFactoryUtil
|
||||
.evaluatePermanentList(humanType) + 2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final AbilitySub subAb = sa.getSubAbility();
|
||||
if (subAb != null) {
|
||||
chance &= subAb.chkAIDrawback();
|
||||
}
|
||||
|
||||
return (((r.nextFloat() < .8) || sa.isTrigger()) && chance);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* changeZoneAllPlayDrawbackAI.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
@Override
|
||||
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa, Player aiPlayer) {
|
||||
// if putting cards from hand to library and parent is drawing cards
|
||||
// make sure this will actually do something:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* gainLifeDoTriggerAINoCost.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param mandatory
|
||||
* a boolean.
|
||||
* @return a boolean.
|
||||
*/
|
||||
@Override
|
||||
public boolean doTriggerAINoCost(Player ai, java.util.Map<String,String> params, SpellAbility sa, boolean mandatory) {
|
||||
// Change Zone All, can be any type moving from one zone to another
|
||||
|
||||
final ZoneType destination = ZoneType.smartValueOf(params.get("Destination"));
|
||||
final ZoneType origin = ZoneType.smartValueOf(params.get("Origin"));
|
||||
|
||||
final Player opp = ai.getOpponent();
|
||||
final List<Card> humanType = AbilityFactory.filterListByType(opp.getCardsIn(origin), params.get("ChangeType"), sa);
|
||||
List<Card> computerType = ai.getCardsIn(origin);
|
||||
computerType = AbilityFactory.filterListByType(computerType, params.get("ChangeType"), sa);
|
||||
|
||||
// TODO improve restrictions on when the AI would want to use this
|
||||
// spBounceAll has some AI we can compare to.
|
||||
if (origin.equals(ZoneType.Hand) || origin.equals(ZoneType.Library)) {
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|
||||
|| !opp.canBeTargetedBy(sa)) {
|
||||
return false;
|
||||
}
|
||||
tgt.resetTargets();
|
||||
tgt.addTarget(opp);
|
||||
}
|
||||
} else if (origin.equals(ZoneType.Battlefield)) {
|
||||
// this statement is assuming the AI is trying to use this spell offensively
|
||||
// if the AI is using it defensively, then something else needs to occur
|
||||
// if only creatures are affected evaluate both lists and pass only
|
||||
// if human creatures are more valuable
|
||||
if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) {
|
||||
if (CardFactoryUtil.evaluateCreatureList(computerType) >= CardFactoryUtil
|
||||
.evaluateCreatureList(humanType)) {
|
||||
return false;
|
||||
}
|
||||
} // otherwise evaluate both lists by CMC and pass only if human
|
||||
// permanents are more valuable
|
||||
else if (CardFactoryUtil.evaluatePermanentList(computerType) >= CardFactoryUtil
|
||||
.evaluatePermanentList(humanType)) {
|
||||
return false;
|
||||
}
|
||||
} else if (origin.equals(ZoneType.Graveyard)) {
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
if (opp.getCardsIn(ZoneType.Graveyard).isEmpty()
|
||||
|| !opp.canBeTargetedBy(sa)) {
|
||||
return false;
|
||||
}
|
||||
tgt.resetTargets();
|
||||
tgt.addTarget(opp);
|
||||
}
|
||||
} else if (origin.equals(ZoneType.Exile)) {
|
||||
|
||||
} else if (origin.equals(ZoneType.Stack)) {
|
||||
// time stop can do something like this:
|
||||
// Origin$ Stack | Destination$ Exile | SubAbility$ DBSkip
|
||||
// DBSKipToPhase | DB$SkipToPhase | Phase$ Cleanup
|
||||
// otherwise, this situation doesn't exist
|
||||
return false;
|
||||
}
|
||||
|
||||
if (destination.equals(ZoneType.Battlefield)) {
|
||||
if (params.get("GainControl") != null) {
|
||||
// Check if the cards are valuable enough
|
||||
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||
if ((CardFactoryUtil.evaluateCreatureList(computerType) + CardFactoryUtil
|
||||
.evaluateCreatureList(humanType)) < 1) {
|
||||
return false;
|
||||
}
|
||||
} // otherwise evaluate both lists by CMC and pass only if human
|
||||
// permanents are less valuable
|
||||
else if ((CardFactoryUtil.evaluatePermanentList(computerType) + CardFactoryUtil
|
||||
.evaluatePermanentList(humanType)) < 1) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// don't activate if human gets more back than AI does
|
||||
if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) {
|
||||
if (CardFactoryUtil.evaluateCreatureList(computerType) <= CardFactoryUtil
|
||||
.evaluateCreatureList(humanType)) {
|
||||
return false;
|
||||
}
|
||||
} // otherwise evaluate both lists by CMC and pass only if human
|
||||
// permanents are less valuable
|
||||
else if (CardFactoryUtil.evaluatePermanentList(computerType) <= CardFactoryUtil
|
||||
.evaluatePermanentList(humanType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean chance = true;
|
||||
final AbilitySub subAb = sa.getSubAbility();
|
||||
if (subAb != null) {
|
||||
chance &= subAb.chkAIDrawback();
|
||||
}
|
||||
|
||||
return chance;
|
||||
}
|
||||
|
||||
}
|
||||
50
src/main/java/forge/card/abilityfactory/ai/StoreSVarAi.java
Normal file
50
src/main/java/forge/card/abilityfactory/ai/StoreSVarAi.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package forge.card.abilityfactory.ai;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.abilityfactory.SpellAiLogic;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.phase.CombatUtil;
|
||||
import forge.game.player.ComputerUtil;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class StoreSVarAi extends SpellAiLogic {
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI(Player ai, java.util.Map<String,String> params, SpellAbility sa) {
|
||||
//Tree of Redemption
|
||||
|
||||
final Card source = sa.getSourceCard();
|
||||
if (ComputerUtil.waitForBlocking(sa) || ai.getLife() + 1 >= source.getNetDefense()
|
||||
|| (ai.getLife() > 5 && !CombatUtil.lifeInSeriousDanger(ai, Singletons.getModel().getGame().getCombat()))) {
|
||||
return false;
|
||||
}
|
||||
final AbilitySub subAb = sa.getSubAbility();
|
||||
if (subAb != null && !subAb.chkAIDrawback()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa, Player aiPlayer) {
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doTriggerAINoCost(Player aiPlayer, java.util.Map<String,String> params, SpellAbility sa, boolean mandatory) {
|
||||
|
||||
// check SubAbilities DoTrigger?
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null) {
|
||||
return abSub.doTrigger(mandatory);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
124
src/main/java/forge/card/abilityfactory/ai/UnattachAllAi.java
Normal file
124
src/main/java/forge/card/abilityfactory/ai/UnattachAllAi.java
Normal file
@@ -0,0 +1,124 @@
|
||||
package forge.card.abilityfactory.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.abilityfactory.SpellAiLogic;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.ComputerUtil;
|
||||
import forge.game.player.Player;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
public class UnattachAllAi extends SpellAiLogic {
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
public boolean canPlayAI(Player ai, Map<String, String> params, SpellAbility sa) {
|
||||
final Random r = MyRandom.getRandom();
|
||||
final Cost abCost = sa.getPayCosts();
|
||||
final Card source = sa.getSourceCard();
|
||||
|
||||
if (abCost != null) {
|
||||
// No Aura spells have Additional Costs
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
boolean chance = r.nextFloat() <= .9;
|
||||
|
||||
// Attach spells always have a target
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
tgt.resetTargets();
|
||||
}
|
||||
|
||||
if (abCost != null && abCost.getTotalMana().contains("X") && source.getSVar("X").equals("Count$xPaid")) {
|
||||
final int xPay = ComputerUtil.determineLeftoverMana(sa, ai);
|
||||
|
||||
if (xPay == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
source.setSVar("PayX", Integer.toString(xPay));
|
||||
}
|
||||
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)
|
||||
&& !"Curse".equals(params.get("AILogic"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return chance;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#doTriggerAINoCost(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility, boolean)
|
||||
*/
|
||||
@Override
|
||||
public boolean doTriggerAINoCost(Player ai, Map<String, String> params, SpellAbility sa, boolean mandatory) {
|
||||
final Card card = sa.getSourceCard();
|
||||
final Player opp = ai.getOpponent();
|
||||
// Check if there are any valid targets
|
||||
ArrayList<Object> targets = new ArrayList<Object>();
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt == null) {
|
||||
targets = AbilityFactory.getDefinedObjects(sa.getSourceCard(), params.get("Defined"), sa);
|
||||
}
|
||||
|
||||
if (!mandatory && card.isEquipment() && !targets.isEmpty()) {
|
||||
Card newTarget = (Card) targets.get(0);
|
||||
//don't equip human creatures
|
||||
if (newTarget.getController().equals(opp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//don't equip a worse creature
|
||||
if (card.isEquipping()) {
|
||||
Card oldTarget = card.getEquipping().get(0);
|
||||
if (CardFactoryUtil.evaluateCreature(oldTarget) > CardFactoryUtil.evaluateCreature(newTarget)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check SubAbilities DoTrigger?
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null) {
|
||||
return abSub.doTrigger(mandatory);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa, Player ai) {
|
||||
// AI should only activate this during Human's turn
|
||||
return canPlayAI(ai, params, sa);
|
||||
}
|
||||
|
||||
/**
|
||||
* UnattachAll stack description.
|
||||
*
|
||||
* @param af
|
||||
* the af
|
||||
* @param sa
|
||||
* the sa
|
||||
* @return the string
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package forge.card.abilityfactory.effects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardCharacteristicName;
|
||||
import forge.CardPredicates;
|
||||
import forge.Singletons;
|
||||
import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.abilityfactory.AbilityFactoryAttach;
|
||||
import forge.card.abilityfactory.SpellEffect;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class ChangeZoneAllEffect extends SpellEffect {
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* changeZoneAllStackDescription.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
@Override
|
||||
protected String getStackDescription(java.util.Map<String,String> params, SpellAbility sa) {
|
||||
// TODO build Stack Description will need expansion as more cards are added
|
||||
|
||||
final String[] desc = sa.getDescription().split(":");
|
||||
|
||||
if (desc.length > 1) {
|
||||
return desc[1];
|
||||
} else {
|
||||
return desc[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* changeZoneAllResolve.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
@Override
|
||||
public void resolve(java.util.Map<String,String> params, SpellAbility sa) {
|
||||
final ZoneType destination = ZoneType.smartValueOf(params.get("Destination"));
|
||||
final List<ZoneType> origin = ZoneType.listValueOf(params.get("Origin"));
|
||||
|
||||
List<Card> cards = null;
|
||||
|
||||
ArrayList<Player> tgtPlayers = null;
|
||||
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
tgtPlayers = tgt.getTargetPlayers();
|
||||
} else if (params.containsKey("Defined")) {
|
||||
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||
}
|
||||
|
||||
if ((tgtPlayers == null) || tgtPlayers.isEmpty()) {
|
||||
cards = Singletons.getModel().getGame().getCardsIn(origin);
|
||||
} else {
|
||||
cards = tgtPlayers.get(0).getCardsIn(origin);
|
||||
}
|
||||
|
||||
cards = AbilityFactory.filterListByType(cards, params.get("ChangeType"), sa);
|
||||
|
||||
if (params.containsKey("ForgetOtherRemembered")) {
|
||||
sa.getSourceCard().clearRemembered();
|
||||
}
|
||||
|
||||
final String remember = params.get("RememberChanged");
|
||||
|
||||
// I don't know if library position is necessary. It's here if it is,
|
||||
// just in case
|
||||
final int libraryPos = params.containsKey("LibraryPosition") ? Integer.parseInt(params.get("LibraryPosition"))
|
||||
: 0;
|
||||
for (final Card c : cards) {
|
||||
if (destination.equals(ZoneType.Battlefield)) {
|
||||
// Auras without Candidates stay in their current location
|
||||
if (c.isAura()) {
|
||||
final SpellAbility saAura = AbilityFactoryAttach.getAttachSpellAbility(c);
|
||||
if (!saAura.getTarget().hasCandidates(saAura, false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (params.containsKey("Tapped")) {
|
||||
c.setTapped(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.containsKey("GainControl")) {
|
||||
c.addController(sa.getSourceCard());
|
||||
Singletons.getModel().getGame().getAction().moveToPlay(c, sa.getActivatingPlayer());
|
||||
} else {
|
||||
final Card movedCard = Singletons.getModel().getGame().getAction().moveTo(destination, c, libraryPos);
|
||||
if (params.containsKey("ExileFaceDown")) {
|
||||
movedCard.setState(CardCharacteristicName.FaceDown);
|
||||
}
|
||||
if (params.containsKey("Tapped")) {
|
||||
movedCard.setTapped(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (remember != null) {
|
||||
Singletons.getModel().getGame().getCardState(sa.getSourceCard()).addRemembered(c);
|
||||
}
|
||||
}
|
||||
|
||||
// if Shuffle parameter exists, and any amount of cards were owned by
|
||||
// that player, then shuffle that library
|
||||
if (params.containsKey("Shuffle")) {
|
||||
for( Player p : Singletons.getModel().getGame().getPlayers()) {
|
||||
if (Iterables.any(cards, CardPredicates.isOwner(p))) {
|
||||
p.shuffle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package forge.card.abilityfactory.effects;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.abilityfactory.SpellEffect;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
public class StoreSVarEffect extends SpellEffect {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* storeSVarResolve.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
@Override
|
||||
public void resolve(java.util.Map<String,String> params, SpellAbility sa) {
|
||||
//SVar$ OldToughness | Type$ Count | Expression$ CardToughness
|
||||
Card source = sa.getSourceCard();
|
||||
|
||||
String key = null;
|
||||
String type = null;
|
||||
String expr = null;
|
||||
|
||||
if (params.containsKey("SVar")) {
|
||||
key = params.get("SVar");
|
||||
}
|
||||
|
||||
if (params.containsKey("Type")) {
|
||||
type = params.get("Type");
|
||||
}
|
||||
|
||||
if (params.containsKey("Expression")) {
|
||||
expr = params.get("Expression");
|
||||
}
|
||||
|
||||
if (key == null || type == null || expr == null) {
|
||||
System.out.println("SVar, Type and Expression paramaters required for StoreSVar. They are missing for " + source.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
|
||||
if (type.equals("Count")) {
|
||||
value = CardFactoryUtil.xCount(source, expr);
|
||||
}
|
||||
else if (type.equals("Number")) {
|
||||
value = Integer.valueOf(expr);
|
||||
}
|
||||
else if (type.equals("CountSVar")) {
|
||||
value = CardFactoryUtil.xCount(source, "SVar$" + expr);
|
||||
}
|
||||
//TODO For other types call a different function
|
||||
|
||||
StringBuilder numBuilder = new StringBuilder();
|
||||
numBuilder.append("Number$");
|
||||
numBuilder.append(value);
|
||||
|
||||
source.setSVar(key, numBuilder.toString());
|
||||
|
||||
SpellAbility root = sa.getRootSpellAbility();
|
||||
while(root != null) {
|
||||
root.setSVar(key, numBuilder.toString());
|
||||
root = root.getSubAbility();
|
||||
}
|
||||
}
|
||||
|
||||
} // end class AbilityFactorystoreSVar
|
||||
@@ -0,0 +1,173 @@
|
||||
package forge.card.abilityfactory.effects;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
import forge.card.abilityfactory.SpellEffect;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class UnattachAllEffect extends SpellEffect {
|
||||
|
||||
private void handleUnattachment(final GameEntity o, final Card cardToUnattach) {
|
||||
|
||||
if (o instanceof Card) {
|
||||
final Card c = (Card) o;
|
||||
if (cardToUnattach.isAura()) {
|
||||
//final boolean gainControl = "GainControl".equals(af.getMapParams().get("AILogic"));
|
||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
|
||||
} else if (cardToUnattach.isEquipment()) {
|
||||
if (cardToUnattach.isEquipping() && c.getEquippedBy().contains(cardToUnattach)) {
|
||||
cardToUnattach.unEquipCard(cardToUnattach.getEquipping().get(0));
|
||||
}
|
||||
//TODO - unfortify would also be handled here
|
||||
}
|
||||
} else if (o instanceof Player) {
|
||||
final Player p = (Player) o;
|
||||
if (cardToUnattach.isAura() && p.getEnchantedBy().contains(cardToUnattach)) {
|
||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, p, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this isn't modifed to handled unattach yet, but should be for things like Remove Enchantments, etc.
|
||||
private static void handleUnattachAura(final Card card, final GameEntity tgt, final boolean gainControl) {
|
||||
if (card.isEnchanting()) {
|
||||
// If this Card is already Enchanting something
|
||||
// Need to unenchant it, then clear out the commands
|
||||
final GameEntity oldEnchanted = card.getEnchanting();
|
||||
card.removeEnchanting(oldEnchanted);
|
||||
card.clearEnchantCommand();
|
||||
card.clearUnEnchantCommand();
|
||||
card.clearTriggers(); // not sure if cleartriggers is needed?
|
||||
}
|
||||
|
||||
if (gainControl) {
|
||||
// Handle GainControl Auras
|
||||
final Player[] pl = new Player[1];
|
||||
|
||||
if (tgt instanceof Card) {
|
||||
pl[0] = ((Card) tgt).getController();
|
||||
} else {
|
||||
pl[0] = (Player) tgt;
|
||||
}
|
||||
|
||||
final Command onEnchant = new Command() {
|
||||
private static final long serialVersionUID = -2519887209491512000L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Card crd = card.getEnchantingCard();
|
||||
if (crd == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
pl[0] = crd.getController();
|
||||
|
||||
crd.addController(card);
|
||||
|
||||
} // execute()
|
||||
}; // Command
|
||||
|
||||
final Command onUnEnchant = new Command() {
|
||||
private static final long serialVersionUID = 3426441132121179288L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Card crd = card.getEnchantingCard();
|
||||
if (crd == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (AllZoneUtil.isCardInPlay(crd)) {
|
||||
crd.removeController(card);
|
||||
}
|
||||
|
||||
} // execute()
|
||||
}; // Command
|
||||
|
||||
final Command onChangesControl = new Command() {
|
||||
private static final long serialVersionUID = -65903786170234039L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Card crd = card.getEnchantingCard();
|
||||
if (crd == null) {
|
||||
return;
|
||||
}
|
||||
crd.removeController(card); // This looks odd, but will
|
||||
// simply refresh controller
|
||||
crd.addController(card);
|
||||
} // execute()
|
||||
}; // Command
|
||||
|
||||
// Add Enchant Commands for Control changers
|
||||
card.addEnchantCommand(onEnchant);
|
||||
card.addUnEnchantCommand(onUnEnchant);
|
||||
card.addChangeControllerCommand(onChangesControl);
|
||||
}
|
||||
|
||||
final Command onLeavesPlay = new Command() {
|
||||
private static final long serialVersionUID = -639204333673364477L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final GameEntity entity = card.getEnchanting();
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
card.unEnchantEntity(entity);
|
||||
}
|
||||
}; // Command
|
||||
|
||||
card.addLeavesPlayCommand(onLeavesPlay);
|
||||
card.enchantEntity(tgt);
|
||||
}
|
||||
*/
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
protected String getStackDescription(Map<String, String> params, SpellAbility sa) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Unattach all valid Equipment and Auras from ");
|
||||
final List<Object> targets = getTargetObjects(sa, params);
|
||||
sb.append(StringUtils.join(targets, " "));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellEffect#resolve(java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
public void resolve(Map<String, String> params, SpellAbility sa) {
|
||||
Card source = sa.getSourceCard();
|
||||
|
||||
final Target tgt = sa.getTarget();
|
||||
final List<Object> targets = getTargetObjects(sa, params);
|
||||
|
||||
|
||||
|
||||
// If Cast Targets will be checked on the Stack
|
||||
for (final Object o : targets) {
|
||||
if (!( o instanceof GameEntity )) continue;
|
||||
|
||||
String valid = params.get("UnattachValid");
|
||||
List<Card> unattachList = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
|
||||
unattachList = CardLists.getValidCards(unattachList, valid.split(","), source.getController(), source);
|
||||
for (final Card c : unattachList) {
|
||||
handleUnattachment((GameEntity)o, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user