mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
removed CombatUtil.canAttack method without specifying attack target
This commit is contained in:
@@ -120,13 +120,6 @@ public final class CardPredicates {
|
||||
};
|
||||
}
|
||||
|
||||
public static final Predicate<Card> possibleAttackers = new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return (c.isCreature() && CombatUtil.canAttack(c));
|
||||
}
|
||||
};
|
||||
|
||||
public final static Predicate<Card> isProtectedFrom(final Card source) {
|
||||
return new Predicate<Card>() {
|
||||
@Override
|
||||
@@ -184,13 +177,6 @@ public final class CardPredicates {
|
||||
};
|
||||
|
||||
|
||||
public static final Predicate<Card> CREATURES_CAN_ATTACK = new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return c.isCreature() && CombatUtil.canAttack(c);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* a Predicate<Card> to get all enchantments.
|
||||
*/
|
||||
|
||||
@@ -392,11 +392,11 @@ public class AbilityFactoryAttach {
|
||||
* the logic
|
||||
* @return the card
|
||||
*/
|
||||
public static Card attachGeneralAI(final Player aiPlayer, final SpellAbility sa, final List<Card> list, final boolean mandatory,
|
||||
public static Card attachGeneralAI(final Player ai, final SpellAbility sa, final List<Card> list, final boolean mandatory,
|
||||
final Card attachSource, final String logic) {
|
||||
Player prefPlayer = aiPlayer.getOpponent();
|
||||
Player prefPlayer = ai.getOpponent();
|
||||
if ("Pump".equals(logic) || "Animate".equals(logic) ) {
|
||||
prefPlayer = aiPlayer;
|
||||
prefPlayer = ai;
|
||||
}
|
||||
// Some ChangeType cards are beneficial, and PrefPlayer should be
|
||||
// changed to represent that
|
||||
@@ -415,7 +415,7 @@ public class AbilityFactoryAttach {
|
||||
} else if ("Curse".equals(logic)) {
|
||||
c = AbilityFactoryAttach.attachAICursePreference(sa, prefList, mandatory, attachSource);
|
||||
} else if ("Pump".equals(logic)) {
|
||||
c = AbilityFactoryAttach.attachAIPumpPreference(sa, prefList, mandatory, attachSource);
|
||||
c = AbilityFactoryAttach.attachAIPumpPreference(ai, sa, prefList, mandatory, attachSource);
|
||||
} else if ("ChangeType".equals(logic)) {
|
||||
c = AbilityFactoryAttach.attachAIChangeTypePreference(sa, prefList, mandatory, attachSource);
|
||||
} else if ("KeepTapped".equals(logic)) {
|
||||
@@ -688,7 +688,7 @@ public class AbilityFactoryAttach {
|
||||
* the attach source
|
||||
* @return the card
|
||||
*/
|
||||
public static Card attachAIPumpPreference(final SpellAbility sa, final List<Card> list, final boolean mandatory,
|
||||
public static Card attachAIPumpPreference(final Player ai, final SpellAbility sa, final List<Card> list, final boolean mandatory,
|
||||
final Card attachSource) {
|
||||
// AI For choosing a Card to Pump
|
||||
Card c = null;
|
||||
@@ -724,7 +724,7 @@ public class AbilityFactoryAttach {
|
||||
magnetList = CardLists.filter(magnetList, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return CombatUtil.canAttack(c);
|
||||
return CombatUtil.canAttack(c, ai.getOpponent());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -800,7 +800,8 @@ public final class AbilityFactoryDebuff {
|
||||
// final Card source = sa.getSourceCard();
|
||||
final Card hostCard = af.getHostCard();
|
||||
final HashMap<String, String> params = af.getMapParams();
|
||||
|
||||
final Player opp = ai.getOpponent();
|
||||
|
||||
final boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); // to
|
||||
// prevent
|
||||
// runaway
|
||||
@@ -812,16 +813,17 @@ public final class AbilityFactoryDebuff {
|
||||
|
||||
List<Card> comp = ai.getCardsIn(ZoneType.Battlefield);
|
||||
comp = CardLists.getValidCards(comp, valid, hostCard.getController(), hostCard);
|
||||
List<Card> human = ai.getOpponent().getCardsIn(ZoneType.Battlefield);
|
||||
List<Card> human = opp.getCardsIn(ZoneType.Battlefield);
|
||||
human = CardLists.getValidCards(human, valid, hostCard.getController(), hostCard);
|
||||
|
||||
// TODO - add blocking situations here also
|
||||
|
||||
|
||||
// only count creatures that can attack
|
||||
human = CardLists.filter(human, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return CombatUtil.canAttack(c);
|
||||
return CombatUtil.canAttack(c, opp);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import forge.card.spellability.Target;
|
||||
import forge.card.trigger.Trigger;
|
||||
import forge.card.trigger.TriggerHandler;
|
||||
import forge.card.trigger.TriggerType;
|
||||
import forge.game.GameState;
|
||||
import forge.game.phase.CombatUtil;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -252,39 +253,41 @@ public class AbilityFactoryEffect {
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean effectCanPlayAI(final Player ai, final AbilityFactory af, final SpellAbility sa) {
|
||||
final GameState game = Singletons.getModel().getGame();
|
||||
final Random r = MyRandom.getRandom();
|
||||
final HashMap<String, String> params = af.getMapParams();
|
||||
boolean randomReturn = r.nextFloat() <= .6667;
|
||||
final Player opp = ai.getOpponent();
|
||||
String logic = "";
|
||||
|
||||
if (params.containsKey("AILogic")) {
|
||||
logic = params.get("AILogic");
|
||||
final PhaseHandler phase = Singletons.getModel().getGame().getPhaseHandler();
|
||||
final PhaseHandler phase = game.getPhaseHandler();
|
||||
if (logic.equals("BeginningOfOppTurn")) {
|
||||
if (phase.isPlayerTurn(ai.getOpponent()) || phase.getPhase().isAfter(PhaseType.DRAW)) {
|
||||
return false;
|
||||
}
|
||||
randomReturn = true;
|
||||
} else if (logic.equals("Fog")) {
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) {
|
||||
if (game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) {
|
||||
return false;
|
||||
}
|
||||
if (!Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
||||
if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
||||
return false;
|
||||
}
|
||||
if (Singletons.getModel().getGame().getStack().size() != 0) {
|
||||
if (game.getStack().size() != 0) {
|
||||
return false;
|
||||
}
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().isPreventCombatDamageThisTurn()) {
|
||||
if (game.getPhaseHandler().isPreventCombatDamageThisTurn()) {
|
||||
return false;
|
||||
}
|
||||
if (!CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
|
||||
if (!CombatUtil.lifeInDanger(ai, game.getCombat())) {
|
||||
return false;
|
||||
}
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
tgt.resetTargets();
|
||||
List<Card> list = Singletons.getModel().getGame().getCombat().getAttackerList();
|
||||
List<Card> list = game.getCombat().getAttackerList();
|
||||
list = CardLists.getValidCards(list, tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
list = CardLists.getTargetableCards(list, sa);
|
||||
Card target = CardFactoryUtil.getBestCreatureAI(list);
|
||||
@@ -298,13 +301,13 @@ public class AbilityFactoryEffect {
|
||||
randomReturn = true;
|
||||
} else if (logic.equals("Evasion")) {
|
||||
List<Card> comp = ai.getCreaturesInPlay();
|
||||
List<Card> human = ai.getOpponent().getCreaturesInPlay();
|
||||
List<Card> human = opp.getCreaturesInPlay();
|
||||
|
||||
// only count creatures that can attack or block
|
||||
comp = CardLists.filter(comp, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return CombatUtil.canAttack(c);
|
||||
return CombatUtil.canAttack(c, opp);
|
||||
}
|
||||
});
|
||||
human = CardLists.filter(human, new Predicate<Card>() {
|
||||
|
||||
@@ -40,6 +40,7 @@ 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;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.ComputerUtil;
|
||||
@@ -998,7 +999,7 @@ public class AbilityFactoryPermanentState {
|
||||
*/
|
||||
private static boolean tapPrefTargeting(final Player ai, final Card source, final Target tgt, final AbilityFactory af,
|
||||
final SpellAbility sa, final boolean mandatory) {
|
||||
Player opp = ai.getOpponent();
|
||||
final Player opp = ai.getOpponent();
|
||||
List<Card> tapList = opp.getCardsIn(ZoneType.Battlefield);
|
||||
tapList = CardLists.filter(tapList, Presets.UNTAPPED);
|
||||
tapList = CardLists.getValidCards(tapList, tgt.getValidTgts(), source.getController(), source);
|
||||
@@ -1038,7 +1039,12 @@ public class AbilityFactoryPermanentState {
|
||||
//Combat has already started
|
||||
attackers = Singletons.getModel().getGame().getCombat().getAttackerList();
|
||||
} else {
|
||||
attackers = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES_CAN_ATTACK);
|
||||
attackers = CardLists.filter(ai.getCreaturesInPlay(), new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return CombatUtil.canAttack(c, opp);
|
||||
}
|
||||
});
|
||||
attackers.remove(sa.getSourceCard());
|
||||
}
|
||||
Predicate<Card> findBlockers = CardPredicates.possibleBlockerForAtLeastOne(attackers);
|
||||
@@ -1051,7 +1057,12 @@ public class AbilityFactoryPermanentState {
|
||||
&& phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
||||
// Tap creatures possible blockers before combat during AI's turn.
|
||||
if (Iterables.any(tapList, CardPredicates.Presets.CREATURES)) {
|
||||
List<Card> creatureList = CardLists.filter(tapList, CardPredicates.Presets.CREATURES_CAN_ATTACK);
|
||||
List<Card> creatureList = CardLists.filter(tapList, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return c.isCreature() && CombatUtil.canAttack(c, opp);
|
||||
}
|
||||
});
|
||||
choice = CardFactoryUtil.getBestCreatureAI(creatureList);
|
||||
} else { // no creatures available
|
||||
choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false);
|
||||
|
||||
@@ -318,20 +318,20 @@ public class AbilityFactoryPump {
|
||||
if (!CardUtil.isStackingKeyword(keyword) && card.hasKeyword(keyword)) {
|
||||
return false;
|
||||
} else if (keyword.equals("Defender") || keyword.endsWith("CARDNAME can't attack.")) {
|
||||
if (ph.isPlayerTurn(ai) || !CombatUtil.canAttack(card)
|
||||
if (ph.isPlayerTurn(ai) || !CombatUtil.canAttack(card, human)
|
||||
|| (card.getNetCombatDamage() <= 0)
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.endsWith("CARDNAME can't attack or block.")) {
|
||||
if (sa.getAbilityFactory().getMapParams().containsKey("UntilYourNextTurn")) {
|
||||
if (CombatUtil.canAttack(card) || CombatUtil.canBlock(card, true)) {
|
||||
if (CombatUtil.canAttack(card, human) || CombatUtil.canBlock(card, true)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (ph.isPlayerTurn(human)) {
|
||||
if (!CombatUtil.canAttack(card)
|
||||
if (!CombatUtil.canAttack(card, human)
|
||||
|| (card.getNetCombatDamage() <= 0)
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
||||
return false;
|
||||
@@ -342,7 +342,12 @@ public class AbilityFactoryPump {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Card> attackers = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.possibleAttackers);
|
||||
List<Card> attackers = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return (c.isCreature() && CombatUtil.canAttack(c, human));
|
||||
}
|
||||
});
|
||||
if (!CombatUtil.canBlockAtLeastOne(card, attackers)) {
|
||||
return false;
|
||||
}
|
||||
@@ -353,7 +358,12 @@ public class AbilityFactoryPump {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Card> attackers = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.possibleAttackers);
|
||||
List<Card> attackers = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return (c.isCreature() && CombatUtil.canAttack(c, human));
|
||||
}
|
||||
});
|
||||
if (!CombatUtil.canBlockAtLeastOne(card, attackers)) {
|
||||
return false;
|
||||
}
|
||||
@@ -376,7 +386,7 @@ public class AbilityFactoryPump {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.endsWith("CARDNAME attacks each turn if able.")) {
|
||||
if (ph.isPlayerTurn(ai) || !CombatUtil.canAttack(card) || !CombatUtil.canBeBlocked(card)
|
||||
if (ph.isPlayerTurn(ai) || !CombatUtil.canAttack(card, human) || !CombatUtil.canBeBlocked(card)
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
||||
return false;
|
||||
}
|
||||
@@ -418,7 +428,7 @@ public class AbilityFactoryPump {
|
||||
|| keyword.contains("Bushido"));
|
||||
// give evasive keywords to creatures that can or do attack
|
||||
if (evasive) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| card.getNetCombatDamage() <= 0
|
||||
|| cardsCanBlock.isEmpty()) {
|
||||
@@ -434,7 +444,7 @@ public class AbilityFactoryPump {
|
||||
return true;
|
||||
}
|
||||
Predicate<Card> flyingOrReach = Predicates.or(CardPredicates.hasKeyword("Flying"), CardPredicates.hasKeyword("Reach"));
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| card.getNetCombatDamage() <= 0 || !Iterables.any(cardsCanBlock, Predicates.not(flyingOrReach))) {
|
||||
return false;
|
||||
@@ -447,7 +457,7 @@ public class AbilityFactoryPump {
|
||||
&& CombatUtil.lifeInDanger(ai, Singletons.getModel().getGame().getCombat())) {
|
||||
return true;
|
||||
}
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| card.getNetCombatDamage() <= 0
|
||||
|| CardLists.getNotKeyword(cardsCanBlock, "Horsemanship").isEmpty()) {
|
||||
@@ -474,7 +484,7 @@ public class AbilityFactoryPump {
|
||||
}
|
||||
}
|
||||
} else if (ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
||||
&& CombatUtil.canAttack(card)) {
|
||||
&& CombatUtil.canAttack(card, opp)) {
|
||||
List<Card> blockers = opp.getCreaturesInPlay();
|
||||
for (Card blocker : blockers) {
|
||||
if (CombatUtil.canBlock(card, blocker, combat)
|
||||
@@ -485,32 +495,32 @@ public class AbilityFactoryPump {
|
||||
}
|
||||
return false;
|
||||
} else if (combatRelevant) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)
|
||||
|| (opp.getCreaturesInPlay().size() < 1)
|
||||
|| cardsCanBlock.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Double Strike")) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| card.getNetCombatDamage() <= 0
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.startsWith("Rampage")) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| cardsCanBlock.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.startsWith("Flanking")) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| CardLists.getNotKeyword(cardsCanBlock, "Flanking").isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.startsWith("Trample")) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| !CombatUtil.canBeBlocked(card)
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| cardsCanBlock.isEmpty()
|
||||
@@ -525,7 +535,7 @@ public class AbilityFactoryPump {
|
||||
return true;
|
||||
}
|
||||
if ((ph.isPlayerTurn(opp))
|
||||
|| !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
|| !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
|
||||
return false;
|
||||
}
|
||||
@@ -548,7 +558,7 @@ public class AbilityFactoryPump {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Vigilance")) {
|
||||
if (ph.isPlayerTurn(opp) || !CombatUtil.canAttack(card)
|
||||
if (ph.isPlayerTurn(opp) || !CombatUtil.canAttack(card, opp)
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
||||
|| CardLists.getNotKeyword(opp.getCreaturesInPlay(), "Defender").size() < 1) {
|
||||
return false;
|
||||
@@ -584,7 +594,7 @@ public class AbilityFactoryPump {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Islandwalk")) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| card.getNetCombatDamage() <= 0
|
||||
|| CardLists.getType(opp.getLandsInPlay(), "Island").isEmpty()
|
||||
@@ -592,7 +602,7 @@ public class AbilityFactoryPump {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Swampwalk")) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| card.getNetCombatDamage() <= 0
|
||||
|| CardLists.getType(opp.getLandsInPlay(), "Swamp").isEmpty()
|
||||
@@ -600,7 +610,7 @@ public class AbilityFactoryPump {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Mountainwalk")) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| card.getNetCombatDamage() <= 0
|
||||
|| CardLists.getType(opp.getLandsInPlay(), "Mountain").isEmpty()
|
||||
@@ -608,7 +618,7 @@ public class AbilityFactoryPump {
|
||||
return false;
|
||||
}
|
||||
} else if (keyword.equals("Forestwalk")) {
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card) || card.isAttacking())
|
||||
if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking())
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)
|
||||
|| card.getNetCombatDamage() <= 0
|
||||
|| CardLists.getType(opp.getLandsInPlay(), "Forest").isEmpty()
|
||||
@@ -1810,7 +1820,7 @@ public class AbilityFactoryPump {
|
||||
if (phase.equals(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) && c.isAttacking()) {
|
||||
return true;
|
||||
}
|
||||
if (phase.isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) && CombatUtil.canAttack(c)) {
|
||||
if (phase.isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) && CombatUtil.canAttack(c, opp)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -291,7 +291,7 @@ public class SpellPermanent extends Spell {
|
||||
}
|
||||
// Wait for Main2 if possible
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.MAIN1)
|
||||
&& !ComputerUtil.castPermanentInMain1(this, ai)) {
|
||||
&& !ComputerUtil.castPermanentInMain1(ai, this)) {
|
||||
return false;
|
||||
}
|
||||
// save cards with flash for surprise blocking
|
||||
|
||||
@@ -3,7 +3,6 @@ package forge.card.trigger;
|
||||
import java.util.HashMap;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.TriggerReplacementBase;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
/**
|
||||
|
||||
@@ -546,7 +546,7 @@ public class Combat {
|
||||
*/
|
||||
public Player getDefendingPlayerRelatedTo(final Card source) {
|
||||
|
||||
Player defender = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().getOpponent();
|
||||
Player defender = getDefenderPlayerByAttacker(source);
|
||||
Card attacker = source;
|
||||
if (source.isAura()) {
|
||||
attacker = source.getEnchantingCard();
|
||||
|
||||
@@ -810,32 +810,9 @@ public class CombatUtil {
|
||||
if (cntAttackers > 0 && Singletons.getModel().getGame().isCardInPlay("Dueling Grounds")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Player defender = c.getController().getOpponent();
|
||||
if (combat != null) {
|
||||
final GameEntity def = combat.getDefender();
|
||||
if (def instanceof Player) {
|
||||
defender = (Player) def;
|
||||
} else {
|
||||
defender = ((Card) def).getController();
|
||||
}
|
||||
}
|
||||
|
||||
return CombatUtil.canAttack(c, defender);
|
||||
}
|
||||
|
||||
// can a creature attack at the moment?
|
||||
/**
|
||||
* <p>
|
||||
* canAttack.
|
||||
* </p>
|
||||
*
|
||||
* @param c
|
||||
* a {@link forge.Card} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean canAttack(final Card c) {
|
||||
return canAttack(c, c.getController().getOpponent());
|
||||
final GameEntity def = combat.getDefender();
|
||||
return CombatUtil.canAttack(c, def instanceof Player ? (Player) def : ((Card) def).getController());
|
||||
}
|
||||
|
||||
// can a creature attack at the moment?
|
||||
|
||||
@@ -1768,8 +1768,7 @@ public class ComputerUtil {
|
||||
*/
|
||||
public static Combat getAttackers(final Player ai) {
|
||||
final Player opp = ai.getOpponent();
|
||||
final ComputerUtilAttack att = new ComputerUtilAttack(ai.getCardsIn(ZoneType.Battlefield),
|
||||
opp.getCardsIn(ZoneType.Battlefield));
|
||||
final ComputerUtilAttack att = new ComputerUtilAttack(ai, opp);
|
||||
|
||||
return att.getAttackers(ai, opp);
|
||||
}
|
||||
@@ -2040,7 +2039,7 @@ public class ComputerUtil {
|
||||
* a SpellAbility object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean castPermanentInMain1(final SpellAbility sa, final Player ai) {
|
||||
public static boolean castPermanentInMain1(final Player ai, final SpellAbility sa) {
|
||||
final Card card = sa.getSourceCard();
|
||||
if (card.getSVar("PlayMain1").equals("TRUE")) {
|
||||
return true;
|
||||
@@ -2061,7 +2060,7 @@ public class ComputerUtil {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (card.isEquipment() && buffedcard.isCreature() && CombatUtil.canAttack(buffedcard)) {
|
||||
if (card.isEquipment() && buffedcard.isCreature() && CombatUtil.canAttack(buffedcard, ai.getOpponent())) {
|
||||
return true;
|
||||
}
|
||||
if (card.isCreature() && buffedcard.hasKeyword("Soulbond") && !buffedcard.isPaired()) {
|
||||
|
||||
@@ -26,7 +26,6 @@ import com.google.common.base.Predicate;
|
||||
import forge.Card;
|
||||
|
||||
import forge.CardLists;
|
||||
import forge.CardPredicates;
|
||||
import forge.Counters;
|
||||
import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
@@ -74,15 +73,16 @@ public class ComputerUtilAttack {
|
||||
* @param possibleBlockers
|
||||
* a {@link forge.CardList} object.
|
||||
*/
|
||||
public ComputerUtilAttack(final List<Card> possibleAttackers, final List<Card> possibleBlockers) {
|
||||
this.humanList = new ArrayList<Card>(possibleBlockers);
|
||||
this.humanList = CardLists.filter(this.humanList, CardPredicates.Presets.CREATURES);
|
||||
public ComputerUtilAttack(final Player ai, final Player human) {
|
||||
this.humanList = human.getCreaturesInPlay();
|
||||
this.computerList = ai.getCreaturesInPlay();
|
||||
|
||||
this.computerList = new ArrayList<Card>(possibleAttackers);
|
||||
this.computerList = CardLists.filter(this.computerList, CardPredicates.Presets.CREATURES);
|
||||
|
||||
this.attackers = this.getPossibleAttackers(possibleAttackers);
|
||||
this.blockers = this.getPossibleBlockers(possibleBlockers, this.attackers);
|
||||
this.attackers = new ArrayList<Card>();
|
||||
for(Card c : computerList)
|
||||
if (CombatUtil.canAttack(c, human))
|
||||
attackers.add(c);
|
||||
|
||||
this.blockers = this.getPossibleBlockers(humanList, this.attackers);
|
||||
} // constructor
|
||||
|
||||
/**
|
||||
@@ -157,26 +157,6 @@ public class ComputerUtilAttack {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPossibleAttackers.
|
||||
* </p>
|
||||
*
|
||||
* @param in
|
||||
* a {@link forge.CardList} object.
|
||||
* @return a {@link forge.CardList} object.
|
||||
*/
|
||||
public final List<Card> getPossibleAttackers(final List<Card> in) {
|
||||
List<Card> list = new ArrayList<Card>(in);
|
||||
list = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return CombatUtil.canAttack(c);
|
||||
}
|
||||
});
|
||||
return list;
|
||||
} // getPossibleAttackers()
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPossibleBlockers.
|
||||
|
||||
@@ -164,6 +164,7 @@ public class QuestWinLose extends ControlWinLose {
|
||||
// TODO: We don't have a enum for difficulty?
|
||||
int difficulty = qData.getAchievements().getDifficulty();
|
||||
|
||||
|
||||
final int wins = qData.getAchievements().getWin();
|
||||
// Win case
|
||||
if (this.wonMatch) {
|
||||
@@ -189,17 +190,17 @@ public class QuestWinLose extends ControlWinLose {
|
||||
if ((wins > 0) && ((wins % 80) == 0)) {
|
||||
this.awardJackpot();
|
||||
}
|
||||
|
||||
// Unlock new sets?
|
||||
if (wins % 50 == 49) {
|
||||
unlockSets();
|
||||
}
|
||||
}
|
||||
// Lose case
|
||||
else {
|
||||
this.penalizeLoss();
|
||||
}
|
||||
|
||||
// Unlock new sets?
|
||||
if (this.wonMatch && wins % 50 == 49) {
|
||||
unlockSets();
|
||||
}
|
||||
|
||||
// Grant booster on a win, or on a loss in easy mode
|
||||
if (this.wonMatch || difficulty == 0) {
|
||||
final int outcome = this.wonMatch ? wins : qData.getAchievements().getLost();
|
||||
|
||||
Reference in New Issue
Block a user