diff --git a/.gitattributes b/.gitattributes
index 0d51c9596e3..6048afb6489 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -12466,7 +12466,6 @@ src/main/java/forge/card/abilityfactory/AbilityFactoryCharm.java svneol=native#t
src/main/java/forge/card/abilityfactory/AbilityFactoryClash.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryCleanup.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryClone.java -text
-src/main/java/forge/card/abilityfactory/AbilityFactoryCombat.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryCopy.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryDelayedTrigger.java svneol=native#text/plain
@@ -12511,17 +12510,21 @@ src/main/java/forge/card/abilityfactory/ai/DrainManaAi.java -text
src/main/java/forge/card/abilityfactory/ai/DrawAi.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/ai/EffectAi.java -text
src/main/java/forge/card/abilityfactory/ai/EndTurnAi.java -text
+src/main/java/forge/card/abilityfactory/ai/FogAi.java -text
src/main/java/forge/card/abilityfactory/ai/LifeExchangeAi.java -text
src/main/java/forge/card/abilityfactory/ai/LifeGainAi.java -text
src/main/java/forge/card/abilityfactory/ai/LifeLoseAi.java -text
src/main/java/forge/card/abilityfactory/ai/LifeSetAi.java -text
src/main/java/forge/card/abilityfactory/ai/MillAi.java -text
+src/main/java/forge/card/abilityfactory/ai/MustAttackAi.java -text
+src/main/java/forge/card/abilityfactory/ai/MustBlockAi.java -text
src/main/java/forge/card/abilityfactory/ai/PlayAi.java -text
src/main/java/forge/card/abilityfactory/ai/PoisonAi.java -text
src/main/java/forge/card/abilityfactory/ai/ProtectAi.java -text
src/main/java/forge/card/abilityfactory/ai/ProtectAllAi.java -text
src/main/java/forge/card/abilityfactory/ai/RegenerateAi.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/ai/RegenerateAllAi.java -text
+src/main/java/forge/card/abilityfactory/ai/RemoveFromCombatAi.java -text
src/main/java/forge/card/abilityfactory/ai/ShuffleAi.java -text
src/main/java/forge/card/abilityfactory/ai/TokenAi.java -text
src/main/java/forge/card/abilityfactory/effects/AddTurnEffect.java -text
@@ -12551,18 +12554,22 @@ src/main/java/forge/card/abilityfactory/effects/DrainManaEffect.java -text
src/main/java/forge/card/abilityfactory/effects/DrawEffect.java -text
src/main/java/forge/card/abilityfactory/effects/EffectEffect.java -text
src/main/java/forge/card/abilityfactory/effects/EndTurnEffect.java -text
+src/main/java/forge/card/abilityfactory/effects/FogEffect.java -text
src/main/java/forge/card/abilityfactory/effects/HelperAnimate.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/effects/LifeExchangeEffect.java -text
src/main/java/forge/card/abilityfactory/effects/LifeGainEffect.java -text
src/main/java/forge/card/abilityfactory/effects/LifeLoseEffect.java -text
src/main/java/forge/card/abilityfactory/effects/LifeSetEffect.java -text
src/main/java/forge/card/abilityfactory/effects/MillEffect.java -text
+src/main/java/forge/card/abilityfactory/effects/MustAttackEffect.java -text
+src/main/java/forge/card/abilityfactory/effects/MustBlockEffect.java -text
src/main/java/forge/card/abilityfactory/effects/PlayEffect.java -text
src/main/java/forge/card/abilityfactory/effects/PoisonEffect.java -text
src/main/java/forge/card/abilityfactory/effects/ProtectAllEffect.java -text
src/main/java/forge/card/abilityfactory/effects/ProtectEffect.java -text
src/main/java/forge/card/abilityfactory/effects/RegenerateAllEffect.java -text
src/main/java/forge/card/abilityfactory/effects/RegenerateEffect.java -text
+src/main/java/forge/card/abilityfactory/effects/RemoveFromCombatEffect.java -text
src/main/java/forge/card/abilityfactory/effects/ShuffleEffect.java -text
src/main/java/forge/card/abilityfactory/effects/TokenEffect.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/package-info.java svneol=native#text/plain
diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactory.java b/src/main/java/forge/card/abilityfactory/AbilityFactory.java
index 81ea6f999db..1bb86d66cdc 100644
--- a/src/main/java/forge/card/abilityfactory/AbilityFactory.java
+++ b/src/main/java/forge/card/abilityfactory/AbilityFactory.java
@@ -729,13 +729,8 @@ public class AbilityFactory {
}
else if (this.api.equals("Fog")) {
- if (this.isAb) {
- spellAbility = AbilityFactoryCombat.createAbilityFog(this);
- } else if (this.isSp) {
- spellAbility = AbilityFactoryCombat.createSpellFog(this);
- } else if (this.isDb) {
- spellAbility = AbilityFactoryCombat.createDrawbackFog(this);
- }
+ ai = new FogAi();
+ se = new FogEffect();
}
else if (this.api.equals("GainControl")) {
@@ -809,23 +804,13 @@ public class AbilityFactory {
}
else if (this.api.equals("MustAttack")) {
- if (this.isAb) {
- spellAbility = AbilityFactoryCombat.createAbilityMustAttack(this);
- } else if (this.isSp) {
- spellAbility = AbilityFactoryCombat.createSpellMustAttack(this);
- } else if (this.isDb) {
- spellAbility = AbilityFactoryCombat.createDrawbackMustAttack(this);
- }
+ ai = new MustAttackAi();
+ se = new MustAttackEffect();
}
else if (this.api.equals("MustBlock")) {
- if (this.isAb) {
- spellAbility = AbilityFactoryCombat.createAbilityMustBlock(this);
- } else if (this.isSp) {
- spellAbility = AbilityFactoryCombat.createSpellMustBlock(this);
- } else if (this.isDb) {
- spellAbility = AbilityFactoryCombat.createDrawbackMustBlock(this);
- }
+ ai = new MustBlockAi();
+ se = new MustBlockEffect();
}
else if (this.api.equals("NameCard")) {
@@ -943,13 +928,8 @@ public class AbilityFactory {
}
else if (this.api.equals("RemoveFromCombat")) {
- if (this.isAb) {
- spellAbility = AbilityFactoryCombat.createAbilityRemoveFromCombat(this);
- } else if (this.isSp) {
- spellAbility = AbilityFactoryCombat.createSpellRemoveFromCombat(this);
- } else if (this.isDb) {
- spellAbility = AbilityFactoryCombat.createDrawbackRemoveFromCombat(this);
- }
+ ai = new RemoveFromCombatAi();
+ se = new RemoveFromCombatEffect();
}
else if (this.api.equals("Repeat")) {
diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryCombat.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryCombat.java
deleted file mode 100644
index 159a9a44fa1..00000000000
--- a/src/main/java/forge/card/abilityfactory/AbilityFactoryCombat.java
+++ /dev/null
@@ -1,1144 +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 .
- */
-package forge.card.abilityfactory;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import com.google.common.base.Predicate;
-
-import forge.Card;
-
-import forge.CardLists;
-import forge.CardPredicates;
-import forge.GameEntity;
-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.spellability.Target;
-import forge.card.cost.Cost;
-import forge.game.phase.CombatUtil;
-import forge.game.phase.PhaseType;
-import forge.game.player.ComputerUtil;
-import forge.game.player.Player;
-import forge.game.zone.ZoneType;
-
-
-/**
- *
- * AbilityFactory_Combat class.
- *
- *
- * @author Forge
- * @version $Id$
- */
-public final class AbilityFactoryCombat {
-
- private AbilityFactoryCombat() {
- throw new AssertionError();
- }
-
- // **************************************************************
- // ****************************** FOG **************************
- // **************************************************************
-
- /**
- *
- * createAbilityFog.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createAbilityFog(final AbilityFactory af) {
- class AbilityFog extends AbilityActivated {
- public AbilityFog(final Card ca, final Cost co, final Target t) {
- super(ca, co, t);
- }
-
- @Override
- public AbilityActivated getCopy() {
- AbilityActivated res = new AbilityFog(getSourceCard(),
- getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = -1933592438783630254L;
-
- @Override
- public String getStackDescription() {
- // when getStackDesc is called, just build exactly what is
- // happening
- return AbilityFactoryCombat.fogStackDescription(af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryCombat.fogCanPlayAI(getActivatingPlayer(), af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.fogResolve(af, this);
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryCombat.fogDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
- }
- }
- final SpellAbility abFog = new AbilityFog(af.getHostCard(), af.getAbCost(), af.getAbTgt());
-
- return abFog;
- }
-
- /**
- *
- * createSpellFog.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createSpellFog(final AbilityFactory af) {
- final SpellAbility spFog = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
- private static final long serialVersionUID = -5141246507533353605L;
-
- @Override
- public String getStackDescription() {
- // when getStackDesc is called, just build exactly what is
- // happening
- return AbilityFactoryCombat.fogStackDescription(af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryCombat.fogCanPlayAI(getActivatingPlayer(), af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.fogResolve(af, this);
- }
-
- };
- return spFog;
- }
-
- /**
- *
- * createDrawbackFog.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createDrawbackFog(final AbilityFactory af) {
- class DrawbackFog extends AbilitySub {
- public DrawbackFog(final Card ca, final Target t) {
- super(ca, t);
- }
-
- @Override
- public AbilitySub getCopy() {
- AbilitySub res = new DrawbackFog(getSourceCard(),
- getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = -5141246507533353605L;
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.fogResolve(af, this);
- }
-
- @Override
- public boolean chkAIDrawback() {
- return AbilityFactoryCombat.fogPlayDrawbackAI(af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryCombat.fogCanPlayAI(getActivatingPlayer(), af, this);
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryCombat.fogDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
- }
- }
- final SpellAbility dbFog = new DrawbackFog(af.getHostCard(), af.getAbTgt());
-
- return dbFog;
- }
-
- /**
- *
- * fogStackDescription.
- *
- *
- * @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 fogStackDescription(final AbilityFactory af, final SpellAbility sa) {
- final StringBuilder sb = new StringBuilder();
-
- if (!(sa instanceof AbilitySub)) {
- sb.append(sa.getSourceCard().getName()).append(" - ");
- } else {
- sb.append(" ");
- }
-
- sb.append(sa.getSourceCard().getController());
- sb.append(" prevents all combat damage this turn.");
-
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- sb.append(abSub.getStackDescription());
- }
-
- return sb.toString();
- }
-
- /**
- *
- * fogCanPlayAI.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @param sa
- * a {@link forge.card.spellability.SpellAbility} object.
- * @return a boolean.
- */
- public static boolean fogCanPlayAI(final Player ai, final AbilityFactory af, final SpellAbility sa) {
- // AI should only activate this during Human's Declare Blockers phase
- if (Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) {
- return false;
- }
- if (!Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
- return false;
- }
-
- // Only cast when Stack is empty, so Human uses spells/abilities first
- if (Singletons.getModel().getGame().getStack().size() != 0) {
- return false;
- }
-
- // Don't cast it, if the effect is already in place
- if (Singletons.getModel().getGame().getPhaseHandler().isPreventCombatDamageThisTurn()) {
- return false;
- }
-
- final AbilitySub subAb = sa.getSubAbility();
- if (subAb != null) {
- if (!subAb.chkAIDrawback()) {
- return false;
- }
- }
-
- // Cast it if life is in danger
- return CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat());
- }
-
- /**
- *
- * fogPlayDrawbackAI.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @param sa
- * a {@link forge.card.spellability.SpellAbility} object.
- * @return a boolean.
- */
- public static boolean fogPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
- // AI should only activate this during Human's turn
- boolean chance;
- if (Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer().getOpponent())) {
- chance = Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_FIRST_STRIKE_DAMAGE);
- } else {
- chance = Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DAMAGE);
- }
-
- final AbilitySub subAb = sa.getSubAbility();
- if (subAb != null) {
- chance &= subAb.chkAIDrawback();
- }
-
- return chance;
- }
-
- /**
- *
- * fogDoTriggerAI.
- *
- *
- * @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 fogDoTriggerAI(final Player ai, final AbilityFactory af, final SpellAbility sa, final boolean mandatory) {
- // If there is a cost payment it's usually not mandatory
- if (!ComputerUtil.canPayCost(sa, ai) && !mandatory) {
- return false;
- }
-
- boolean chance;
- if (Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer().getOpponent())) {
- chance = Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_FIRST_STRIKE_DAMAGE);
- } else {
- chance = Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DAMAGE);
- }
-
- // check SubAbilities DoTrigger?
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- return chance && abSub.doTrigger(mandatory);
- }
-
- return chance;
- }
-
- /**
- *
- * fogResolve.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @param sa
- * a {@link forge.card.spellability.SpellAbility} object.
- */
- public static void fogResolve(final AbilityFactory af, final SpellAbility sa) {
-
- // Expand Fog keyword here depending on what we need out of it.
- Singletons.getModel().getGame().getPhaseHandler().setPreventCombatDamageThisTurn(true);
- }
-
- // **************************************************************
- // *********************** MUSTATTACK ***************************
- // **************************************************************
-
- // AB$ MustAttack | Cost$ R T | ValidTgts$ Opponent | TgtPrompt$ Select
- // target opponent | Defender$ Self | SpellDescription$ ...
-
- /**
- *
- * createAbilityMustAttack.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- *
- * @since 1.1.01
- */
- public static SpellAbility createAbilityMustAttack(final AbilityFactory af) {
- class AbilityMustAttack extends AbilityActivated {
- public AbilityMustAttack(final Card ca, final Cost co, final Target t) {
- super(ca, co, t);
- }
-
- @Override
- public AbilityActivated getCopy() {
- AbilityActivated res = new AbilityMustAttack(getSourceCard(),
- getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = 4559154732470225755L;
-
- @Override
- public String getStackDescription() {
- return AbilityFactoryCombat.mustAttackStackDescription(af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryCombat.mustAttackCanPlayAI(af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.mustAttackResolve(af, this);
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryCombat.mustAttackDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
- }
- }
- final SpellAbility abMustAttack = new AbilityMustAttack(af.getHostCard(), af.getAbCost(), af.getAbTgt());
-
- return abMustAttack;
- }
-
- /**
- *
- * createSpellMustAttack.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createSpellMustAttack(final AbilityFactory af) {
- final SpellAbility spMustAttack = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
- private static final long serialVersionUID = 4103945257601008403L;
-
- @Override
- public String getStackDescription() {
- return AbilityFactoryCombat.mustAttackStackDescription(af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryCombat.mustAttackCanPlayAI(af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.mustAttackResolve(af, this);
- }
-
- };
- return spMustAttack;
- }
-
- /**
- *
- * createDrawbackMustAttack.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createDrawbackMustAttack(final AbilityFactory af) {
- class DrawbackMustAttack extends AbilitySub {
- public DrawbackMustAttack(final Card ca, final Target t) {
- super(ca, t);
- }
-
- @Override
- public AbilitySub getCopy() {
- AbilitySub res = new DrawbackMustAttack(getSourceCard(),
- getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = 1294949210616598158L;
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.mustAttackResolve(af, this);
- }
-
- @Override
- public boolean chkAIDrawback() {
- return AbilityFactoryCombat.mustAttackPlayDrawbackAI(af, this);
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryCombat.mustAttackDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
- }
- }
- final SpellAbility dbMustAttack = new DrawbackMustAttack(af.getHostCard(), af.getAbTgt());
-
- return dbMustAttack;
- }
-
- private static String mustAttackStackDescription(final AbilityFactory af, final SpellAbility sa) {
- final HashMap params = af.getMapParams();
- final Card host = sa.getSourceCard();
- final StringBuilder sb = new StringBuilder();
-
- if (sa instanceof AbilitySub) {
- sb.append(" ");
- } else {
- sb.append(sa.getSourceCard()).append(" - ");
- }
-
- // end standard pre-
-
- ArrayList tgtPlayers;
-
- final Target tgt = sa.getTarget();
- if (tgt != null) {
- tgtPlayers = tgt.getTargetPlayers();
- } else {
- tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
- }
-
- String defender = null;
- if (params.get("Defender").equals("Self")) {
- defender = host.toString();
- } else {
- // TODO - if more needs arise in the future
- }
-
- for (final Player player : tgtPlayers) {
- sb.append("Creatures ").append(player).append(" controls attack ");
- sb.append(defender).append(" during his or her next turn.");
- }
-
- // begin standard post-
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- sb.append(abSub.getStackDescription());
- }
-
- return sb.toString();
- }
-
- private static boolean mustAttackCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
- // disabled for the AI for now. Only for Gideon Jura at this time.
- return false;
- }
-
- private static boolean mustAttackPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
- // AI should only activate this during Human's turn
- boolean chance;
-
- // TODO - implement AI
- chance = false;
-
- final AbilitySub subAb = sa.getSubAbility();
- if (subAb != null) {
- chance &= subAb.chkAIDrawback();
- }
-
- return chance;
- }
-
- private static boolean mustAttackDoTriggerAI(final Player ai, final AbilityFactory af, final SpellAbility sa, final boolean mandatory) {
- // If there is a cost payment it's usually not mandatory
- if (!ComputerUtil.canPayCost(sa, ai) && !mandatory) {
- return false;
- }
-
- boolean chance;
-
- // TODO - implement AI
- chance = false;
-
- // check SubAbilities DoTrigger?
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- return chance && abSub.doTrigger(mandatory);
- }
-
- return chance;
- }
-
- private static void mustAttackResolve(final AbilityFactory af, final SpellAbility sa) {
- final HashMap params = af.getMapParams();
-
- ArrayList tgtPlayers;
-
- final Target tgt = sa.getTarget();
- if ((tgt != null) && !params.containsKey("Defined")) {
- tgtPlayers = tgt.getTargetPlayers();
- } else {
- tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
- }
-
- for (final Player p : tgtPlayers) {
- if ((tgt == null) || p.canBeTargetedBy(sa)) {
- GameEntity entity;
- if (params.get("Defender").equals("Self")) {
- entity = sa.getSourceCard();
- } else {
- entity = p.getOpponent();
- }
- // System.out.println("Setting mustAttackEntity to: "+entity);
- p.setMustAttackEntity(entity);
- }
- }
-
- } // mustAttackResolve()
-
- // **************************************************************
- // ********************* RemoveFromCombat ***********************
- // **************************************************************
-
- /**
- *
- * createAbilityRemoveFromCombat.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- *
- * @since 1.1.6
- */
- public static SpellAbility createAbilityRemoveFromCombat(final AbilityFactory af) {
- class AbilityRemoveFromCombat extends AbilityActivated {
- public AbilityRemoveFromCombat(final Card ca, final Cost co, final Target t) {
- super(ca, co, t);
- }
-
- @Override
- public AbilityActivated getCopy() {
- AbilityActivated res = new AbilityRemoveFromCombat(getSourceCard(),
- getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = -2472319390656924874L;
-
- @Override
- public String getStackDescription() {
- return AbilityFactoryCombat.removeFromCombatStackDescription(af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryCombat.removeFromCombatCanPlayAI(af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.removeFromCombatResolve(af, this);
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryCombat.removeFromCombatDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
- }
- }
- final SpellAbility abRemCombat = new AbilityRemoveFromCombat(af.getHostCard(), af.getAbCost(), af.getAbTgt());
-
- return abRemCombat;
- }
-
- /**
- *
- * createSpellRemoveFeomCombat.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createSpellRemoveFromCombat(final AbilityFactory af) {
- final SpellAbility spRemCombat = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
- private static final long serialVersionUID = 4086879057558760897L;
-
- @Override
- public String getStackDescription() {
- return AbilityFactoryCombat.removeFromCombatStackDescription(af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryCombat.removeFromCombatCanPlayAI(af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.removeFromCombatResolve(af, this);
- }
-
- };
- return spRemCombat;
- }
-
- /**
- *
- * createDrawbackRemoveFromCombat.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createDrawbackRemoveFromCombat(final AbilityFactory af) {
- class DrawbackRemoveFromCombat extends AbilitySub {
- public DrawbackRemoveFromCombat(final Card ca, final Target t) {
- super(ca, t);
- }
-
- @Override
- public AbilitySub getCopy() {
- AbilitySub res = new DrawbackRemoveFromCombat(getSourceCard(),
- getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = 5080737903616292224L;
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.removeFromCombatResolve(af, this);
- }
-
- @Override
- public boolean chkAIDrawback() {
- return AbilityFactoryCombat.removeFromCombatPlayDrawbackAI(af, this);
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryCombat.removeFromCombatDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
- }
- }
- final SpellAbility dbRemCombat = new DrawbackRemoveFromCombat(af.getHostCard(), af.getAbTgt());
-
- return dbRemCombat;
- }
-
- private static String removeFromCombatStackDescription(final AbilityFactory af, final SpellAbility sa) {
- final HashMap params = af.getMapParams();
- final StringBuilder sb = new StringBuilder();
-
- if (sa instanceof AbilitySub) {
- sb.append(" ");
- } else {
- sb.append(sa.getSourceCard()).append(" - ");
- }
-
- // end standard pre-
-
- ArrayList tgtCards;
-
- final Target tgt = sa.getTarget();
- if (tgt != null) {
- tgtCards = tgt.getTargetCards();
- } else {
- tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
- }
-
- sb.append("Remove ");
-
- for (final Card c : tgtCards) {
- sb.append(c);
- }
-
- sb.append(" from combat.");
-
- // begin standard post-
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- sb.append(abSub.getStackDescription());
- }
-
- return sb.toString();
- }
-
- private static boolean removeFromCombatCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
- // disabled for the AI for now. Only for Gideon Jura at this time.
- return false;
- }
-
- private static boolean removeFromCombatPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
- // AI should only activate this during Human's turn
- boolean chance;
-
- // TODO - implement AI
- chance = false;
-
- final AbilitySub subAb = sa.getSubAbility();
- if (subAb != null) {
- chance &= subAb.chkAIDrawback();
- }
-
- return chance;
- }
-
- private static boolean removeFromCombatDoTriggerAI(final Player ai, final AbilityFactory af, final SpellAbility sa,
- final boolean mandatory) {
- // If there is a cost payment it's usually not mandatory
- if (!ComputerUtil.canPayCost(sa, ai) && !mandatory) {
- return false;
- }
-
- boolean chance;
-
- // TODO - implement AI
- chance = false;
-
- // check SubAbilities DoTrigger?
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- return chance && abSub.doTrigger(mandatory);
- }
-
- return chance;
- }
-
- private static void removeFromCombatResolve(final AbilityFactory af, final SpellAbility sa) {
- final HashMap params = af.getMapParams();
-
- ArrayList tgtCards;
-
- final Target tgt = sa.getTarget();
- if ((tgt != null) && !params.containsKey("Defined")) {
- tgtCards = tgt.getTargetCards();
- } else {
- tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
- }
-
- for (final Card c : tgtCards) {
- if ((tgt == null) || c.canBeTargetedBy(sa)) {
- Singletons.getModel().getGame().getCombat().removeFromCombat(c);
- }
- }
-
- } // mustAttackResolve()
-
- // **************************************************************
- // *********************** MustBlock ****************************
- // **************************************************************
-
- // AB$ MustBlock | Cost$ R T | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$
- // Select target creature defending player controls | DefinedAttacker$ Self
- // | SpellDescription$ ...
-
- /**
- *
- * createAbilityMustBlock.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- *
- * @since 1.1.6
- */
- public static SpellAbility createAbilityMustBlock(final AbilityFactory af) {
- class AbilityMustBlock extends AbilityActivated {
- public AbilityMustBlock(final Card ca, final Cost co, final Target t) {
- super(ca, co, t);
- }
-
- @Override
- public AbilityActivated getCopy() {
- AbilityActivated res = new AbilityMustBlock(getSourceCard(),
- getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = 4237190949098526123L;
-
- @Override
- public String getStackDescription() {
- return AbilityFactoryCombat.mustBlockStackDescription(af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryCombat.mustBlockCanPlayAI(af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.mustBlockResolve(af, this);
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryCombat.mustBlockDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
- }
- }
- final SpellAbility abMustBlock = new AbilityMustBlock(af.getHostCard(), af.getAbCost(), af.getAbTgt());
-
- return abMustBlock;
- }
-
- /**
- *
- * createSpellMustBlock.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- *
- * @since 1.1.6
- */
- public static SpellAbility createSpellMustBlock(final AbilityFactory af) {
- final SpellAbility spMustBlock = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
- private static final long serialVersionUID = 6758785067306305860L;
-
- @Override
- public String getStackDescription() {
- return AbilityFactoryCombat.mustBlockStackDescription(af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryCombat.mustBlockCanPlayAI(af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.mustBlockResolve(af, this);
- }
-
- };
- return spMustBlock;
- }
-
- /**
- *
- * createDrawbackMustBlock.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- *
- * @since 1.1.6
- */
- public static SpellAbility createDrawbackMustBlock(final AbilityFactory af) {
- class DrawbackMustBlock extends AbilitySub {
- public DrawbackMustBlock(final Card ca, final Target t) {
- super(ca, t);
- }
-
- @Override
- public AbilitySub getCopy() {
- AbilitySub res = new DrawbackMustBlock(getSourceCard(),
- getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = -815813765448972775L;
-
- @Override
- public void resolve() {
- AbilityFactoryCombat.mustBlockResolve(af, this);
- }
-
- @Override
- public boolean chkAIDrawback() {
- return AbilityFactoryCombat.mustBlockPlayDrawbackAI(af, this);
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryCombat.mustBlockDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
- }
- }
- final SpellAbility dbMustBlock = new DrawbackMustBlock(af.getHostCard(), af.getAbTgt());
-
- return dbMustBlock;
- }
-
- private static String mustBlockStackDescription(final AbilityFactory af, final SpellAbility sa) {
- final HashMap params = af.getMapParams();
- final Card host = sa.getSourceCard();
- final StringBuilder sb = new StringBuilder();
-
- if (sa instanceof AbilitySub) {
- sb.append(" ");
- } else {
- sb.append(sa.getSourceCard()).append(" - ");
- }
-
- // end standard pre-
-
- ArrayList tgtCards;
-
- final Target tgt = sa.getTarget();
- if (tgt != null) {
- tgtCards = tgt.getTargetCards();
- } else {
- tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
- }
-
- String attacker = null;
- if (params.containsKey("DefinedAttacker")) {
- final ArrayList cards = AbilityFactory.getDefinedCards(sa.getSourceCard(),
- params.get("DefinedAttacker"), sa);
- attacker = cards.get(0).toString();
- } else {
- attacker = host.toString();
- }
-
- for (final Card c : tgtCards) {
- sb.append(c).append(" must block ").append(attacker).append(" if able.");
- }
-
- // begin standard post-
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- sb.append(abSub.getStackDescription());
- }
-
- return sb.toString();
- }
-
- private static boolean mustBlockCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
- // disabled for the AI until he/she can make decisions about who to make
- // block
- return false;
- }
-
- private static boolean mustBlockPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
- // AI should only activate this during Human's turn
- boolean chance;
-
- // TODO - implement AI
- chance = false;
-
- final AbilitySub subAb = sa.getSubAbility();
- if (subAb != null) {
- chance &= subAb.chkAIDrawback();
- }
-
- return chance;
- }
-
- private static boolean mustBlockDoTriggerAI(final Player ai, final AbilityFactory af, final SpellAbility sa, final boolean mandatory) {
- final HashMap params = af.getMapParams();
- final Card source = sa.getSourceCard();
- final Target abTgt = sa.getTarget();
-
- // If there is a cost payment it's usually not mandatory
- if (!ComputerUtil.canPayCost(sa, ai) && !mandatory) {
- return false;
- }
-
- // only use on creatures that can attack
- if (!Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)) {
- return false;
- }
-
- Card attacker = null;
- if (params.containsKey("DefinedAttacker")) {
- final ArrayList cards = AbilityFactory.getDefinedCards(sa.getSourceCard(),
- params.get("DefinedAttacker"), sa);
- if (cards.isEmpty()) {
- return false;
- }
-
- attacker = cards.get(0);
- }
-
- if (attacker == null) {
- attacker = source;
- }
-
- final Card definedAttacker = attacker;
-
- boolean chance = false;
-
- if (abTgt != null) {
- List list = CardLists.filter(ai.getOpponent().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
- list = CardLists.getTargetableCards(list, sa);
- list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
- list = CardLists.filter(list, new Predicate() {
- @Override
- public boolean apply(final Card c) {
- boolean tapped = c.isTapped();
- c.setTapped(false);
- if (!CombatUtil.canBlock(definedAttacker, c)) {
- return false;
- }
- if (CombatUtil.canDestroyAttacker(definedAttacker, c, null, false)) {
- return false;
- }
- if (!CombatUtil.canDestroyBlocker(c, definedAttacker, null, false)) {
- return false;
- }
- c.setTapped(tapped);
- return true;
- }
- });
- if (list.isEmpty()) {
- return false;
- }
- final Card blocker = CardFactoryUtil.getBestCreatureAI(list);
- if (blocker == null) {
- return false;
- }
- abTgt.addTarget(blocker);
- chance = true;
- } else {
- return false;
- }
-
- // check SubAbilities DoTrigger?
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- return chance && abSub.doTrigger(mandatory);
- }
-
- return chance;
- }
-
- private static void mustBlockResolve(final AbilityFactory af, final SpellAbility sa) {
- final HashMap params = af.getMapParams();
- final Card host = sa.getSourceCard();
-
- ArrayList tgtCards;
-
- final Target tgt = sa.getTarget();
- if (tgt != null) {
- tgtCards = tgt.getTargetCards();
- } else {
- tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
- }
-
- ArrayList cards;
- if (params.containsKey("DefinedAttacker")) {
- cards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("DefinedAttacker"), sa);
- } else {
- cards = new ArrayList();
- cards.add(host);
- }
-
- for (final Card c : tgtCards) {
- if ((tgt == null) || c.canBeTargetedBy(sa)) {
- final Card attacker = cards.get(0);
- c.addMustBlockCard(attacker);
- System.out.println(c + " is adding " + attacker + " to mustBlockCards: " + c.getMustBlockCards());
- }
- }
-
- } // mustBlockResolve()
-
-} // end class AbilityFactory_Combat
diff --git a/src/main/java/forge/card/abilityfactory/SpellAiLogic.java b/src/main/java/forge/card/abilityfactory/SpellAiLogic.java
index 7ffcc0adb7a..6567ad39354 100644
--- a/src/main/java/forge/card/abilityfactory/SpellAiLogic.java
+++ b/src/main/java/forge/card/abilityfactory/SpellAiLogic.java
@@ -18,10 +18,12 @@ public abstract class SpellAiLogic {
return doTriggerAINoCost(aiPlayer, params, sa, mandatory);
}
+ @SuppressWarnings("unused") // 'unused' parameters are used by overloads
public boolean doTriggerAINoCost(final Player aiPlayer, final Map params, final SpellAbility sa, final boolean mandatory) {
return canPlayAI(aiPlayer, params, sa);
}
// consider safe
+ @SuppressWarnings("unused") // 'unused' parameters are used by overloads
public boolean chkAIDrawback(final Map params, final SpellAbility sa, final Player aiPlayer) { return true; }
}
\ No newline at end of file
diff --git a/src/main/java/forge/card/abilityfactory/ai/FogAi.java b/src/main/java/forge/card/abilityfactory/ai/FogAi.java
new file mode 100644
index 00000000000..f975fb9e8ab
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/ai/FogAi.java
@@ -0,0 +1,110 @@
+package forge.card.abilityfactory.ai;
+
+import java.util.Map;
+
+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.phase.PhaseType;
+import forge.game.player.Player;
+
+public class FogAi 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 params, SpellAbility sa) {
+ // AI should only activate this during Human's Declare Blockers phase
+ if (Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) {
+ return false;
+ }
+ if (!Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
+ return false;
+ }
+
+ // Only cast when Stack is empty, so Human uses spells/abilities first
+ if (!Singletons.getModel().getGame().getStack().isEmpty()) {
+ return false;
+ }
+
+ // Don't cast it, if the effect is already in place
+ if (Singletons.getModel().getGame().getPhaseHandler().isPreventCombatDamageThisTurn()) {
+ return false;
+ }
+
+ final AbilitySub subAb = sa.getSubAbility();
+ if (subAb != null) {
+ if (!subAb.chkAIDrawback()) {
+ return false;
+ }
+ }
+
+ // Cast it if life is in danger
+ return CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat());
+ }
+
+ /**
+ *
+ * fogPlayDrawbackAI.
+ *
+ *
+ * @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 params, SpellAbility sa, Player ai) {
+ // AI should only activate this during Human's turn
+ boolean chance;
+
+ // should really check if other player is attacking this player
+ if (ai.isHostileTo(Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn())) {
+ chance = Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_FIRST_STRIKE_DAMAGE);
+ } else {
+ chance = Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DAMAGE);
+ }
+
+ final AbilitySub subAb = sa.getSubAbility();
+ if (subAb != null) {
+ chance &= subAb.chkAIDrawback();
+ }
+
+ return chance;
+ }
+
+ /**
+ *
+ * fogDoTriggerAI.
+ *
+ *
+ * @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 aiPlayer, java.util.Map params, SpellAbility sa, boolean mandatory) {
+ boolean chance;
+ if (Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer().getOpponent())) {
+ chance = Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_FIRST_STRIKE_DAMAGE);
+ } else {
+ chance = Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DAMAGE);
+ }
+
+ // check SubAbilities DoTrigger?
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ return chance && abSub.doTrigger(mandatory);
+ }
+
+ return chance;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/forge/card/abilityfactory/ai/MustAttackAi.java b/src/main/java/forge/card/abilityfactory/ai/MustAttackAi.java
new file mode 100644
index 00000000000..e00f77f6c0d
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/ai/MustAttackAi.java
@@ -0,0 +1,44 @@
+package forge.card.abilityfactory.ai;
+
+import java.util.Map;
+
+import forge.card.abilityfactory.SpellAiLogic;
+import forge.card.spellability.AbilitySub;
+import forge.card.spellability.SpellAbility;
+import forge.game.player.Player;
+
+public class MustAttackAi extends SpellAiLogic {
+
+ @Override
+ public boolean canPlayAI(Player aiPlayer, java.util.Map params, SpellAbility sa) {
+ // disabled for the AI for now. Only for Gideon Jura at this time.
+ return false;
+ }
+
+ @Override
+ public boolean chkAIDrawback(java.util.Map params, SpellAbility sa, Player aiPlayer) {
+ // AI should only activate this during Human's turn
+ // TODO - implement AI
+ return false;
+ }
+
+ /* (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 aiPlayer, Map params, SpellAbility sa, boolean mandatory) {
+
+ boolean chance;
+
+ // TODO - implement AI
+ chance = false;
+
+ // check SubAbilities DoTrigger?
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ return chance && abSub.doTrigger(mandatory);
+ }
+
+ return chance;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/forge/card/abilityfactory/ai/MustBlockAi.java b/src/main/java/forge/card/abilityfactory/ai/MustBlockAi.java
new file mode 100644
index 00000000000..1528ffd5add
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/ai/MustBlockAi.java
@@ -0,0 +1,109 @@
+package forge.card.abilityfactory.ai;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.base.Predicate;
+
+import forge.Card;
+import forge.CardLists;
+import forge.CardPredicates;
+import forge.Singletons;
+import forge.card.abilityfactory.AbilityFactory;
+import forge.card.abilityfactory.SpellAiLogic;
+import forge.card.cardfactory.CardFactoryUtil;
+import forge.card.spellability.AbilitySub;
+import forge.card.spellability.SpellAbility;
+import forge.card.spellability.Target;
+import forge.game.phase.CombatUtil;
+import forge.game.phase.PhaseType;
+import forge.game.player.Player;
+import forge.game.zone.ZoneType;
+
+public class MustBlockAi extends SpellAiLogic {
+
+ @Override
+ public boolean canPlayAI(Player aiPlayer, java.util.Map params, SpellAbility sa) {
+ // disabled for the AI until he/she can make decisions about who to make
+ // block
+ return false;
+ }
+
+ @Override
+ public boolean chkAIDrawback(java.util.Map params, SpellAbility sa, Player aiPlayer) {
+ return false;
+ }
+
+ @Override
+ public boolean doTriggerAINoCost(Player ai, java.util.Map params, SpellAbility sa, boolean mandatory) {
+ final Card source = sa.getSourceCard();
+ final Target abTgt = sa.getTarget();
+
+ // only use on creatures that can attack
+ if (!Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)) {
+ return false;
+ }
+
+ Card attacker = null;
+ if (params.containsKey("DefinedAttacker")) {
+ final ArrayList cards = AbilityFactory.getDefinedCards(sa.getSourceCard(),
+ params.get("DefinedAttacker"), sa);
+ if (cards.isEmpty()) {
+ return false;
+ }
+
+ attacker = cards.get(0);
+ }
+
+ if (attacker == null) {
+ attacker = source;
+ }
+
+ final Card definedAttacker = attacker;
+
+ boolean chance = false;
+
+ if (abTgt != null) {
+ List list = CardLists.filter(ai.getOpponent().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
+ list = CardLists.getTargetableCards(list, sa);
+ list = CardLists.getValidCards(list, abTgt.getValidTgts(), source.getController(), source);
+ list = CardLists.filter(list, new Predicate() {
+ @Override
+ public boolean apply(final Card c) {
+ boolean tapped = c.isTapped();
+ c.setTapped(false);
+ if (!CombatUtil.canBlock(definedAttacker, c)) {
+ return false;
+ }
+ if (CombatUtil.canDestroyAttacker(definedAttacker, c, null, false)) {
+ return false;
+ }
+ if (!CombatUtil.canDestroyBlocker(c, definedAttacker, null, false)) {
+ return false;
+ }
+ c.setTapped(tapped);
+ return true;
+ }
+ });
+ if (list.isEmpty()) {
+ return false;
+ }
+ final Card blocker = CardFactoryUtil.getBestCreatureAI(list);
+ if (blocker == null) {
+ return false;
+ }
+ abTgt.addTarget(blocker);
+ chance = true;
+ } else {
+ return false;
+ }
+
+ // check SubAbilities DoTrigger?
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ return chance && abSub.doTrigger(mandatory);
+ }
+
+ return chance;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/forge/card/abilityfactory/ai/RegenerateAi.java b/src/main/java/forge/card/abilityfactory/ai/RegenerateAi.java
index 799591dcc8c..ecb9ecfda84 100644
--- a/src/main/java/forge/card/abilityfactory/ai/RegenerateAi.java
+++ b/src/main/java/forge/card/abilityfactory/ai/RegenerateAi.java
@@ -18,7 +18,6 @@
package forge.card.abilityfactory.ai;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import forge.Card;
@@ -31,9 +30,7 @@ import forge.card.abilityfactory.SpellAiLogic;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost;
import forge.card.cost.CostUtil;
-import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilitySub;
-import forge.card.spellability.Spell;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.phase.CombatUtil;
diff --git a/src/main/java/forge/card/abilityfactory/ai/RegenerateAllAi.java b/src/main/java/forge/card/abilityfactory/ai/RegenerateAllAi.java
index 93ff3d54539..5d5cc384790 100644
--- a/src/main/java/forge/card/abilityfactory/ai/RegenerateAllAi.java
+++ b/src/main/java/forge/card/abilityfactory/ai/RegenerateAllAi.java
@@ -15,7 +15,6 @@ import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType;
-import forge.game.player.ComputerUtil;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -107,14 +106,10 @@ public class RegenerateAllAi extends SpellAiLogic {
* a boolean.
* @return a boolean.
*/
- private static boolean regenerateAllDoTriggerAI(final Player ai, final AbilityFactory af, final SpellAbility sa,
- final boolean mandatory) {
+ @Override
+ public boolean doTriggerAINoCost(Player aiPlayer, java.util.Map params, SpellAbility sa, boolean mandatory) {
boolean chance = true;
- if (!ComputerUtil.canPayCost(sa, ai)) {
- return false;
- }
-
final AbilitySub subAb = sa.getSubAbility();
if (subAb != null) {
chance &= subAb.doTrigger(mandatory);
diff --git a/src/main/java/forge/card/abilityfactory/ai/RemoveFromCombatAi.java b/src/main/java/forge/card/abilityfactory/ai/RemoveFromCombatAi.java
new file mode 100644
index 00000000000..b4f3efb61f5
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/ai/RemoveFromCombatAi.java
@@ -0,0 +1,44 @@
+package forge.card.abilityfactory.ai;
+
+import java.util.Map;
+
+import forge.card.abilityfactory.SpellAiLogic;
+import forge.card.spellability.AbilitySub;
+import forge.card.spellability.SpellAbility;
+import forge.game.player.Player;
+
+public class RemoveFromCombatAi extends SpellAiLogic {
+
+ @Override
+ public boolean canPlayAI(Player aiPlayer, java.util.Map params, SpellAbility sa) {
+ // disabled for the AI for now. Only for Gideon Jura at this time.
+ return false;
+ }
+
+ @Override
+ public boolean chkAIDrawback(java.util.Map params, SpellAbility sa, Player aiPlayer) {
+ // AI should only activate this during Human's turn
+
+ // TODO - implement AI
+ return false;
+ }
+
+ /* (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 aiPlayer, Map params, SpellAbility sa, boolean mandatory) {
+ boolean chance;
+
+ // TODO - implement AI
+ chance = false;
+
+ // check SubAbilities DoTrigger?
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ return chance && abSub.doTrigger(mandatory);
+ }
+
+ return chance;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/forge/card/abilityfactory/effects/FogEffect.java b/src/main/java/forge/card/abilityfactory/effects/FogEffect.java
new file mode 100644
index 00000000000..0e8aa79c5b2
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/effects/FogEffect.java
@@ -0,0 +1,38 @@
+package forge.card.abilityfactory.effects;
+
+import forge.Singletons;
+import forge.card.abilityfactory.SpellEffect;
+import forge.card.spellability.AbilitySub;
+import forge.card.spellability.SpellAbility;
+
+public class FogEffect extends SpellEffect {
+
+
+ @Override
+ public String getStackDescription(java.util.Map params, SpellAbility sa) {
+ final StringBuilder sb = new StringBuilder();
+
+ if (!(sa instanceof AbilitySub)) {
+ sb.append(sa.getSourceCard().getName()).append(" - ");
+ } else {
+ sb.append(" ");
+ }
+
+ sb.append(sa.getSourceCard().getController());
+ sb.append(" prevents all combat damage this turn.");
+
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ sb.append(abSub.getStackDescription());
+ }
+
+ return sb.toString();
+ }
+
+
+ @Override
+ public void resolve(java.util.Map params, SpellAbility sa) {
+ // Expand Fog keyword here depending on what we need out of it.
+ Singletons.getModel().getGame().getPhaseHandler().setPreventCombatDamageThisTurn(true);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/forge/card/abilityfactory/effects/MustAttackEffect.java b/src/main/java/forge/card/abilityfactory/effects/MustAttackEffect.java
new file mode 100644
index 00000000000..f6c2d4964ed
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/effects/MustAttackEffect.java
@@ -0,0 +1,93 @@
+package forge.card.abilityfactory.effects;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import forge.Card;
+import forge.GameEntity;
+import forge.card.abilityfactory.AbilityFactory;
+import forge.card.abilityfactory.SpellEffect;
+import forge.card.spellability.AbilitySub;
+import forge.card.spellability.SpellAbility;
+import forge.card.spellability.Target;
+import forge.game.player.Player;
+
+public class MustAttackEffect extends SpellEffect {
+
+ /* (non-Javadoc)
+ * @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility)
+ */
+ @Override
+ public String getStackDescription(Map params, SpellAbility sa) {
+ final Card host = sa.getSourceCard();
+ final StringBuilder sb = new StringBuilder();
+
+ if (sa instanceof AbilitySub) {
+ sb.append(" ");
+ } else {
+ sb.append(sa.getSourceCard()).append(" - ");
+ }
+
+ // end standard pre-
+
+ ArrayList tgtPlayers;
+
+ final Target tgt = sa.getTarget();
+ if (tgt != null) {
+ tgtPlayers = tgt.getTargetPlayers();
+ } else {
+ tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
+ }
+
+ String defender = null;
+ if (params.get("Defender").equals("Self")) {
+ defender = host.toString();
+ } else {
+ // TODO - if more needs arise in the future
+ }
+
+ for (final Player player : tgtPlayers) {
+ sb.append("Creatures ").append(player).append(" controls attack ");
+ sb.append(defender).append(" during his or her next turn.");
+ }
+
+ // begin standard post-
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ sb.append(abSub.getStackDescription());
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ public void resolve(java.util.Map params, SpellAbility sa) {
+ ArrayList tgtPlayers;
+
+ final Target tgt = sa.getTarget();
+ if ((tgt != null) && !params.containsKey("Defined")) {
+ tgtPlayers = tgt.getTargetPlayers();
+ } else {
+ tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
+ }
+
+ for (final Player p : tgtPlayers) {
+ if ((tgt == null) || p.canBeTargetedBy(sa)) {
+ GameEntity entity;
+ if (params.get("Defender").equals("Self")) {
+ entity = sa.getSourceCard();
+ } else {
+ entity = p.getOpponent();
+ }
+ // System.out.println("Setting mustAttackEntity to: "+entity);
+ p.setMustAttackEntity(entity);
+ }
+ }
+
+ } // mustAttackResolve()
+
+ // **************************************************************
+ // ********************* RemoveFromCombat ***********************
+ // **************************************************************
+
+}
\ No newline at end of file
diff --git a/src/main/java/forge/card/abilityfactory/effects/MustBlockEffect.java b/src/main/java/forge/card/abilityfactory/effects/MustBlockEffect.java
new file mode 100644
index 00000000000..2db0cc75123
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/effects/MustBlockEffect.java
@@ -0,0 +1,89 @@
+package forge.card.abilityfactory.effects;
+
+import java.util.ArrayList;
+
+import forge.Card;
+import forge.card.abilityfactory.AbilityFactory;
+import forge.card.abilityfactory.SpellEffect;
+import forge.card.spellability.AbilitySub;
+import forge.card.spellability.SpellAbility;
+import forge.card.spellability.Target;
+
+public class MustBlockEffect extends SpellEffect {
+
+ @Override
+ public void resolve(java.util.Map params, SpellAbility sa) {
+ final Card host = sa.getSourceCard();
+
+ ArrayList tgtCards;
+
+ final Target tgt = sa.getTarget();
+ if (tgt != null) {
+ tgtCards = tgt.getTargetCards();
+ } else {
+ tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
+ }
+
+ ArrayList cards;
+ if (params.containsKey("DefinedAttacker")) {
+ cards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("DefinedAttacker"), sa);
+ } else {
+ cards = new ArrayList();
+ cards.add(host);
+ }
+
+ for (final Card c : tgtCards) {
+ if ((tgt == null) || c.canBeTargetedBy(sa)) {
+ final Card attacker = cards.get(0);
+ c.addMustBlockCard(attacker);
+ System.out.println(c + " is adding " + attacker + " to mustBlockCards: " + c.getMustBlockCards());
+ }
+ }
+
+ } // mustBlockResolve()
+
+ @Override
+ public String getStackDescription(java.util.Map params, SpellAbility sa) {
+ final Card host = sa.getSourceCard();
+ final StringBuilder sb = new StringBuilder();
+
+ if (sa instanceof AbilitySub) {
+ sb.append(" ");
+ } else {
+ sb.append(sa.getSourceCard()).append(" - ");
+ }
+
+ // end standard pre-
+
+ ArrayList tgtCards;
+
+ final Target tgt = sa.getTarget();
+ if (tgt != null) {
+ tgtCards = tgt.getTargetCards();
+ } else {
+ tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
+ }
+
+ String attacker = null;
+ if (params.containsKey("DefinedAttacker")) {
+ final ArrayList cards = AbilityFactory.getDefinedCards(sa.getSourceCard(),
+ params.get("DefinedAttacker"), sa);
+ attacker = cards.get(0).toString();
+ } else {
+ attacker = host.toString();
+ }
+
+ for (final Card c : tgtCards) {
+ sb.append(c).append(" must block ").append(attacker).append(" if able.");
+ }
+
+ // begin standard post-
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ sb.append(abSub.getStackDescription());
+ }
+
+ return sb.toString();
+ }
+
+} // end class AbilityFactory_Combat
\ No newline at end of file
diff --git a/src/main/java/forge/card/abilityfactory/effects/RegenerateAllEffect.java b/src/main/java/forge/card/abilityfactory/effects/RegenerateAllEffect.java
index 7137b192e4c..e5bea6e9e22 100644
--- a/src/main/java/forge/card/abilityfactory/effects/RegenerateAllEffect.java
+++ b/src/main/java/forge/card/abilityfactory/effects/RegenerateAllEffect.java
@@ -6,7 +6,6 @@ import forge.Card;
import forge.CardLists;
import forge.Command;
import forge.Singletons;
-import forge.card.abilityfactory.AbilityFactory;
import forge.card.abilityfactory.SpellEffect;
import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility;
diff --git a/src/main/java/forge/card/abilityfactory/effects/RemoveFromCombatEffect.java b/src/main/java/forge/card/abilityfactory/effects/RemoveFromCombatEffect.java
new file mode 100644
index 00000000000..0eb89b8f46a
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/effects/RemoveFromCombatEffect.java
@@ -0,0 +1,72 @@
+package forge.card.abilityfactory.effects;
+
+import java.util.ArrayList;
+
+import forge.Card;
+import forge.Singletons;
+import forge.card.abilityfactory.AbilityFactory;
+import forge.card.abilityfactory.SpellEffect;
+import forge.card.spellability.AbilitySub;
+import forge.card.spellability.SpellAbility;
+import forge.card.spellability.Target;
+
+public class RemoveFromCombatEffect extends SpellEffect {
+
+ @Override
+ public String getStackDescription(java.util.Map params, SpellAbility sa) {
+ final StringBuilder sb = new StringBuilder();
+
+ if (sa instanceof AbilitySub) {
+ sb.append(" ");
+ } else {
+ sb.append(sa.getSourceCard()).append(" - ");
+ }
+
+ // end standard pre-
+
+ ArrayList tgtCards;
+
+ final Target tgt = sa.getTarget();
+ if (tgt != null) {
+ tgtCards = tgt.getTargetCards();
+ } else {
+ tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
+ }
+
+ sb.append("Remove ");
+
+ for (final Card c : tgtCards) {
+ sb.append(c);
+ }
+
+ sb.append(" from combat.");
+
+ // begin standard post-
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ sb.append(abSub.getStackDescription());
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ public void resolve(java.util.Map params, SpellAbility sa) {
+
+ ArrayList tgtCards;
+
+ final Target tgt = sa.getTarget();
+ if ((tgt != null) && !params.containsKey("Defined")) {
+ tgtCards = tgt.getTargetCards();
+ } else {
+ tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
+ }
+
+ for (final Card c : tgtCards) {
+ if ((tgt == null) || c.canBeTargetedBy(sa)) {
+ Singletons.getModel().getGame().getCombat().removeFromCombat(c);
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/forge/game/phase/CombatUtil.java b/src/main/java/forge/game/phase/CombatUtil.java
index 41eaa134cdd..715e1693076 100644
--- a/src/main/java/forge/game/phase/CombatUtil.java
+++ b/src/main/java/forge/game/phase/CombatUtil.java
@@ -1042,7 +1042,7 @@ public class CombatUtil {
* a {@link forge.game.phase.Combat} object.
* @return a int.
*/
- public static int poisonIfUnblocked(final Card attacker, final Player attacked, final Combat combat) {
+ public static int poisonIfUnblocked(final Card attacker, final Player attacked) {
int damage = attacker.getNetCombatDamage();
int poison = 0;
damage += CombatUtil.predictPowerBonusOfAttacker(attacker, null, null);
@@ -1093,7 +1093,7 @@ public class CombatUtil {
public static int sumPoisonIfUnblocked(final List attackers, final Player attacked) {
int sum = 0;
for (final Card attacker : attackers) {
- sum += CombatUtil.poisonIfUnblocked(attacker, attacked, null);
+ sum += CombatUtil.poisonIfUnblocked(attacker, attacked);
}
return sum;
}
diff --git a/src/main/java/forge/game/player/ComputerUtilAttack.java b/src/main/java/forge/game/player/ComputerUtilAttack.java
index 98595e1a7a4..4a46a093ca3 100644
--- a/src/main/java/forge/game/player/ComputerUtilAttack.java
+++ b/src/main/java/forge/game/player/ComputerUtilAttack.java
@@ -138,7 +138,7 @@ public class ComputerUtilAttack {
if (CombatUtil.damageIfUnblocked(attacker, opp, combat) > 0) {
return true;
}
- if (CombatUtil.poisonIfUnblocked(attacker, opp, combat) > 0) {
+ if (CombatUtil.poisonIfUnblocked(attacker, opp) > 0) {
return true;
}
if (this.attackers.size() == 1 && attacker.hasKeyword("Exalted")) {
@@ -341,7 +341,7 @@ public class ComputerUtilAttack {
continue;
}
totalAttack += CombatUtil.damageIfUnblocked(attacker, ai, null);
- totalPoison += CombatUtil.poisonIfUnblocked(attacker, ai, null);
+ totalPoison += CombatUtil.poisonIfUnblocked(attacker, ai);
}
if (ai.getLife() <= totalAttack
diff --git a/src/main/java/forge/game/player/Player.java b/src/main/java/forge/game/player/Player.java
index f8b953346e2..06e6739f7ba 100644
--- a/src/main/java/forge/game/player/Player.java
+++ b/src/main/java/forge/game/player/Player.java
@@ -2887,5 +2887,17 @@ public abstract class Player extends GameEntity implements Comparable {
}
return false;
}
+
+ /**
+ * TODO: Write javadoc for this method.
+ * @param playerTurn
+ * @return
+ */
+ public boolean isHostileTo(Player other) {
+ if ( other.equals(getOpponent()) )
+ return true;
+
+ return other.getType() != this.getType();
+ }
}