AF: Combat refactored (17800 get!)

This commit is contained in:
Maxmtg
2012-10-31 07:41:23 +00:00
parent 5b16ada639
commit a08d455312
18 changed files with 635 additions and 1188 deletions

9
.gitattributes vendored
View File

@@ -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

View File

@@ -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")) {

View File

@@ -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<String, String> 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<String, String> params, final SpellAbility sa, final Player aiPlayer) { return true; }
}

View File

@@ -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<String, String> 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());
}
/**
* <p>
* fogPlayDrawbackAI.
* </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 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;
}
/**
* <p>
* fogDoTriggerAI.
* </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 aiPlayer, java.util.Map<String,String> 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;
}
}

View File

@@ -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<String,String> 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<String,String> 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<String, String> 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;
}
}

View File

@@ -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<String,String> 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<String,String> params, SpellAbility sa, Player aiPlayer) {
return false;
}
@Override
public boolean doTriggerAINoCost(Player ai, java.util.Map<String,String> 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<Card> 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<Card> 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<Card>() {
@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;
}
}

View File

@@ -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;

View File

@@ -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<String,String> 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);

View File

@@ -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<String,String> 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<String,String> 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<String, String> 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;
}
}

View File

@@ -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<String,String> 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<String,String> params, SpellAbility sa) {
// Expand Fog keyword here depending on what we need out of it.
Singletons.getModel().getGame().getPhaseHandler().setPreventCombatDamageThisTurn(true);
}
}

View File

@@ -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<String, String> 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<Player> 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<String,String> params, SpellAbility sa) {
ArrayList<Player> 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 ***********************
// **************************************************************
}

View File

@@ -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<String,String> params, SpellAbility sa) {
final Card host = sa.getSourceCard();
ArrayList<Card> tgtCards;
final Target tgt = sa.getTarget();
if (tgt != null) {
tgtCards = tgt.getTargetCards();
} else {
tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
}
ArrayList<Card> cards;
if (params.containsKey("DefinedAttacker")) {
cards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("DefinedAttacker"), sa);
} else {
cards = new ArrayList<Card>();
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<String,String> 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<Card> 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<Card> 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

View File

@@ -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;

View File

@@ -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<String,String> params, SpellAbility sa) {
final StringBuilder sb = new StringBuilder();
if (sa instanceof AbilitySub) {
sb.append(" ");
} else {
sb.append(sa.getSourceCard()).append(" - ");
}
// end standard pre-
ArrayList<Card> 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<String,String> params, SpellAbility sa) {
ArrayList<Card> 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);
}
}
}
}

View File

@@ -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<Card> 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;
}

View File

@@ -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

View File

@@ -2887,5 +2887,17 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
}
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();
}
}