mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
removed some calls to IsComputer in favour of comparision with player passed as parameter
checkConditions inlined ComputerUtilCombat recieve ai player as parameter
This commit is contained in:
@@ -345,19 +345,6 @@ public class AbilityFactory {
|
||||
condition.setConditions(mapParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* checkConditional.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean checkConditional(final SpellAbility sa) {
|
||||
return sa.getConditions().checkConditions(sa);
|
||||
}
|
||||
|
||||
// Easy creation of SubAbilities
|
||||
/**
|
||||
* <p>
|
||||
@@ -1579,13 +1566,7 @@ public class AbilityFactory {
|
||||
public static void passUnlessCost(final SpellAbility sa, final boolean usedStack, final GameState game) {
|
||||
final Card source = sa.getSourceCard();
|
||||
final ApiType api = sa.getApi();
|
||||
if (api == null) {
|
||||
sa.resolve();
|
||||
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
|
||||
return;
|
||||
}
|
||||
// Nothing to do
|
||||
if (sa.getParam("UnlessCost") == null) {
|
||||
if (api == null || sa.getParam("UnlessCost") == null) {
|
||||
sa.resolve();
|
||||
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
|
||||
return;
|
||||
@@ -1730,7 +1711,7 @@ public class AbilityFactory {
|
||||
|
||||
final GameState game = Singletons.getModel().getGame();
|
||||
// check conditions
|
||||
if (AbilityFactory.checkConditional(sa)) {
|
||||
if (sa.getConditions().areMet(sa)) {
|
||||
if (sa.isWrapper()) {
|
||||
sa.resolve();
|
||||
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
|
||||
@@ -1757,12 +1738,12 @@ public class AbilityFactory {
|
||||
// every resolving spellAbility will end here
|
||||
if (usedStack) {
|
||||
SpellAbility root = sa.getRootAbility();
|
||||
Singletons.getModel().getGame().getStack().finishResolving(root, false);
|
||||
game.getStack().finishResolving(root, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// check conditions
|
||||
if (AbilityFactory.checkConditional(abSub)) {
|
||||
if (abSub.getConditions().areMet(abSub)) {
|
||||
AbilityFactory.passUnlessCost(abSub, usedStack, game);
|
||||
} else {
|
||||
AbilityFactory.resolveSubAbilities(abSub, usedStack, game);
|
||||
|
||||
@@ -816,7 +816,7 @@ public class AttachAi extends SpellAiLogic {
|
||||
// at some point can support attaching a different card
|
||||
|
||||
// Don't equip if already equipping
|
||||
if (attachSource.getEquippingCard() != null && attachSource.getEquippingCard().getController().isComputer()) {
|
||||
if (attachSource.getEquippingCard() != null && attachSource.getEquippingCard().getController() == aiPlayer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -222,10 +222,10 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
}
|
||||
|
||||
// don't play if the conditions aren't met, unless it would trigger a beneficial sub-condition
|
||||
if (!AbilityFactory.checkConditional(sa)) {
|
||||
if (!sa.getConditions().areMet(sa)) {
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null && !sa.isWrapper() && "True".equals(source.getSVar("AIPlayForSub"))) {
|
||||
if (!AbilityFactory.checkConditional(abSub)) {
|
||||
if (!abSub.getConditions().areMet(abSub)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -269,7 +269,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
for (final Player p : pDefined) {
|
||||
List<Card> list = p.getCardsIn(origin);
|
||||
|
||||
if ((type != null) && p.isComputer()) {
|
||||
if ((type != null) && p == ai) {
|
||||
// AI only "knows" about his information
|
||||
list = CardLists.getValidCards(list, type, source.getController(), source);
|
||||
}
|
||||
@@ -402,7 +402,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
List<Card> list = p.getCardsIn(origin);
|
||||
|
||||
// Computer should "know" his deck
|
||||
if (p.isComputer()) {
|
||||
if (p == ai) {
|
||||
list = AbilityFactory.filterListByType(list, sa.getParam("ChangeType"), sa);
|
||||
}
|
||||
|
||||
@@ -741,7 +741,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
CardLists.sortByEvaluateCreature(combatants);
|
||||
|
||||
for (final Card c : combatants) {
|
||||
if (c.getShield() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(c) && !c.getOwner().isHuman() && !c.isToken()) {
|
||||
if (c.getShield() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c) && c.getOwner() == ai && !c.isToken()) {
|
||||
tgt.addTarget(c);
|
||||
return true;
|
||||
}
|
||||
@@ -812,7 +812,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
for (Card aura : c.getEnchantedBy()) {
|
||||
if (c.getOwner().isHuman() && aura.getController().equals(ai)) {
|
||||
if (c.getOwner().isHostileTo(ai) && aura.getController().equals(ai)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1036,7 +1036,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
if (!list.isEmpty()) {
|
||||
final Card attachedTo = list.get(0);
|
||||
// This code is for the Dragon auras
|
||||
if (attachedTo.getController().isHuman()) {
|
||||
if (attachedTo.getController().isHostileTo(ai)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1147,7 +1147,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (player.isHuman() && sa.hasParam("GainControl") && activator.equals(ai)) {
|
||||
if (player.isHostileTo(ai) && sa.hasParam("GainControl") && activator.equals(ai)) {
|
||||
fetchList = CardLists.filter(fetchList, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
@@ -1161,7 +1161,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
}
|
||||
if (ZoneType.Exile.equals(destination) || origin.contains(ZoneType.Battlefield)) {
|
||||
// Exiling or bouncing stuff
|
||||
if (player.isHuman()) {
|
||||
if (player.isHostileTo(ai)) {
|
||||
c = CardFactoryUtil.getBestAI(fetchList);
|
||||
} else {
|
||||
c = CardFactoryUtil.getWorstAI(fetchList);
|
||||
|
||||
@@ -155,7 +155,7 @@ public class DamageDealAi extends DamageAiBase {
|
||||
final List<Card> killables = CardLists.filter(hPlay, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return (c.getEnoughDamageToKill(d, source, false, noPrevention) <= d) && !ComputerUtil.canRegenerate(c)
|
||||
return (c.getEnoughDamageToKill(d, source, false, noPrevention) <= d) && !ComputerUtil.canRegenerate(ai, c)
|
||||
&& !(c.getSVar("SacMe").length() > 0);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -68,7 +68,7 @@ public class DamagePreventAi extends SpellAiLogic {
|
||||
for (final Object o : objects) {
|
||||
if (o instanceof Card) {
|
||||
final Card c = (Card) o;
|
||||
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(c);
|
||||
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(ai, c);
|
||||
} else if (o instanceof Player) {
|
||||
// Don't need to worry about Combat Damage during AI's turn
|
||||
final Player p = (Player) o;
|
||||
@@ -134,7 +134,7 @@ public class DamagePreventAi extends SpellAiLogic {
|
||||
CardLists.sortByEvaluateCreature(combatants);
|
||||
|
||||
for (final Card c : combatants) {
|
||||
if (ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||
if (ComputerUtilCombat.combatantWouldBeDestroyed(ai, c)) {
|
||||
tgt.addTarget(c);
|
||||
chance = true;
|
||||
break;
|
||||
@@ -195,7 +195,7 @@ public class DamagePreventAi extends SpellAiLogic {
|
||||
CardLists.sortByEvaluateCreature(combatants);
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
||||
for (final Card c : combatants) {
|
||||
if (ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||
if (ComputerUtilCombat.combatantWouldBeDestroyed(ai, c)) {
|
||||
tgt.addTarget(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class DestroyAi extends SpellAiLogic {
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||
protected boolean canPlayAI(final Player ai, SpellAbility sa) {
|
||||
// AI needs to be expanded, since this function can be pretty complex
|
||||
// based on what the expected targets could be
|
||||
final Random r = MyRandom.getRandom();
|
||||
@@ -105,7 +105,7 @@ public class DestroyAi extends SpellAiLogic {
|
||||
list = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return ((c.getShield() == 0) && !ComputerUtil.canRegenerate(c));
|
||||
return ((c.getShield() == 0) && !ComputerUtil.canRegenerate(ai, c));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -52,10 +52,10 @@ public class LifeGainAi extends SpellAiLogic {
|
||||
}
|
||||
// don't play if the conditions aren't met, unless it would trigger a
|
||||
// beneficial sub-condition
|
||||
if (!AbilityFactory.checkConditional(sa)) {
|
||||
if (!sa.getConditions().areMet(sa)) {
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null && !sa.isWrapper() && "True".equals(source.getSVar("AIPlayForSub"))) {
|
||||
if (!AbilityFactory.checkConditional(abSub)) {
|
||||
if (!abSub.getConditions().areMet(abSub)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -34,7 +34,7 @@ public class MustBlockAi extends SpellAiLogic {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||
protected boolean doTriggerAINoCost(final Player ai, SpellAbility sa, boolean mandatory) {
|
||||
final Card source = sa.getSourceCard();
|
||||
final Target abTgt = sa.getTarget();
|
||||
|
||||
@@ -73,10 +73,10 @@ public class MustBlockAi extends SpellAiLogic {
|
||||
if (!CombatUtil.canBlock(definedAttacker, c)) {
|
||||
return false;
|
||||
}
|
||||
if (ComputerUtilCombat.canDestroyAttacker(definedAttacker, c, null, false)) {
|
||||
if (ComputerUtilCombat.canDestroyAttacker(ai, definedAttacker, c, null, false)) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCombat.canDestroyBlocker(c, definedAttacker, null, false)) {
|
||||
if (!ComputerUtilCombat.canDestroyBlocker(ai, c, definedAttacker, null, false)) {
|
||||
return false;
|
||||
}
|
||||
c.setTapped(tapped);
|
||||
|
||||
@@ -15,6 +15,7 @@ import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.GameState;
|
||||
import forge.game.ai.ComputerUtilCombat;
|
||||
import forge.game.ai.ComputerUtilCost;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -66,6 +67,7 @@ public class ProtectAi extends SpellAiLogic {
|
||||
*/
|
||||
private static List<Card> getProtectCreatures(final Player ai, final SpellAbility sa) {
|
||||
final ArrayList<String> gains = AbilityFactory.getProtectionList(sa);
|
||||
final GameState game = Singletons.getModel().getGame();
|
||||
|
||||
List<Card> list = ai.getCreaturesInPlay();
|
||||
list = CardLists.filter(list, new Predicate<Card>() {
|
||||
@@ -81,8 +83,8 @@ public class ProtectAi extends SpellAiLogic {
|
||||
}
|
||||
|
||||
// will the creature attack (only relevant for sorcery speed)?
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
||||
&& Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(ai)
|
||||
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
||||
&& game.getPhaseHandler().isPlayerTurn(ai)
|
||||
&& CardFactoryUtil.doesCreatureAttackAI(ai, c)) {
|
||||
return true;
|
||||
}
|
||||
@@ -90,14 +92,14 @@ public class ProtectAi extends SpellAiLogic {
|
||||
// is the creature blocking and unable to destroy the attacker
|
||||
// or would be destroyed itself?
|
||||
if (c.isBlocking()
|
||||
&& (ComputerUtilCombat.blockerWouldBeDestroyed(c))) {
|
||||
&& (ComputerUtilCombat.blockerWouldBeDestroyed(ai, c))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// is the creature in blocked and the blocker would survive
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)
|
||||
&& Singletons.getModel().getGame().getCombat().isAttacking(c) && Singletons.getModel().getGame().getCombat().isBlocked(c)
|
||||
&& ComputerUtilCombat.blockerWouldBeDestroyed(Singletons.getModel().getGame().getCombat().getBlockers(c).get(0))) {
|
||||
if (game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)
|
||||
&& game.getCombat().isAttacking(c) && game.getCombat().isBlocked(c)
|
||||
&& ComputerUtilCombat.blockerWouldBeDestroyed(ai, game.getCombat().getBlockers(c).get(0))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.abilityfactory.SpellAiLogic;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.GameState;
|
||||
import forge.game.ai.ComputerUtilCombat;
|
||||
import forge.game.phase.Combat;
|
||||
import forge.game.phase.CombatUtil;
|
||||
@@ -223,7 +224,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
||||
List<Card> attackers = combat.getAttackers();
|
||||
for (Card attacker : attackers) {
|
||||
if (CombatUtil.canBlock(attacker, card, combat)
|
||||
&& !ComputerUtilCombat.canDestroyAttacker(attacker, card, combat, false)) {
|
||||
&& !ComputerUtilCombat.canDestroyAttacker(ai, attacker, card, combat, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -232,7 +233,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
||||
List<Card> blockers = opp.getCreaturesInPlay();
|
||||
for (Card blocker : blockers) {
|
||||
if (CombatUtil.canBlock(card, blocker, combat)
|
||||
&& !ComputerUtilCombat.canDestroyBlocker(blocker, card, combat, false)) {
|
||||
&& !ComputerUtilCombat.canDestroyBlocker(ai, blocker, card, combat, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -382,7 +383,8 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
||||
|
||||
protected boolean shouldPumpCard(final Player ai, final SpellAbility sa, final Card c, final int defense, final int attack,
|
||||
final List<String> keywords) {
|
||||
PhaseHandler phase = Singletons.getModel().getGame().getPhaseHandler();
|
||||
final GameState game = Singletons.getModel().getGame();
|
||||
PhaseHandler phase = game.getPhaseHandler();
|
||||
|
||||
if (!c.canBeTargetedBy(sa)) {
|
||||
return false;
|
||||
@@ -408,36 +410,35 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
||||
// is the creature blocking and unable to destroy the attacker
|
||||
// or would be destroyed itself?
|
||||
if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) && c.isBlocking()) {
|
||||
if (defense > 0 && ComputerUtilCombat.blockerWouldBeDestroyed(c)) {
|
||||
if (defense > 0 && ComputerUtilCombat.blockerWouldBeDestroyed(ai, c)) {
|
||||
return true;
|
||||
}
|
||||
List<Card> blockedBy = Singletons.getModel().getGame().getCombat().getAttackersBlockedBy(c);
|
||||
// For now, Only care the first creature blocked by a card.
|
||||
// TODO Add in better BlockAdditional support
|
||||
if (!blockedBy.isEmpty() && attack > 0 && !ComputerUtilCombat.attackerWouldBeDestroyed(blockedBy.get(0))) {
|
||||
if (!blockedBy.isEmpty() && attack > 0 && !ComputerUtilCombat.attackerWouldBeDestroyed(ai, blockedBy.get(0))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// is the creature unblocked and the spell will pump its power?
|
||||
if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)
|
||||
&& Singletons.getModel().getGame().getCombat().isAttacking(c)
|
||||
&& Singletons.getModel().getGame().getCombat().isUnblocked(c) && attack > 0) {
|
||||
&& game.getCombat().isAttacking(c) && game.getCombat().isUnblocked(c) && attack > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// is the creature blocked and the blocker would survive
|
||||
if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) && attack > 0
|
||||
&& Singletons.getModel().getGame().getCombat().isAttacking(c)
|
||||
&& Singletons.getModel().getGame().getCombat().isBlocked(c)
|
||||
&& Singletons.getModel().getGame().getCombat().getBlockers(c) != null
|
||||
&& !Singletons.getModel().getGame().getCombat().getBlockers(c).isEmpty()
|
||||
&& !ComputerUtilCombat.blockerWouldBeDestroyed(Singletons.getModel().getGame().getCombat().getBlockers(c).get(0))) {
|
||||
&& game.getCombat().isAttacking(c)
|
||||
&& game.getCombat().isBlocked(c)
|
||||
&& game.getCombat().getBlockers(c) != null
|
||||
&& !game.getCombat().getBlockers(c).isEmpty()
|
||||
&& !ComputerUtilCombat.blockerWouldBeDestroyed(ai, game.getCombat().getBlockers(c).get(0))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the life of the computer is in danger, try to pump blockers blocking Tramplers
|
||||
List<Card> blockedBy = Singletons.getModel().getGame().getCombat().getAttackersBlockedBy(c);
|
||||
List<Card> blockedBy = game.getCombat().getAttackersBlockedBy(c);
|
||||
boolean attackerHasTrample = false;
|
||||
for (Card b : blockedBy) {
|
||||
attackerHasTrample |= b.hasKeyword("Trample");
|
||||
@@ -448,7 +449,7 @@ public abstract class PumpAiBase extends SpellAiLogic {
|
||||
&& c.isBlocking()
|
||||
&& defense > 0
|
||||
&& attackerHasTrample
|
||||
&& (sa.isAbility() || ComputerUtilCombat.lifeInDanger(ai, Singletons.getModel().getGame().getCombat()))) {
|
||||
&& (sa.isAbility() || ComputerUtilCombat.lifeInDanger(ai, game.getCombat()))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ public class RegenerateAi extends SpellAiLogic {
|
||||
|
||||
for (final Card c : list) {
|
||||
if (c.getShield() == 0) {
|
||||
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(c);
|
||||
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(ai, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ public class RegenerateAi extends SpellAiLogic {
|
||||
CardLists.sortByEvaluateCreature(combatants);
|
||||
|
||||
for (final Card c : combatants) {
|
||||
if ((c.getShield() == 0) && ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||
if ((c.getShield() == 0) && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c)) {
|
||||
tgt.addTarget(c);
|
||||
chance = true;
|
||||
break;
|
||||
@@ -190,7 +190,7 @@ public class RegenerateAi extends SpellAiLogic {
|
||||
CardLists.sortByEvaluateCreature(combatants);
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
||||
for (final Card c : combatants) {
|
||||
if ((c.getShield() == 0) && ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||
if ((c.getShield() == 0) && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c)) {
|
||||
tgt.addTarget(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class RegenerateAllAi extends SpellAiLogic {
|
||||
final List<Card> combatants = CardLists.filter(list, CardPredicates.Presets.CREATURES);
|
||||
|
||||
for (final Card c : combatants) {
|
||||
if (c.getShield() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(c)) {
|
||||
if (c.getShield() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c)) {
|
||||
numSaved++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ public class ChooseTypeEffect extends SpellEffect {
|
||||
GuiChoose.one("Computer picked: ", new String[]{chosen});
|
||||
chosenType = chosen;
|
||||
}
|
||||
|
||||
if (CardUtil.isACreatureType(chosenType) && !invalidTypes.contains(chosenType)) {
|
||||
valid = true;
|
||||
card.setChosenType(chosenType);
|
||||
|
||||
@@ -166,7 +166,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public final boolean checkConditions(final SpellAbility sa) {
|
||||
public final boolean areMet(final SpellAbility sa) {
|
||||
|
||||
Player activator = sa.getActivatingPlayer();
|
||||
if (activator == null) {
|
||||
|
||||
@@ -901,7 +901,7 @@ public class AiAttackController {
|
||||
if ((isWorthLessThanAllKillers || canKillAllDangerous || numberOfPossibleBlockers < 2)
|
||||
&& CombatUtil.canBlock(attacker, defender)) {
|
||||
numberOfPossibleBlockers += 1;
|
||||
if (isWorthLessThanAllKillers && ComputerUtilCombat.canDestroyAttacker(attacker, defender, combat, false)
|
||||
if (isWorthLessThanAllKillers && ComputerUtilCombat.canDestroyAttacker(ai, attacker, defender, combat, false)
|
||||
&& !(attacker.hasKeyword("Undying") && attacker.getCounters(CounterType.P1P1) == 0)) {
|
||||
canBeKilledByOne = true; // there is a single creature on
|
||||
// the battlefield that can kill
|
||||
@@ -915,7 +915,7 @@ public class AiAttackController {
|
||||
}
|
||||
// see if this attacking creature can destroy this defender, if
|
||||
// not record that it can't kill everything
|
||||
if (canKillAllDangerous && !ComputerUtilCombat.canDestroyBlocker(defender, attacker, combat, false)) {
|
||||
if (canKillAllDangerous && !ComputerUtilCombat.canDestroyBlocker(ai, defender, attacker, combat, false)) {
|
||||
canKillAll = false;
|
||||
if (!canKillAllDangerous) {
|
||||
continue;
|
||||
|
||||
@@ -415,7 +415,7 @@ public class ComputerUtil {
|
||||
typeList = CardLists.getNotType(typeList, "Creature");
|
||||
}
|
||||
|
||||
if ((target != null) && target.getController().isComputer() && typeList.contains(target)) {
|
||||
if ((target != null) && target.getController() == ai && typeList.contains(target)) {
|
||||
typeList.remove(target); // don't sacrifice the card we're pumping
|
||||
}
|
||||
|
||||
@@ -473,7 +473,7 @@ public class ComputerUtil {
|
||||
} else {
|
||||
typeList = CardLists.getValidCards(ai.getCardsIn(zone), type.split(","), activate.getController(), activate);
|
||||
}
|
||||
if ((target != null) && target.getController().isComputer() && typeList.contains(target)) {
|
||||
if ((target != null) && target.getController() == ai && typeList.contains(target)) {
|
||||
typeList.remove(target); // don't exile the card we're pumping
|
||||
}
|
||||
|
||||
@@ -588,7 +588,7 @@ public class ComputerUtil {
|
||||
public static List<Card> chooseReturnType(final Player ai, final String type, final Card activate, final Card target, final int amount) {
|
||||
final List<Card> typeList =
|
||||
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(","), activate.getController(), activate);
|
||||
if ((target != null) && target.getController().isComputer() && typeList.contains(target)) {
|
||||
if ((target != null) && target.getController() == ai && typeList.contains(target)) {
|
||||
// don't bounce the card we're pumping
|
||||
typeList.remove(target);
|
||||
}
|
||||
@@ -709,12 +709,13 @@ public class ComputerUtil {
|
||||
* <p>
|
||||
* canRegenerate.
|
||||
* </p>
|
||||
* @param ai
|
||||
*
|
||||
* @param card
|
||||
* a {@link forge.Card} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean canRegenerate(final Card card) {
|
||||
public static boolean canRegenerate(Player ai, final Card card) {
|
||||
|
||||
if (card.hasKeyword("CARDNAME can't be regenerated.")) {
|
||||
return false;
|
||||
@@ -736,7 +737,7 @@ public class ComputerUtil {
|
||||
continue; // Can't play ability
|
||||
}
|
||||
|
||||
if (controller.isComputer()) {
|
||||
if (controller == ai) {
|
||||
final Cost abCost = sa.getPayCosts();
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
|
||||
@@ -229,11 +229,11 @@ public class ComputerUtilBlock {
|
||||
* a {@link forge.game.phase.Combat} object.
|
||||
* @return a {@link forge.CardList} object.
|
||||
*/
|
||||
private static List<Card> getSafeBlockers(final Card attacker, final List<Card> blockersLeft, final Combat combat) {
|
||||
private static List<Card> getSafeBlockers(final Player ai, final Card attacker, final List<Card> blockersLeft, final Combat combat) {
|
||||
final List<Card> blockers = new ArrayList<Card>();
|
||||
|
||||
for (final Card b : blockersLeft) {
|
||||
if (!ComputerUtilCombat.canDestroyBlocker(b, attacker, combat, false)) {
|
||||
if (!ComputerUtilCombat.canDestroyBlocker(ai, b, attacker, combat, false)) {
|
||||
blockers.add(b);
|
||||
}
|
||||
}
|
||||
@@ -255,11 +255,11 @@ public class ComputerUtilBlock {
|
||||
* a {@link forge.game.phase.Combat} object.
|
||||
* @return a {@link forge.CardList} object.
|
||||
*/
|
||||
private static List<Card> getKillingBlockers(final Card attacker, final List<Card> blockersLeft, final Combat combat) {
|
||||
private static List<Card> getKillingBlockers(final Player ai, final Card attacker, final List<Card> blockersLeft, final Combat combat) {
|
||||
final List<Card> blockers = new ArrayList<Card>();
|
||||
|
||||
for (final Card b : blockersLeft) {
|
||||
if (ComputerUtilCombat.canDestroyAttacker(attacker, b, combat, false)) {
|
||||
if (ComputerUtilCombat.canDestroyAttacker(ai, attacker, b, combat, false)) {
|
||||
blockers.add(b);
|
||||
}
|
||||
}
|
||||
@@ -337,7 +337,7 @@ public class ComputerUtilBlock {
|
||||
* a {@link forge.game.phase.Combat} object.
|
||||
* @return a {@link forge.game.phase.Combat} object.
|
||||
*/
|
||||
private static Combat makeGoodBlocks(final Combat combat) {
|
||||
private static Combat makeGoodBlocks(final Player ai, final Combat combat) {
|
||||
|
||||
List<Card> currentAttackers = new ArrayList<Card>(ComputerUtilBlock.getAttackersLeft());
|
||||
|
||||
@@ -352,13 +352,13 @@ public class ComputerUtilBlock {
|
||||
final List<Card> blockers = ComputerUtilBlock.getPossibleBlockers(attacker,
|
||||
ComputerUtilBlock.getBlockersLeft(), combat, true);
|
||||
|
||||
final List<Card> safeBlockers = ComputerUtilBlock.getSafeBlockers(attacker, blockers, combat);
|
||||
final List<Card> safeBlockers = ComputerUtilBlock.getSafeBlockers(ai, attacker, blockers, combat);
|
||||
List<Card> killingBlockers;
|
||||
|
||||
if (safeBlockers.size() > 0) {
|
||||
// 1.Blockers that can destroy the attacker but won't get
|
||||
// destroyed
|
||||
killingBlockers = ComputerUtilBlock.getKillingBlockers(attacker, safeBlockers, combat);
|
||||
killingBlockers = ComputerUtilBlock.getKillingBlockers(ai, attacker, safeBlockers, combat);
|
||||
if (killingBlockers.size() > 0) {
|
||||
blocker = CardFactoryUtil.getWorstCreatureAI(killingBlockers);
|
||||
} else if (!attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")) {
|
||||
@@ -368,7 +368,7 @@ public class ComputerUtilBlock {
|
||||
} // no safe blockers
|
||||
else {
|
||||
// 3.Blockers that can destroy the attacker and have an upside when dying
|
||||
killingBlockers = ComputerUtilBlock.getKillingBlockers(attacker, blockers, combat);
|
||||
killingBlockers = ComputerUtilBlock.getKillingBlockers(ai, attacker, blockers, combat);
|
||||
for (Card b : killingBlockers) {
|
||||
if ((b.hasKeyword("Undying") && b.getCounters(CounterType.P1P1) == 0)
|
||||
|| !b.getSVar("SacMe").equals("")) {
|
||||
@@ -542,7 +542,7 @@ public class ComputerUtilBlock {
|
||||
continue;
|
||||
}
|
||||
|
||||
killingBlockers = ComputerUtilBlock.getKillingBlockers(attacker,
|
||||
killingBlockers = ComputerUtilBlock.getKillingBlockers(ai, attacker,
|
||||
ComputerUtilBlock.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true),
|
||||
combat);
|
||||
if ((killingBlockers.size() > 0) && ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||
@@ -648,7 +648,7 @@ public class ComputerUtilBlock {
|
||||
* a {@link forge.game.phase.Combat} object.
|
||||
* @return a {@link forge.game.phase.Combat} object.
|
||||
*/
|
||||
private static Combat reinforceBlockersToKill(final Combat combat) {
|
||||
private static Combat reinforceBlockersToKill(final Player ai, final Combat combat) {
|
||||
|
||||
List<Card> safeBlockers;
|
||||
List<Card> blockers;
|
||||
@@ -664,7 +664,7 @@ public class ComputerUtilBlock {
|
||||
blockers.removeAll(combat.getBlockers(attacker));
|
||||
|
||||
// Try to use safe blockers first
|
||||
safeBlockers = ComputerUtilBlock.getSafeBlockers(attacker, blockers, combat);
|
||||
safeBlockers = ComputerUtilBlock.getSafeBlockers(ai, attacker, blockers, combat);
|
||||
for (final Card blocker : safeBlockers) {
|
||||
final int damageNeeded = attacker.getKillDamage()
|
||||
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
|
||||
@@ -808,7 +808,7 @@ public class ComputerUtilBlock {
|
||||
CardLists.sortAttackLowFirst(ComputerUtilBlock.getBlockersLeft());
|
||||
|
||||
// == 1. choose best blocks first ==
|
||||
combat = ComputerUtilBlock.makeGoodBlocks(combat);
|
||||
combat = ComputerUtilBlock.makeGoodBlocks(ai, combat);
|
||||
combat = ComputerUtilBlock.makeGangBlocks(ai, combat);
|
||||
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||
combat = ComputerUtilBlock.makeTradeBlocks(ai, combat); // choose
|
||||
@@ -830,7 +830,7 @@ public class ComputerUtilBlock {
|
||||
// Support blockers not destroying the attacker with more blockers to
|
||||
// try to kill the attacker
|
||||
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||
combat = ComputerUtilBlock.reinforceBlockersToKill(combat);
|
||||
combat = ComputerUtilBlock.reinforceBlockersToKill(ai, combat);
|
||||
}
|
||||
|
||||
// == 2. If the AI life would still be in danger make a safer approach
|
||||
@@ -845,7 +845,7 @@ public class ComputerUtilBlock {
|
||||
// necessary
|
||||
// trade blocks
|
||||
// if life is in danger
|
||||
combat = ComputerUtilBlock.makeGoodBlocks(combat);
|
||||
combat = ComputerUtilBlock.makeGoodBlocks(ai, combat);
|
||||
if (ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||
combat = ComputerUtilBlock.makeChumpBlocks(ai, combat); // choose
|
||||
// necessary
|
||||
@@ -859,7 +859,7 @@ public class ComputerUtilBlock {
|
||||
combat = ComputerUtilBlock.reinforceBlockersAgainstTrample(ai, combat);
|
||||
}
|
||||
combat = ComputerUtilBlock.makeGangBlocks(ai, combat);
|
||||
combat = ComputerUtilBlock.reinforceBlockersToKill(combat);
|
||||
combat = ComputerUtilBlock.reinforceBlockersToKill(ai, combat);
|
||||
}
|
||||
|
||||
// == 3. If the AI life would be in serious danger make an even safer
|
||||
@@ -878,7 +878,7 @@ public class ComputerUtilBlock {
|
||||
}
|
||||
|
||||
if (!ComputerUtilCombat.lifeInDanger(ai, combat)) {
|
||||
combat = ComputerUtilBlock.makeGoodBlocks(combat);
|
||||
combat = ComputerUtilBlock.makeGoodBlocks(ai, combat);
|
||||
}
|
||||
// Reinforce blockers blocking attackers with trample if life is
|
||||
// still in danger
|
||||
@@ -888,7 +888,7 @@ public class ComputerUtilBlock {
|
||||
combat = ComputerUtilBlock.makeGangBlocks(ai, combat);
|
||||
// Support blockers not destroying the attacker with more blockers
|
||||
// to try to kill the attacker
|
||||
combat = ComputerUtilBlock.reinforceBlockersToKill(combat);
|
||||
combat = ComputerUtilBlock.reinforceBlockersToKill(ai, combat);
|
||||
}
|
||||
|
||||
// assign blockers that have to block
|
||||
|
||||
@@ -517,18 +517,19 @@ public class ComputerUtilCombat {
|
||||
* <p>
|
||||
* combatantWouldBeDestroyed.
|
||||
* </p>
|
||||
* @param ai
|
||||
*
|
||||
* @param combatant
|
||||
* a {@link forge.Card} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean combatantWouldBeDestroyed(final Card combatant) {
|
||||
public static boolean combatantWouldBeDestroyed(Player ai, final Card combatant) {
|
||||
|
||||
if (combatant.isAttacking()) {
|
||||
return ComputerUtilCombat.attackerWouldBeDestroyed(combatant);
|
||||
return ComputerUtilCombat.attackerWouldBeDestroyed(ai, combatant);
|
||||
}
|
||||
if (combatant.isBlocking()) {
|
||||
return ComputerUtilCombat.blockerWouldBeDestroyed(combatant);
|
||||
return ComputerUtilCombat.blockerWouldBeDestroyed(ai, combatant);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -538,16 +539,17 @@ public class ComputerUtilCombat {
|
||||
* <p>
|
||||
* attackerWouldBeDestroyed.
|
||||
* </p>
|
||||
* @param ai
|
||||
*
|
||||
* @param attacker
|
||||
* a {@link forge.Card} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean attackerWouldBeDestroyed(final Card attacker) {
|
||||
public static boolean attackerWouldBeDestroyed(Player ai, final Card attacker) {
|
||||
final List<Card> blockers = Singletons.getModel().getGame().getCombat().getBlockers(attacker);
|
||||
|
||||
for (final Card defender : blockers) {
|
||||
if (ComputerUtilCombat.canDestroyAttacker(attacker, defender, Singletons.getModel().getGame().getCombat(), true)
|
||||
if (ComputerUtilCombat.canDestroyAttacker(ai, attacker, defender, Singletons.getModel().getGame().getCombat(), true)
|
||||
&& !(defender.hasKeyword("Wither") || defender.hasKeyword("Infect"))) {
|
||||
return true;
|
||||
}
|
||||
@@ -1343,6 +1345,7 @@ public class ComputerUtilCombat {
|
||||
* <p>
|
||||
* canDestroyAttacker.
|
||||
* </p>
|
||||
* @param ai
|
||||
*
|
||||
* @param attacker
|
||||
* a {@link forge.Card} object.
|
||||
@@ -1354,7 +1357,7 @@ public class ComputerUtilCombat {
|
||||
* a boolean.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean canDestroyAttacker(final Card attacker, final Card defender, final Combat combat,
|
||||
public static boolean canDestroyAttacker(Player ai, final Card attacker, final Card defender, final Combat combat,
|
||||
final boolean withoutAbilities) {
|
||||
|
||||
if (attacker.getName().equals("Sylvan Basilisk") && !defender.hasKeyword("Indestructible")) {
|
||||
@@ -1375,7 +1378,7 @@ public class ComputerUtilCombat {
|
||||
}
|
||||
} // flanking
|
||||
|
||||
if (((attacker.hasKeyword("Indestructible") || (ComputerUtil.canRegenerate(attacker) && !withoutAbilities)) && !(defender
|
||||
if (((attacker.hasKeyword("Indestructible") || (ComputerUtil.canRegenerate(ai, attacker) && !withoutAbilities)) && !(defender
|
||||
.hasKeyword("Wither") || defender.hasKeyword("Infect")))
|
||||
|| (attacker.hasKeyword("Persist") && !attacker.canHaveCountersPlacedOnIt(CounterType.M1M1) && (attacker
|
||||
.getCounters(CounterType.M1M1) == 0))
|
||||
@@ -1471,18 +1474,19 @@ public class ComputerUtilCombat {
|
||||
* <p>
|
||||
* blockerWouldBeDestroyed.
|
||||
* </p>
|
||||
* @param ai
|
||||
*
|
||||
* @param blocker
|
||||
* a {@link forge.Card} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean blockerWouldBeDestroyed(final Card blocker) {
|
||||
public static boolean blockerWouldBeDestroyed(Player ai, final Card blocker) {
|
||||
// TODO THis function only checks if a single attacker at a time would destroy a blocker
|
||||
// This needs to expand to tally up damage
|
||||
final List<Card> attackers = Singletons.getModel().getGame().getCombat().getAttackersBlockedBy(blocker);
|
||||
|
||||
for (Card attacker : attackers) {
|
||||
if (ComputerUtilCombat.canDestroyBlocker(blocker, attacker, Singletons.getModel().getGame().getCombat(), true)
|
||||
if (ComputerUtilCombat.canDestroyBlocker(ai, blocker, attacker, Singletons.getModel().getGame().getCombat(), true)
|
||||
&& !(attacker.hasKeyword("Wither") || attacker.hasKeyword("Infect"))) {
|
||||
return true;
|
||||
}
|
||||
@@ -1495,6 +1499,7 @@ public class ComputerUtilCombat {
|
||||
* <p>
|
||||
* canDestroyBlocker.
|
||||
* </p>
|
||||
* @param ai
|
||||
*
|
||||
* @param defender
|
||||
* a {@link forge.Card} object.
|
||||
@@ -1506,7 +1511,7 @@ public class ComputerUtilCombat {
|
||||
* a boolean.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean canDestroyBlocker(final Card defender, final Card attacker, final Combat combat,
|
||||
public static boolean canDestroyBlocker(Player ai, final Card defender, final Card attacker, final Combat combat,
|
||||
final boolean withoutAbilities) {
|
||||
|
||||
int flankingMagnitude = 0;
|
||||
@@ -1522,7 +1527,7 @@ public class ComputerUtilCombat {
|
||||
}
|
||||
} // flanking
|
||||
|
||||
if (((defender.hasKeyword("Indestructible") || (ComputerUtil.canRegenerate(defender) && !withoutAbilities)) && !(attacker
|
||||
if (((defender.hasKeyword("Indestructible") || (ComputerUtil.canRegenerate(ai, defender) && !withoutAbilities)) && !(attacker
|
||||
.hasKeyword("Wither") || attacker.hasKeyword("Infect")))
|
||||
|| (defender.hasKeyword("Persist") && !defender.canHaveCountersPlacedOnIt(CounterType.M1M1) && (defender
|
||||
.getCounters(CounterType.M1M1) == 0))
|
||||
|
||||
Reference in New Issue
Block a user