mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
Compare commits
1 Commits
exiledWith
...
mayPlayAlt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33633ebd50 |
@@ -17,26 +17,16 @@
|
||||
*/
|
||||
package forge.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ability.AnimateAi;
|
||||
import forge.card.CardTypeView;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.ability.effects.ProtectEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.combat.GlobalAttackRestrictions;
|
||||
@@ -53,6 +43,9 @@ import forge.util.MyRandom;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.collect.FCollectionView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
//doesHumanAttackAndWin() uses the global variable AllZone.getComputerPlayer()
|
||||
/**
|
||||
@@ -76,7 +69,6 @@ public class AiAttackController {
|
||||
private Player defendingOpponent;
|
||||
|
||||
private int aiAggression = 0; // added by Masher, how aggressive the ai is attack will be depending on circumstances
|
||||
private final boolean nextTurn;
|
||||
|
||||
|
||||
/**
|
||||
@@ -86,24 +78,18 @@ public class AiAttackController {
|
||||
*
|
||||
*/
|
||||
public AiAttackController(final Player ai) {
|
||||
this(ai, false);
|
||||
} // constructor
|
||||
|
||||
public AiAttackController(final Player ai, boolean nextTurn) {
|
||||
this.ai = ai;
|
||||
this.defendingOpponent = choosePreferredDefenderPlayer();
|
||||
this.defendingOpponent = choosePreferredDefenderPlayer();
|
||||
this.oppList = getOpponentCreatures(this.defendingOpponent);
|
||||
this.myList = ai.getCreaturesInPlay();
|
||||
this.attackers = new ArrayList<>();
|
||||
for (Card c : myList) {
|
||||
if (nextTurn && CombatUtil.canAttackNextTurn(c, this.defendingOpponent) ||
|
||||
CombatUtil.canAttack(c, this.defendingOpponent)) {
|
||||
if (CombatUtil.canAttack(c, this.defendingOpponent)) {
|
||||
attackers.add(c);
|
||||
}
|
||||
}
|
||||
this.blockers = getPossibleBlockers(oppList, this.attackers);
|
||||
this.nextTurn = nextTurn;
|
||||
} // overloaded constructor to evaluate attackers that should attack next turn
|
||||
} // constructor
|
||||
|
||||
public AiAttackController(final Player ai, Card attacker) {
|
||||
this.ai = ai;
|
||||
@@ -115,7 +101,6 @@ public class AiAttackController {
|
||||
attackers.add(attacker);
|
||||
}
|
||||
this.blockers = getPossibleBlockers(oppList, this.attackers);
|
||||
this.nextTurn = false;
|
||||
} // overloaded constructor to evaluate single specified attacker
|
||||
|
||||
public static List<Card> getOpponentCreatures(final Player defender) {
|
||||
@@ -147,14 +132,6 @@ public class AiAttackController {
|
||||
this.oppList.remove(blocker);
|
||||
}
|
||||
|
||||
private boolean canAttackWrapper(final Card attacker, final GameEntity defender) {
|
||||
if (nextTurn) {
|
||||
return CombatUtil.canAttackNextTurn(attacker, defender);
|
||||
} else {
|
||||
return CombatUtil.canAttack(attacker, defender);
|
||||
}
|
||||
}
|
||||
|
||||
/** Choose opponent for AI to attack here. Expand as necessary. */
|
||||
private Player choosePreferredDefenderPlayer() {
|
||||
Player defender = ai.getWeakestOpponent(); //Gets opponent with the least life
|
||||
@@ -705,8 +682,6 @@ public class AiAttackController {
|
||||
final boolean bAssault = this.doAssault(ai);
|
||||
// TODO: detect Lightmine Field by presence of a card with a specific trigger
|
||||
final boolean lightmineField = ComputerUtilCard.isPresentOnBattlefield(ai.getGame(), "Lightmine Field");
|
||||
// TODO: detect Season of the Witch by presence of a card with a specific trigger
|
||||
final boolean seasonOfTheWitch = ComputerUtilCard.isPresentOnBattlefield(ai.getGame(), "Season of the Witch");
|
||||
|
||||
// Determine who will be attacked
|
||||
GameEntity defender = this.chooseDefender(combat, bAssault);
|
||||
@@ -727,46 +702,39 @@ public class AiAttackController {
|
||||
|
||||
// Attackers that don't really have a choice
|
||||
int numForcedAttackers = 0;
|
||||
// nextTurn is now only used by effect from Oracle en-Vec, which can skip check must attack,
|
||||
// because creatures not chosen can't attack.
|
||||
if (!nextTurn) {
|
||||
for (final Card attacker : this.attackers) {
|
||||
if (!CombatUtil.canAttack(attacker, defender)) {
|
||||
attackersLeft.remove(attacker);
|
||||
continue;
|
||||
}
|
||||
boolean mustAttack = false;
|
||||
if (attacker.isGoaded()) {
|
||||
mustAttack = true;
|
||||
} else if (attacker.getSVar("MustAttack").equals("True")) {
|
||||
mustAttack = true;
|
||||
} else if (attacker.hasSVar("EndOfTurnLeavePlay")
|
||||
&& isEffectiveAttacker(ai, attacker, combat)) {
|
||||
mustAttack = true;
|
||||
} else if (seasonOfTheWitch) {
|
||||
// TODO: if there are other ways to tap this creature (like mana creature), then don't need to attack
|
||||
mustAttack = true;
|
||||
} else {
|
||||
for (KeywordInterface inst : attacker.getKeywords()) {
|
||||
String s = inst.getOriginal();
|
||||
if (s.equals("CARDNAME attacks each turn if able.")
|
||||
|| s.startsWith("CARDNAME attacks specific player each combat if able")
|
||||
|| s.equals("CARDNAME attacks each combat if able.")) {
|
||||
mustAttack = true;
|
||||
break;
|
||||
}
|
||||
for (final Card attacker : this.attackers) {
|
||||
if (!CombatUtil.canAttack(attacker, defender)) {
|
||||
attackersLeft.remove(attacker);
|
||||
continue;
|
||||
}
|
||||
boolean mustAttack = false;
|
||||
if (attacker.isGoaded()) {
|
||||
mustAttack = true;
|
||||
} else if (attacker.getSVar("MustAttack").equals("True")) {
|
||||
mustAttack = true;
|
||||
} else if (attacker.hasSVar("EndOfTurnLeavePlay")
|
||||
&& isEffectiveAttacker(ai, attacker, combat)) {
|
||||
mustAttack = true;
|
||||
} else {
|
||||
for (KeywordInterface inst : attacker.getKeywords()) {
|
||||
String s = inst.getOriginal();
|
||||
if (s.equals("CARDNAME attacks each turn if able.")
|
||||
|| s.startsWith("CARDNAME attacks specific player each combat if able")
|
||||
|| s.equals("CARDNAME attacks each combat if able.")) {
|
||||
mustAttack = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mustAttack || attacker.getController().getMustAttackEntity() != null || attacker.getController().getMustAttackEntityThisTurn() != null) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
attackersLeft.remove(attacker);
|
||||
numForcedAttackers++;
|
||||
}
|
||||
}
|
||||
if (attackersLeft.isEmpty()) {
|
||||
return;
|
||||
if (mustAttack || attacker.getController().getMustAttackEntity() != null || attacker.getController().getMustAttackEntityThisTurn() != null) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
attackersLeft.remove(attacker);
|
||||
numForcedAttackers++;
|
||||
}
|
||||
}
|
||||
if (attackersLeft.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Lightmine Field: make sure the AI doesn't wipe out its own creatures
|
||||
if (lightmineField) {
|
||||
@@ -787,7 +755,7 @@ public class AiAttackController {
|
||||
if (attackMax != -1 && combat.getAttackers().size() >= attackMax)
|
||||
return;
|
||||
|
||||
if (canAttackWrapper(attacker, defender) && this.isEffectiveAttacker(ai, attacker, combat)) {
|
||||
if (CombatUtil.canAttack(attacker, defender) && this.isEffectiveAttacker(ai, attacker, combat)) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
}
|
||||
}
|
||||
@@ -828,7 +796,7 @@ public class AiAttackController {
|
||||
System.out.println("Exalted");
|
||||
this.aiAggression = 6;
|
||||
for (Card attacker : this.attackers) {
|
||||
if (canAttackWrapper(attacker, defender) && this.shouldAttack(ai, attacker, this.blockers, combat)) {
|
||||
if (CombatUtil.canAttack(attacker, defender) && this.shouldAttack(ai, attacker, this.blockers, combat)) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
return;
|
||||
}
|
||||
@@ -844,7 +812,7 @@ public class AiAttackController {
|
||||
// reached max, breakup
|
||||
if (attackMax != -1 && combat.getAttackers().size() >= attackMax)
|
||||
break;
|
||||
if (canAttackWrapper(attacker, defender) && this.shouldAttack(ai, attacker, this.blockers, combat)) {
|
||||
if (CombatUtil.canAttack(attacker, defender) && this.shouldAttack(ai, attacker, this.blockers, combat)) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
}
|
||||
}
|
||||
@@ -1085,7 +1053,7 @@ public class AiAttackController {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.shouldAttack(ai, attacker, this.blockers, combat) && canAttackWrapper(attacker, defender)) {
|
||||
if (this.shouldAttack(ai, attacker, this.blockers, combat) && CombatUtil.canAttack(attacker, defender)) {
|
||||
combat.addAttacker(attacker, defender);
|
||||
// check if attackers are enough to finish the attacked planeswalker
|
||||
if (defender instanceof Card) {
|
||||
|
||||
@@ -17,23 +17,12 @@
|
||||
*/
|
||||
package forge.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.card.CardStateName;
|
||||
import forge.game.CardTraitBase;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.keyword.Keyword;
|
||||
@@ -44,6 +33,8 @@ import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.collect.FCollectionView;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -272,14 +263,14 @@ public class AiBlockController {
|
||||
|
||||
if (mode == TriggerType.DamageDone) {
|
||||
if ((!trigParams.containsKey("ValidSource")
|
||||
|| trigger.matchesValid(attacker, trigParams.get("ValidSource").split(",")))
|
||||
|| CardTraitBase.matchesValid(attacker, trigParams.get("ValidSource").split(","), attacker))
|
||||
&& attacker.getNetCombatDamage() > 0
|
||||
&& (!trigParams.containsKey("ValidTarget")
|
||||
|| trigger.matchesValid(combat.getDefenderByAttacker(attacker), trigParams.get("ValidTarget").split(",")))) {
|
||||
|| CardTraitBase.matchesValid(combat.getDefenderByAttacker(attacker), trigParams.get("ValidTarget").split(","), attacker))) {
|
||||
value += 50;
|
||||
}
|
||||
} else if (mode == TriggerType.AttackerUnblocked) {
|
||||
if (trigger.matchesValid(attacker, trigParams.get("ValidCard").split(","))) {
|
||||
if (CardTraitBase.matchesValid(attacker, trigParams.get("ValidCard").split(","), attacker)) {
|
||||
value += 50;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
package forge.ai;
|
||||
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AiCardMemory class.
|
||||
|
||||
@@ -17,19 +17,11 @@
|
||||
*/
|
||||
package forge.ai;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ability.ChangeZoneAi;
|
||||
import forge.ai.ability.ExploreAi;
|
||||
import forge.ai.simulation.SpellAbilityPicker;
|
||||
@@ -38,38 +30,16 @@ import forge.card.mana.ManaCost;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.game.CardTraitBase;
|
||||
import forge.game.CardTraitPredicates;
|
||||
import forge.game.Direction;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameActionUtil;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.*;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.ability.SpellApiBased;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPlayOption;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Accessors;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostAdjustment;
|
||||
import forge.game.cost.CostDiscard;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostPayEnergy;
|
||||
import forge.game.cost.CostPayLife;
|
||||
import forge.game.cost.CostPutCounter;
|
||||
import forge.game.cost.CostRemoveCounter;
|
||||
import forge.game.cost.CostSacrifice;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.mana.ManaCostBeingPaid;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -78,15 +48,7 @@ import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.replacement.ReplaceMoved;
|
||||
import forge.game.replacement.ReplacementEffect;
|
||||
import forge.game.replacement.ReplacementType;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.LandAbility;
|
||||
import forge.game.spellability.OptionalCost;
|
||||
import forge.game.spellability.OptionalCostValue;
|
||||
import forge.game.spellability.Spell;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityCondition;
|
||||
import forge.game.spellability.SpellAbilityPredicates;
|
||||
import forge.game.spellability.SpellPermanent;
|
||||
import forge.game.spellability.*;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.game.trigger.Trigger;
|
||||
import forge.game.trigger.TriggerType;
|
||||
@@ -94,13 +56,16 @@ import forge.game.trigger.WrappedAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.item.PaperCard;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.ComparatorUtil;
|
||||
import forge.util.Expressions;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.ComparatorUtil;
|
||||
import forge.util.collect.FCollectionView;
|
||||
import io.sentry.Sentry;
|
||||
import io.sentry.event.BreadcrumbBuilder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AiController class.
|
||||
@@ -114,7 +79,6 @@ public class AiController {
|
||||
private final Game game;
|
||||
private final AiCardMemory memory;
|
||||
private Combat predictedCombat;
|
||||
private Combat predictedCombatNextTurn;
|
||||
private boolean cheatShuffle;
|
||||
private boolean useSimulation;
|
||||
private SpellAbilityPicker simPicker;
|
||||
@@ -159,15 +123,6 @@ public class AiController {
|
||||
return predictedCombat;
|
||||
}
|
||||
|
||||
public Combat getPredictedCombatNextTurn() {
|
||||
if (predictedCombatNextTurn == null) {
|
||||
AiAttackController aiAtk = new AiAttackController(player, true);
|
||||
predictedCombatNextTurn = new Combat(player);
|
||||
aiAtk.declareAttackers(predictedCombatNextTurn);
|
||||
}
|
||||
return predictedCombatNextTurn;
|
||||
}
|
||||
|
||||
public AiController(final Player computerPlayer, final Game game0) {
|
||||
player = computerPlayer;
|
||||
game = game0;
|
||||
@@ -1045,7 +1000,7 @@ public class AiController {
|
||||
}
|
||||
// move snap-casted spells to front
|
||||
if (source.isInZone(ZoneType.Graveyard)) {
|
||||
if (sa.getMayPlay() != null && source.mayPlay(sa.getMayPlay()) != null) {
|
||||
if (!sa.getMayPlayList().isEmpty()) {
|
||||
p += 50;
|
||||
}
|
||||
}
|
||||
@@ -1120,8 +1075,9 @@ public class AiController {
|
||||
CardCollection discards = CardLists.filter(player.getCardsIn(ZoneType.Hand), CardPredicates.hasCMC(cmc));
|
||||
if (discards.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return new CardCollection(ComputerUtilCard.getWorstAI(discards));
|
||||
}
|
||||
return new CardCollection(ComputerUtilCard.getWorstAI(discards));
|
||||
}
|
||||
|
||||
if (sa.hasParam("AnyNumber")) {
|
||||
@@ -1408,8 +1364,6 @@ public class AiController {
|
||||
// Reset cached predicted combat, as it may be stale. It will be
|
||||
// re-created if needed and used for any AI logic that needs it.
|
||||
predictedCombat = null;
|
||||
// Also reset predicted combat for next turn here
|
||||
predictedCombatNextTurn = null;
|
||||
|
||||
// Reset priority mana reservation that's meant to work for one spell only
|
||||
AiCardMemory.clearMemorySet(player, AiCardMemory.MemorySet.HELD_MANA_SOURCES_FOR_NEXT_SPELL);
|
||||
@@ -1441,22 +1395,8 @@ public class AiController {
|
||||
if (ComputerUtil.getDamageFromETB(player, land) < player.getLife() || !player.canLoseLife()
|
||||
|| player.cantLoseForZeroOrLessLife() ) {
|
||||
if (!game.getPhaseHandler().is(PhaseType.MAIN1) || !isSafeToHoldLandDropForMain2(land)) {
|
||||
final List<SpellAbility> abilities = Lists.newArrayList();
|
||||
final List<SpellAbility> abilities = GameActionUtil.getAlternativeCosts(land.getFirstSpellAbility(), player);
|
||||
|
||||
LandAbility la = new LandAbility(land, player, null);
|
||||
la.setCardState(land.getCurrentState());
|
||||
if (la.canPlay()) {
|
||||
abilities.add(la);
|
||||
}
|
||||
|
||||
// add mayPlay option
|
||||
for (CardPlayOption o : land.mayPlay(player)) {
|
||||
la = new LandAbility(land, player, o.getAbility());
|
||||
la.setCardState(land.getCurrentState());
|
||||
if (la.canPlay()) {
|
||||
abilities.add(la);
|
||||
}
|
||||
}
|
||||
if (!abilities.isEmpty()) {
|
||||
return abilities;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package forge.ai;
|
||||
|
||||
import static forge.ai.ComputerUtilCard.getBestCreatureAI;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.CardType;
|
||||
@@ -22,46 +21,18 @@ import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.cost.CostAddMana;
|
||||
import forge.game.cost.CostChooseCreatureType;
|
||||
import forge.game.cost.CostDamage;
|
||||
import forge.game.cost.CostDecisionMakerBase;
|
||||
import forge.game.cost.CostDiscard;
|
||||
import forge.game.cost.CostDraw;
|
||||
import forge.game.cost.CostExert;
|
||||
import forge.game.cost.CostExile;
|
||||
import forge.game.cost.CostExileFromStack;
|
||||
import forge.game.cost.CostExiledMoveToGrave;
|
||||
import forge.game.cost.CostFlipCoin;
|
||||
import forge.game.cost.CostGainControl;
|
||||
import forge.game.cost.CostGainLife;
|
||||
import forge.game.cost.CostMill;
|
||||
import forge.game.cost.CostPartMana;
|
||||
import forge.game.cost.CostPayEnergy;
|
||||
import forge.game.cost.CostPayLife;
|
||||
import forge.game.cost.CostPutCardToLib;
|
||||
import forge.game.cost.CostPutCounter;
|
||||
import forge.game.cost.CostRemoveAnyCounter;
|
||||
import forge.game.cost.CostRemoveCounter;
|
||||
import forge.game.cost.CostReturn;
|
||||
import forge.game.cost.CostReveal;
|
||||
import forge.game.cost.CostSacrifice;
|
||||
import forge.game.cost.CostTap;
|
||||
import forge.game.cost.CostTapType;
|
||||
import forge.game.cost.CostUnattach;
|
||||
import forge.game.cost.CostUntap;
|
||||
import forge.game.cost.CostUntapType;
|
||||
import forge.game.cost.PaymentDecision;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.collect.FCollectionView;
|
||||
|
||||
import static forge.ai.ComputerUtilCard.getBestCreatureAI;
|
||||
|
||||
public class AiCostDecision extends CostDecisionMakerBase {
|
||||
private final SpellAbility ability;
|
||||
private final Card source;
|
||||
@@ -92,15 +63,9 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
|
||||
@Override
|
||||
public PaymentDecision visit(CostChooseCreatureType cost) {
|
||||
Integer amount = cost.convertAmount();
|
||||
Iterable<String> choices = player.getController().chooseSomeType(
|
||||
Localizer.getInstance().getMessage("lblCreature"), ability, amount, amount, Lists.newArrayList(CardType.getAllCreatureTypes()));
|
||||
|
||||
if (choices == null || Iterables.isEmpty(choices)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return PaymentDecision.types(choices);
|
||||
String choice = player.getController().chooseSomeType("Creature", ability, CardType.getAllCreatureTypes(),
|
||||
Lists.newArrayList());
|
||||
return PaymentDecision.type(choice);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,7 +88,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
}
|
||||
else if (type.equals("Hand")) {
|
||||
if (hand.size() > 1 && ability.getActivatingPlayer() != null) {
|
||||
hand = ability.getActivatingPlayer().getController().orderMoveToZoneList(hand, ZoneType.Graveyard, ability);
|
||||
hand = ability.getActivatingPlayer().getController().orderMoveToZoneList(hand, ZoneType.Graveyard);
|
||||
}
|
||||
return PaymentDecision.card(hand);
|
||||
}
|
||||
@@ -139,7 +104,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
if (type.equals("Random")) {
|
||||
CardCollectionView randomSubset = CardLists.getRandomSubList(new CardCollection(hand), c);
|
||||
if (randomSubset.size() > 1 && ability.getActivatingPlayer() != null) {
|
||||
randomSubset = ability.getActivatingPlayer().getController().orderMoveToZoneList(randomSubset, ZoneType.Graveyard, ability);
|
||||
randomSubset = ability.getActivatingPlayer().getController().orderMoveToZoneList(randomSubset, ZoneType.Graveyard);
|
||||
}
|
||||
return PaymentDecision.card(randomSubset);
|
||||
}
|
||||
@@ -220,7 +185,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
CardCollectionView chosen = ComputerUtil.chooseExileFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c, ability);
|
||||
CardCollectionView chosen = ComputerUtil.chooseExileFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c);
|
||||
return null == chosen ? null : PaymentDecision.card(chosen);
|
||||
}
|
||||
}
|
||||
@@ -427,7 +392,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
chosen = chosen.subList(0, c);
|
||||
}
|
||||
else {
|
||||
chosen = ComputerUtil.choosePutToLibraryFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c, ability);
|
||||
chosen = ComputerUtil.choosePutToLibraryFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c);
|
||||
}
|
||||
return chosen.isEmpty() ? null : PaymentDecision.card(chosen);
|
||||
}
|
||||
@@ -499,7 +464,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
type = TextUtil.fastReplace(type, "+withTotalPowerGE", "");
|
||||
totap = ComputerUtil.chooseTapTypeAccumulatePower(player, type, ability, !cost.canTapSource, Integer.parseInt(totalP), exclude);
|
||||
} else {
|
||||
totap = ComputerUtil.chooseTapType(player, type, source, !cost.canTapSource, c, exclude, ability);
|
||||
totap = ComputerUtil.chooseTapType(player, type, source, !cost.canTapSource, c, exclude);
|
||||
}
|
||||
|
||||
if (totap == null) {
|
||||
@@ -516,9 +481,6 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
if (cost.payCostFromSource()) {
|
||||
return PaymentDecision.card(source);
|
||||
}
|
||||
if (cost.getType().equals("OriginalHost")) {
|
||||
return PaymentDecision.card(ability.getHostCard());
|
||||
}
|
||||
if (cost.getAmount().equals("All")) {
|
||||
// Does the AI want to use Sacrifice All?
|
||||
return null;
|
||||
@@ -545,7 +507,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
|
||||
}
|
||||
|
||||
CardCollectionView res = ComputerUtil.chooseReturnType(player, cost.getType(), source, ability.getTargetCard(), c, ability);
|
||||
CardCollectionView res = ComputerUtil.chooseReturnType(player, cost.getType(), source, ability.getTargetCard(), c);
|
||||
return res.isEmpty() ? null : PaymentDecision.card(res);
|
||||
}
|
||||
|
||||
@@ -607,7 +569,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
public PaymentDecision visit(CostRemoveAnyCounter cost) {
|
||||
final String amount = cost.getAmount();
|
||||
final int c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
final Card originalHost = ability.getOriginalOrHost();
|
||||
final Card originalHost = ObjectUtils.defaultIfNull(ability.getOriginalHost(), source);
|
||||
|
||||
if (c <= 0) {
|
||||
return null;
|
||||
@@ -863,7 +825,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
}
|
||||
|
||||
CardCollectionView list = ComputerUtil.chooseUntapType(player, cost.getType(), source, cost.canUntapSource, c, ability);
|
||||
CardCollectionView list = ComputerUtil.chooseUntapType(player, cost.getType(), source, cost.canUntapSource, c);
|
||||
|
||||
if (list == null) {
|
||||
System.out.println("Couldn't find a valid card to untap for: " + source.getName());
|
||||
|
||||
@@ -17,19 +17,19 @@
|
||||
*/
|
||||
package forge.ai;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.FileUtil;
|
||||
|
||||
import forge.util.TextUtil;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
/**
|
||||
* Holds default AI personality profile values in an enum.
|
||||
* Loads profile from the given text file when setProfile is called.
|
||||
|
||||
@@ -17,22 +17,12 @@
|
||||
*/
|
||||
package forge.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import forge.ai.ability.ChooseGenericEffectAi;
|
||||
import forge.ai.ability.ProtectAi;
|
||||
import forge.ai.ability.TokenAi;
|
||||
@@ -40,33 +30,16 @@ import forge.card.CardStateName;
|
||||
import forge.card.CardType;
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.CardTraitPredicates;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameActionUtil;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.GameType;
|
||||
import forge.game.*;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.ability.effects.CharmEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardState;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostDiscard;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostPayment;
|
||||
import forge.game.cost.CostPutCounter;
|
||||
import forge.game.cost.CostSacrifice;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -88,6 +61,9 @@ import forge.util.Aggregates;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.collect.FCollection;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
@@ -291,14 +267,14 @@ public class ComputerUtil {
|
||||
newSA.setHostCard(game.getAction().moveToStack(source, sa));
|
||||
|
||||
if (newSA.getApi() == ApiType.Charm && !newSA.isWrapper()) {
|
||||
if (!CharmEffect.makeChoices(newSA)) {
|
||||
if (!CharmEffect.makeChoices(sa)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final CostPayment pay = new CostPayment(newSA.getPayCosts(), newSA);
|
||||
pay.payComputerCosts(new AiCostDecision(ai, newSA));
|
||||
pay.payComputerCosts(new AiCostDecision(ai, sa));
|
||||
|
||||
game.getStack().add(newSA);
|
||||
return true;
|
||||
@@ -539,7 +515,7 @@ public class ComputerUtil {
|
||||
|
||||
public static CardCollection chooseSacrificeType(final Player ai, final String type, final SpellAbility ability, final Card target, final int amount) {
|
||||
final Card source = ability.getHostCard();
|
||||
CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), source.getController(), source, ability);
|
||||
CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), source.getController(), source, null);
|
||||
|
||||
typeList = CardLists.filter(typeList, CardPredicates.canBeSacrificedBy(ability));
|
||||
|
||||
@@ -570,8 +546,8 @@ public class ComputerUtil {
|
||||
}
|
||||
|
||||
public static CardCollection chooseExileFrom(final Player ai, final ZoneType zone, final String type, final Card activate,
|
||||
final Card target, final int amount, SpellAbility sa) {
|
||||
CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(zone), type.split(";"), activate.getController(), activate, sa);
|
||||
final Card target, final int amount) {
|
||||
CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(zone), type.split(";"), activate.getController(), activate, null);
|
||||
|
||||
if ((target != null) && target.getController() == ai) {
|
||||
typeList.remove(target); // don't exile the card we're pumping
|
||||
@@ -591,8 +567,8 @@ public class ComputerUtil {
|
||||
}
|
||||
|
||||
public static CardCollection choosePutToLibraryFrom(final Player ai, final ZoneType zone, final String type, final Card activate,
|
||||
final Card target, final int amount, SpellAbility sa) {
|
||||
CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(zone), type.split(";"), activate.getController(), activate, sa);
|
||||
final Card target, final int amount) {
|
||||
CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(zone), type.split(";"), activate.getController(), activate, null);
|
||||
|
||||
if ((target != null) && target.getController() == ai) {
|
||||
typeList.remove(target); // don't move the card we're pumping
|
||||
@@ -615,11 +591,14 @@ public class ComputerUtil {
|
||||
return list;
|
||||
}
|
||||
|
||||
public static CardCollection chooseTapType(final Player ai, final String type, final Card activate, final boolean tap, final int amount, final CardCollectionView exclude, SpellAbility sa) {
|
||||
public static CardCollection chooseTapType(final Player ai, final String type, final Card activate, final boolean tap, final int amount) {
|
||||
return chooseTapType(ai, type, activate, tap, amount, CardCollection.EMPTY);
|
||||
}
|
||||
public static CardCollection chooseTapType(final Player ai, final String type, final Card activate, final boolean tap, final int amount, final CardCollectionView exclude) {
|
||||
CardCollection all = new CardCollection(ai.getCardsIn(ZoneType.Battlefield));
|
||||
all.removeAll(exclude);
|
||||
CardCollection typeList =
|
||||
CardLists.getValidCards(all, type.split(";"), activate.getController(), activate, sa);
|
||||
CardLists.getValidCards(all, type.split(";"), activate.getController(), activate, null);
|
||||
|
||||
// is this needed?
|
||||
typeList = CardLists.filter(typeList, Presets.UNTAPPED);
|
||||
@@ -692,9 +671,9 @@ public class ComputerUtil {
|
||||
return tapList;
|
||||
}
|
||||
|
||||
public static CardCollection chooseUntapType(final Player ai, final String type, final Card activate, final boolean untap, final int amount, SpellAbility sa) {
|
||||
public static CardCollection chooseUntapType(final Player ai, final String type, final Card activate, final boolean untap, final int amount) {
|
||||
CardCollection typeList =
|
||||
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), activate.getController(), activate, sa);
|
||||
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), activate.getController(), activate, null);
|
||||
|
||||
// is this needed?
|
||||
typeList = CardLists.filter(typeList, Presets.TAPPED);
|
||||
@@ -717,9 +696,9 @@ public class ComputerUtil {
|
||||
return untapList;
|
||||
}
|
||||
|
||||
public static CardCollection chooseReturnType(final Player ai, final String type, final Card activate, final Card target, final int amount, SpellAbility sa) {
|
||||
public static CardCollection chooseReturnType(final Player ai, final String type, final Card activate, final Card target, final int amount) {
|
||||
final CardCollection typeList =
|
||||
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), activate.getController(), activate, sa);
|
||||
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), activate.getController(), activate, null);
|
||||
if ((target != null) && target.getController() == ai) {
|
||||
// don't bounce the card we're pumping
|
||||
typeList.remove(target);
|
||||
@@ -967,7 +946,7 @@ public class ComputerUtil {
|
||||
}
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
if (tgt != null) {
|
||||
if (CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), controller, sa.getHostCard(), sa).contains(card)) {
|
||||
if (CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), controller, sa.getHostCard(), null).contains(card)) {
|
||||
prevented += AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa);
|
||||
}
|
||||
|
||||
@@ -1583,8 +1562,9 @@ public class ComputerUtil {
|
||||
if (threatApi == null) {
|
||||
return threatened;
|
||||
}
|
||||
final TargetRestrictions tgt = topStack.getTargetRestrictions();
|
||||
|
||||
if (!topStack.usesTargeting()) {
|
||||
if (tgt == null) {
|
||||
if (topStack.hasParam("Defined")) {
|
||||
objects = AbilityUtils.getDefinedObjects(source, topStack.getParam("Defined"), topStack);
|
||||
} else if (topStack.hasParam("ValidCards")) {
|
||||
@@ -1681,7 +1661,7 @@ public class ComputerUtil {
|
||||
|
||||
if (saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll) {
|
||||
boolean canSave = ComputerUtilCombat.predictDamageTo(c, dmg - toughness, source, false) < ComputerUtilCombat.getDamageToKill(c);
|
||||
if ((!topStack.usesTargeting() && !grantIndestructible && !canSave)
|
||||
if ((tgt == null && !grantIndestructible && !canSave)
|
||||
|| (!grantIndestructible && !grantShroud && !canSave)) {
|
||||
continue;
|
||||
}
|
||||
@@ -1741,7 +1721,7 @@ public class ComputerUtil {
|
||||
final boolean cantSave = c.getNetToughness() + toughness <= dmg
|
||||
|| (!c.hasKeyword(Keyword.INDESTRUCTIBLE) && c.getShieldCount() == 0 && !grantIndestructible
|
||||
&& (dmg >= toughness + ComputerUtilCombat.getDamageToKill(c)));
|
||||
if (cantSave && (!topStack.usesTargeting() || !grantShroud)) {
|
||||
if (cantSave && (tgt == null || !grantShroud)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1754,7 +1734,7 @@ public class ComputerUtil {
|
||||
}
|
||||
|
||||
if (saviourApi == ApiType.Protection) {
|
||||
if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
if (tgt == null || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1791,13 +1771,13 @@ public class ComputerUtil {
|
||||
if (saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll
|
||||
|| saviorWithSubsApi == ApiType.Pump
|
||||
|| saviorWithSubsApi == ApiType.PumpAll) {
|
||||
if ((!topStack.usesTargeting() && !grantIndestructible)
|
||||
if ((tgt == null && !grantIndestructible)
|
||||
|| (!grantShroud && !grantIndestructible)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (saviourApi == ApiType.Protection) {
|
||||
if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
if (tgt == null || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1826,11 +1806,11 @@ public class ComputerUtil {
|
||||
if (o instanceof Card) {
|
||||
final Card c = (Card) o;
|
||||
// give Shroud to targeted creatures
|
||||
if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll) && (!topStack.usesTargeting() || !grantShroud)) {
|
||||
if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll) && (tgt == null || !grantShroud)) {
|
||||
continue;
|
||||
}
|
||||
if (saviourApi == ApiType.Protection) {
|
||||
if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
if (tgt == null || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1854,11 +1834,11 @@ public class ComputerUtil {
|
||||
if (o instanceof Card) {
|
||||
final Card c = (Card) o;
|
||||
// give Shroud to targeted creatures
|
||||
if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll && !topStack.usesTargeting()) && !grantShroud) {
|
||||
if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll && tgt == null) && !grantShroud) {
|
||||
continue;
|
||||
}
|
||||
if (saviourApi == ApiType.Protection) {
|
||||
if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
if (tgt == null || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1875,11 +1855,11 @@ public class ComputerUtil {
|
||||
if (o instanceof Card) {
|
||||
final Card c = (Card) o;
|
||||
// give Shroud to targeted creatures
|
||||
if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll && !topStack.usesTargeting()) && !grantShroud) {
|
||||
if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll && tgt == null) && !grantShroud) {
|
||||
continue;
|
||||
}
|
||||
if (saviourApi == ApiType.Protection) {
|
||||
if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
if (tgt == null || (ProtectAi.toProtectFrom(source, saviour) == null)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1972,10 +1952,10 @@ public class ComputerUtil {
|
||||
ComputerUtilCombat.combatantWouldBeDestroyed(ai, source, game.getCombat())) {
|
||||
return true;
|
||||
}
|
||||
} else if (zone.getZoneType() == ZoneType.Exile && sa.getMayPlay() != null) {
|
||||
} else if (zone.getZoneType() == ZoneType.Exile) {
|
||||
// play cards in exile that can only be played that turn
|
||||
if (game.getPhaseHandler().getPhase() == PhaseType.MAIN2) {
|
||||
if (source.mayPlay(sa.getMayPlay()) != null) {
|
||||
if (!sa.getMayPlayList().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2076,8 +2056,8 @@ public class ComputerUtil {
|
||||
final CardCollection candidates = new CardCollection();
|
||||
final CardCollectionView handList = ai.getCardsIn(ZoneType.Hand);
|
||||
|
||||
final CardCollection lands = CardLists.getValidCards(handList, "Card.Land", ai, null, null);
|
||||
final CardCollection nonLands = CardLists.getValidCards(handList, "Card.nonLand", ai, null, null);
|
||||
final CardCollection lands = CardLists.getValidCards(handList, "Card.Land", ai, null);
|
||||
final CardCollection nonLands = CardLists.getValidCards(handList, "Card.nonLand", ai, null);
|
||||
CardLists.sortByCmcDesc(nonLands);
|
||||
|
||||
if (lands.size() >= 3 && lands.size() <= 4) {
|
||||
@@ -2256,16 +2236,17 @@ public class ComputerUtil {
|
||||
return getCardsToDiscardFromOpponent(aiChooser, p, sa, validCards, min, max);
|
||||
}
|
||||
|
||||
public static List<String> chooseSomeType(Player ai, String kindOfType, String logic, int min, int max, Collection<String> validTypes) {
|
||||
public static String chooseSomeType(Player ai, String kindOfType, String logic, Collection<String> validTypes, List<String> invalidTypes) {
|
||||
if (invalidTypes == null) {
|
||||
invalidTypes = ImmutableList.of();
|
||||
}
|
||||
if (validTypes == null) {
|
||||
validTypes = ImmutableList.of();
|
||||
}
|
||||
|
||||
final Game game = ai.getGame();
|
||||
List<String> chosenList = Lists.newArrayList();
|
||||
String chosen = "";
|
||||
if (kindOfType.equals("Card")) {
|
||||
String chosen = "";
|
||||
|
||||
// TODO
|
||||
// computer will need to choose a type
|
||||
// based on whether it needs a creature or land,
|
||||
@@ -2273,25 +2254,24 @@ public class ComputerUtil {
|
||||
// then, reveal chosenType to Human
|
||||
if (game.getPhaseHandler().is(PhaseType.UNTAP) && logic == null) { // Storage Matrix
|
||||
double amount = 0;
|
||||
for (String type : validTypes) {
|
||||
CardCollection list = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.isType(type), Presets.TAPPED);
|
||||
double i = type.equals("Creature") ? list.size() * 1.5 : list.size();
|
||||
if (i > amount) {
|
||||
amount = i;
|
||||
chosen = type;
|
||||
for (String type : CardType.getAllCardTypes()) {
|
||||
if (!invalidTypes.contains(type)) {
|
||||
CardCollection list = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.isType(type), Presets.TAPPED);
|
||||
double i = type.equals("Creature") ? list.size() * 1.5 : list.size();
|
||||
if (i > amount) {
|
||||
amount = i;
|
||||
chosen = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (logic == "MostProminentInComputerDeck") {
|
||||
chosen = ComputerUtilCard.getMostProminentType(ai.getAllCards(), validTypes);
|
||||
}
|
||||
if (StringUtils.isEmpty(chosen)) {
|
||||
chosen = validTypes.isEmpty() ? "Creature" : Aggregates.random(validTypes);
|
||||
}
|
||||
chosenList.add(chosen);
|
||||
} else if (kindOfType.equals("Creature")) {
|
||||
String chosen = "";
|
||||
if (logic != null) {
|
||||
List <String> valid = Lists.newArrayList(validTypes);
|
||||
List <String> valid = Lists.newArrayList(CardType.getAllCreatureTypes());
|
||||
valid.removeAll(invalidTypes);
|
||||
|
||||
if (logic.equals("MostProminentOnBattlefield")) {
|
||||
chosen = ComputerUtilCard.getMostProminentType(game.getCardsIn(ZoneType.Battlefield), valid);
|
||||
@@ -2302,7 +2282,7 @@ public class ComputerUtil {
|
||||
else if (logic.equals("MostProminentOppControls")) {
|
||||
CardCollection list = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents());
|
||||
chosen = ComputerUtilCard.getMostProminentType(list, valid);
|
||||
if (!CardType.isACreatureType(chosen) || !validTypes.contains(chosen)) {
|
||||
if (!CardType.isACreatureType(chosen) || invalidTypes.contains(chosen)) {
|
||||
list = CardLists.filterControlledBy(game.getCardsInGame(), ai.getOpponents());
|
||||
chosen = ComputerUtilCard.getMostProminentType(list, valid);
|
||||
}
|
||||
@@ -2314,17 +2294,16 @@ public class ComputerUtil {
|
||||
chosen = ComputerUtilCard.getMostProminentType(ai.getCardsIn(ZoneType.Graveyard), valid);
|
||||
}
|
||||
}
|
||||
if (!CardType.isACreatureType(chosen) || !validTypes.contains(chosen)) {
|
||||
chosen = Iterables.getFirst(validTypes, null);
|
||||
if (!CardType.isACreatureType(chosen) || invalidTypes.contains(chosen)) {
|
||||
chosen = "Sliver";
|
||||
}
|
||||
|
||||
chosenList.add(chosen);
|
||||
} else if (kindOfType.equals("Basic Land")) {
|
||||
String chosen = "";
|
||||
if (logic != null) {
|
||||
if (logic.equals("MostProminentOppControls")) {
|
||||
CardCollection list = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents());
|
||||
List<String> valid = Lists.newArrayList(validTypes);
|
||||
List<String> valid = Lists.newArrayList(CardType.getBasicTypes());
|
||||
valid.removeAll(invalidTypes);
|
||||
|
||||
chosen = ComputerUtilCard.getMostProminentType(list, valid);
|
||||
} else if (logic.equals("MostNeededType")) {
|
||||
@@ -2347,9 +2326,9 @@ public class ComputerUtil {
|
||||
}
|
||||
}
|
||||
else if (logic.equals("ChosenLandwalk")) {
|
||||
for (Card c : ai.getWeakestOpponent().getLandsInPlay()) {
|
||||
for (Card c : ComputerUtil.getOpponentFor(ai).getLandsInPlay()) {
|
||||
for (String t : c.getType()) {
|
||||
if (validTypes.contains(t) && CardType.isABasicLandType(t)) {
|
||||
if (!invalidTypes.contains(t) && CardType.isABasicLandType(t)) {
|
||||
chosen = t;
|
||||
break;
|
||||
}
|
||||
@@ -2358,28 +2337,16 @@ public class ComputerUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (!CardType.isABasicLandType(chosen) || !validTypes.contains(chosen)) {
|
||||
chosen = Iterables.getFirst(validTypes, null);
|
||||
}
|
||||
chosenList.add(chosen);
|
||||
// the only one with choosing two types is Illusionary Terrain
|
||||
// and it needs other AI logic
|
||||
while (chosenList.size() < min) {
|
||||
validTypes.remove(chosen);
|
||||
chosen = Iterables.getFirst(validTypes, null);
|
||||
if (chosen == null) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
chosenList.add(chosen);
|
||||
if (!CardType.isABasicLandType(chosen) || invalidTypes.contains(chosen)) {
|
||||
chosen = "Island";
|
||||
}
|
||||
}
|
||||
else if (kindOfType.equals("Land")) {
|
||||
String chosen = "";
|
||||
if (logic != null) {
|
||||
if (logic.equals("ChosenLandwalk")) {
|
||||
for (Card c : ai.getWeakestOpponent().getLandsInPlay()) {
|
||||
for (Card c : ComputerUtil.getOpponentFor(ai).getLandsInPlay()) {
|
||||
for (String t : c.getType().getLandTypes()) {
|
||||
if (validTypes.contains(t)) {
|
||||
if (!invalidTypes.contains(t)) {
|
||||
chosen = t;
|
||||
break;
|
||||
}
|
||||
@@ -2388,11 +2355,10 @@ public class ComputerUtil {
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(chosen)) {
|
||||
chosen = Iterables.getFirst(validTypes, null);
|
||||
chosen = "Island";
|
||||
}
|
||||
chosenList.add(chosen);
|
||||
}
|
||||
return chosenList;
|
||||
return chosen;
|
||||
}
|
||||
|
||||
public static Object vote(Player ai, List<Object> options, SpellAbility sa, Multimap<Object, Player> votes, Player forPlayer) {
|
||||
@@ -2943,8 +2909,9 @@ public class ComputerUtil {
|
||||
}
|
||||
if (targetSpellCard == null) {
|
||||
return false;
|
||||
} else {
|
||||
sa.getTargets().add(targetSpellCard);
|
||||
}
|
||||
sa.getTargets().add(targetSpellCard);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3029,7 +2996,7 @@ public class ComputerUtil {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
list = CardLists.getValidCards(srcList, sa.getParam("AITgts"), sa.getActivatingPlayer(), source, sa);
|
||||
list = CardLists.getValidCards(srcList, sa.getParam("AITgts"), sa.getActivatingPlayer(), source);
|
||||
}
|
||||
|
||||
if (!list.isEmpty() || sa.hasParam("AITgtsStrict") || alwaysStrict) {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package forge.ai;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.CardStateName;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameActionUtil;
|
||||
@@ -16,11 +14,15 @@ import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.LandAbility;
|
||||
import forge.game.spellability.OptionalCostValue;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class ComputerUtilAbility {
|
||||
public static CardCollection getAvailableLandsToPlay(final Game game, final Player player) {
|
||||
if (!game.getStack().isEmpty() || !game.getPhaseHandler().getPhase().isMain()) {
|
||||
@@ -54,7 +56,8 @@ public class ComputerUtilAbility {
|
||||
if (!(crd.isLand() || (crd.isFaceDown() && crd.getState(CardStateName.Original).getType().isLand()))) {
|
||||
continue;
|
||||
}
|
||||
if (!crd.mayPlay(player).isEmpty()) {
|
||||
|
||||
if (Iterables.any(crd.getAllPossibleAbilities(player, true), Predicates.instanceOf(LandAbility.class))) {
|
||||
landList.add(crd);
|
||||
}
|
||||
}
|
||||
@@ -117,7 +120,7 @@ public class ComputerUtilAbility {
|
||||
newAbilities.add(sa);
|
||||
newAbilities.addAll(otherAltSa);
|
||||
}
|
||||
|
||||
|
||||
final List<SpellAbility> result = Lists.newArrayList();
|
||||
for (SpellAbility sa : newAbilities) {
|
||||
sa.setActivatingPlayer(player);
|
||||
@@ -171,8 +174,12 @@ public class ComputerUtilAbility {
|
||||
return sa;
|
||||
}
|
||||
|
||||
public static Card getAbilitySource(SpellAbility sa) {
|
||||
return sa.getOriginalHost() != null ? sa.getOriginalHost() : sa.getHostCard();
|
||||
}
|
||||
|
||||
public static String getAbilitySourceName(SpellAbility sa) {
|
||||
final Card c = sa.getOriginalOrHost();
|
||||
final Card c = getAbilitySource(sa);
|
||||
return c != null ? c.getName() : "";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
package forge.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
@@ -33,16 +18,7 @@ import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactory;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
@@ -64,6 +40,12 @@ import forge.item.PaperCard;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.Expressions;
|
||||
import forge.util.MyRandom;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class ComputerUtilCard {
|
||||
public static Card getMostExpensivePermanentAI(final CardCollectionView list, final SpellAbility spell, final boolean targeted) {
|
||||
@@ -327,17 +309,6 @@ public class ComputerUtilCard {
|
||||
return biggest;
|
||||
}
|
||||
|
||||
// For ability of Oracle en-Vec, return the first card that are going to attack next turn
|
||||
public static Card getBestCreatureToAttackNextTurnAI(final Player aiPlayer, final Iterable<Card> list) {
|
||||
AiController aic = ((PlayerControllerAi)aiPlayer.getController()).getAi();
|
||||
for(final Card card : list) {
|
||||
if (aic.getPredictedCombatNextTurn().isAttacking(card)) {
|
||||
return card;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getWorstAI.
|
||||
@@ -982,7 +953,7 @@ public class ComputerUtilCard {
|
||||
for(byte c : MagicColor.WUBRG) {
|
||||
String devotionCode = "Count$Devotion." + MagicColor.toLongString(c);
|
||||
|
||||
int devotion = AbilityUtils.calculateAmount(sa.getHostCard(), devotionCode, sa);
|
||||
int devotion = CardFactoryUtil.xCount(sa.getHostCard(), devotionCode);
|
||||
if (devotion > curDevotion && !CardLists.filter(hand, CardPredicates.isColor(c)).isEmpty()) {
|
||||
curDevotion = devotion;
|
||||
chosenColor = MagicColor.toLongString(c);
|
||||
@@ -1171,8 +1142,8 @@ public class ComputerUtilCard {
|
||||
}
|
||||
// if this thing has AILogic set to "Curse", it's probably meant as some form of disruption
|
||||
if (!priority) {
|
||||
for (final String value : c.getSVars().values()) {
|
||||
if (value.contains("AILogic$ Curse")) {
|
||||
for (final String sVar : c.getSVars().keySet()) {
|
||||
if (c.getSVars().get(sVar).contains("AILogic$ Curse")) {
|
||||
// this is a curse ability, so prioritize its removal
|
||||
priority = true;
|
||||
break;
|
||||
@@ -1214,9 +1185,10 @@ public class ComputerUtilCard {
|
||||
final float valueNow = Math.max(valueTempo, threat);
|
||||
if (valueNow < 0.2) { //hard floor to reduce ridiculous odds for instants over time
|
||||
return false;
|
||||
} else {
|
||||
final float chance = MyRandom.getRandom().nextFloat();
|
||||
return chance < valueNow;
|
||||
}
|
||||
final float chance = MyRandom.getRandom().nextFloat();
|
||||
return chance < valueNow;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1912,7 +1884,7 @@ public class ComputerUtilCard {
|
||||
|
||||
CardCollectionView list = game.getCardsIn(ZoneType.Battlefield);
|
||||
|
||||
list = CardLists.getValidCards(list, needsToPlay.split(","), card.getController(), card, sa);
|
||||
list = CardLists.getValidCards(list, needsToPlay.split(","), card.getController(), card, null);
|
||||
if (list.isEmpty()) {
|
||||
return AiPlayDecision.MissingNeededCards;
|
||||
}
|
||||
|
||||
@@ -25,19 +25,13 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.game.CardTraitBase;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.CostPayment;
|
||||
@@ -796,9 +790,9 @@ public class ComputerUtilCombat {
|
||||
return false; // The trigger should have triggered already
|
||||
}
|
||||
if (trigParams.containsKey("ValidCard")) {
|
||||
if (!trigger.matchesValid(attacker, trigParams.get("ValidCard").split(","))
|
||||
&& !(combat.isAttacking(source) && trigger.matchesValid(source,
|
||||
trigParams.get("ValidCard").split(","))
|
||||
if (!CardTraitBase.matchesValid(attacker, trigParams.get("ValidCard").split(","), source)
|
||||
&& !(combat.isAttacking(source) && CardTraitBase.matchesValid(source,
|
||||
trigParams.get("ValidCard").split(","), source)
|
||||
&& !trigParams.containsKey("Alone"))) {
|
||||
return false;
|
||||
}
|
||||
@@ -806,7 +800,7 @@ public class ComputerUtilCombat {
|
||||
if (trigParams.containsKey("Attacked")) {
|
||||
if (combat.isAttacking(attacker)) {
|
||||
GameEntity attacked = combat.getDefenderByAttacker(attacker);
|
||||
if (!trigger.matchesValid(attacked, trigParams.get("Attacked").split(","))) {
|
||||
if (!CardTraitBase.matchesValid(attacked, trigParams.get("Attacked").split(","), source)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -826,7 +820,7 @@ public class ComputerUtilCombat {
|
||||
if ((defender == null) && mode == TriggerType.AttackerUnblocked) {
|
||||
willTrigger = true;
|
||||
if (trigParams.containsKey("ValidCard")) {
|
||||
if (!trigger.matchesValid(attacker, trigParams.get("ValidCard").split(","))) {
|
||||
if (!CardTraitBase.matchesValid(attacker, trigParams.get("ValidCard").split(","), source)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -848,7 +842,7 @@ public class ComputerUtilCombat {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!trigger.matchesValid(attacker, validBlocked.split(","))) {
|
||||
if (!CardTraitBase.matchesValid(attacker, validBlocked.split(","), source)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -862,35 +856,35 @@ public class ComputerUtilCombat {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!trigger.matchesValid(defender, validBlocker.split(","))) {
|
||||
if (!CardTraitBase.matchesValid(defender, validBlocker.split(","), source)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (mode == TriggerType.AttackerBlocked || mode == TriggerType.AttackerBlockedByCreature) {
|
||||
willTrigger = true;
|
||||
if (trigParams.containsKey("ValidBlocker")) {
|
||||
if (!trigger.matchesValid(defender, trigParams.get("ValidBlocker").split(","))) {
|
||||
if (!CardTraitBase.matchesValid(defender, trigParams.get("ValidBlocker").split(","), source)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (trigParams.containsKey("ValidCard")) {
|
||||
if (!trigger.matchesValid(attacker, trigParams.get("ValidCard").split(","))) {
|
||||
if (!CardTraitBase.matchesValid(attacker, trigParams.get("ValidCard").split(","), source)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (mode == TriggerType.DamageDone) {
|
||||
willTrigger = true;
|
||||
if (trigParams.containsKey("ValidSource")) {
|
||||
if (!(trigger.matchesValid(defender, trigParams.get("ValidSource").split(","))
|
||||
if (!(CardTraitBase.matchesValid(defender, trigParams.get("ValidSource").split(","), source)
|
||||
&& defender.getNetCombatDamage() > 0
|
||||
&& (!trigParams.containsKey("ValidTarget")
|
||||
|| trigger.matchesValid(attacker, trigParams.get("ValidTarget").split(","))))) {
|
||||
|| CardTraitBase.matchesValid(attacker, trigParams.get("ValidTarget").split(","), source)))) {
|
||||
return false;
|
||||
}
|
||||
if (!(trigger.matchesValid(attacker, trigParams.get("ValidSource").split(","))
|
||||
if (!(CardTraitBase.matchesValid(attacker, trigParams.get("ValidSource").split(","), source)
|
||||
&& attacker.getNetCombatDamage() > 0
|
||||
&& (!trigParams.containsKey("ValidTarget")
|
||||
|| trigger.matchesValid(defender, trigParams.get("ValidTarget").split(","))))) {
|
||||
|| CardTraitBase.matchesValid(defender, trigParams.get("ValidTarget").split(","), source)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,16 @@
|
||||
package forge.ai;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import forge.ai.ability.AnimateAi;
|
||||
import forge.card.ColorSet;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostDamage;
|
||||
import forge.game.cost.CostDiscard;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostPayLife;
|
||||
import forge.game.cost.CostPayment;
|
||||
import forge.game.cost.CostPutCounter;
|
||||
import forge.game.cost.CostRemoveAnyCounter;
|
||||
import forge.game.cost.CostRemoveCounter;
|
||||
import forge.game.cost.CostSacrifice;
|
||||
import forge.game.cost.CostTapType;
|
||||
import forge.game.cost.PaymentDecision;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.Spell;
|
||||
@@ -45,6 +20,12 @@ import forge.util.MyRandom;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.collect.FCollectionView;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class ComputerUtilCost {
|
||||
|
||||
@@ -137,9 +118,8 @@ public class ComputerUtilCost {
|
||||
* the source
|
||||
* @return true, if successful
|
||||
*/
|
||||
|
||||
public static boolean checkDiscardCost(final Player ai, final Cost cost, final Card source, SpellAbility sa) {
|
||||
if (cost == null || source.hasSVar("AISkipDiscardCostCheck") /* FIXME: should not be needed! */ ) {
|
||||
public static boolean checkDiscardCost(final Player ai, final Cost cost, final Card source) {
|
||||
if (cost == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -153,7 +133,7 @@ public class ComputerUtilCost {
|
||||
if (type.equals("CARDNAME") && source.getAbilityText().contains("Bloodrush")) {
|
||||
continue;
|
||||
}
|
||||
final CardCollection typeList = CardLists.getValidCards(hand, type.split(","), source.getController(), source, sa);
|
||||
final CardCollection typeList = CardLists.getValidCards(hand, type.split(","), source.getController(), source, null);
|
||||
if (typeList.size() > ai.getMaxHandSize()) {
|
||||
continue;
|
||||
}
|
||||
@@ -163,9 +143,10 @@ public class ComputerUtilCost {
|
||||
Card pref = ComputerUtil.getCardPreference(ai, source, "DiscardCost", typeList);
|
||||
if (pref == null) {
|
||||
return false;
|
||||
} else {
|
||||
typeList.remove(pref);
|
||||
hand.remove(pref);
|
||||
}
|
||||
typeList.remove(pref);
|
||||
hand.remove(pref);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,7 +251,7 @@ public class ComputerUtilCost {
|
||||
}
|
||||
|
||||
final CardCollection sacList = new CardCollection();
|
||||
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), source.getController(), source, sourceAbility);
|
||||
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), source.getController(), source, null);
|
||||
|
||||
int count = 0;
|
||||
while (count < amount) {
|
||||
@@ -320,7 +301,7 @@ public class ComputerUtilCost {
|
||||
}
|
||||
|
||||
final CardCollection sacList = new CardCollection();
|
||||
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), source.getController(), source, sourceAbility);
|
||||
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), source.getController(), source, null);
|
||||
|
||||
int count = 0;
|
||||
while (count < amount) {
|
||||
@@ -641,7 +622,7 @@ public class ComputerUtilCost {
|
||||
return checkLifeCost(payer, cost, source, 4, sa)
|
||||
&& checkDamageCost(payer, cost, source, 4)
|
||||
&& (isMine || checkSacrificeCost(payer, cost, source, sa))
|
||||
&& (isMine || checkDiscardCost(payer, cost, source, sa))
|
||||
&& (isMine || checkDiscardCost(payer, cost, source))
|
||||
&& (!source.getName().equals("Tyrannize") || payer.getCardsIn(ZoneType.Hand).size() > 2)
|
||||
&& (!source.getName().equals("Perplex") || payer.getCardsIn(ZoneType.Hand).size() < 2)
|
||||
&& (!source.getName().equals("Breaking Point") || payer.getCreaturesInPlay().size() > 1)
|
||||
@@ -722,7 +703,7 @@ public class ComputerUtilCost {
|
||||
continue;
|
||||
}
|
||||
|
||||
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), part.getType().split(";"), source.getController(), source, sa);
|
||||
final CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), part.getType().split(";"), source.getController(), source, null);
|
||||
|
||||
int count = 0;
|
||||
while (count < val) {
|
||||
|
||||
@@ -1,26 +1,8 @@
|
||||
package forge.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import com.google.common.collect.*;
|
||||
import forge.ai.ability.AnimateAi;
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.MagicColor;
|
||||
@@ -31,23 +13,11 @@ import forge.card.mana.ManaCostShard;
|
||||
import forge.game.CardTraitPredicates;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameActionUtil;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.ability.*;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostAdjustment;
|
||||
import forge.game.cost.CostPartMana;
|
||||
import forge.game.cost.CostPayEnergy;
|
||||
import forge.game.cost.CostPayment;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.mana.Mana;
|
||||
import forge.game.mana.ManaCostBeingPaid;
|
||||
@@ -61,12 +31,15 @@ import forge.game.replacement.ReplacementType;
|
||||
import forge.game.spellability.AbilityManaPart;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.game.trigger.Trigger;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.TextUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ComputerUtilMana {
|
||||
private final static boolean DEBUG_MANA_PAYMENT = false;
|
||||
@@ -319,8 +292,8 @@ public class ComputerUtilMana {
|
||||
|
||||
// Exception: when paying generic mana with Cavern of Souls, prefer the colored mana producing ability
|
||||
// to attempt to make the spell uncounterable when possible.
|
||||
if (ComputerUtilAbility.getAbilitySourceName(ma).equals("Cavern of Souls") && ma.hasChosenType()
|
||||
&& sa.getHostCard().getType().getCreatureTypes().contains(ma.getChosenType(0))) {
|
||||
if (ComputerUtilAbility.getAbilitySourceName(ma).equals("Cavern of Souls")
|
||||
&& sa.getHostCard().getType().getCreatureTypes().contains(ma.getHostCard().getChosenType())) {
|
||||
if (toPay == ManaCostShard.COLORLESS && cost.getUnpaidShards().contains(ManaCostShard.GENERIC)) {
|
||||
// Deprioritize Cavern of Souls, try to pay generic mana with it instead to use the NoCounter ability
|
||||
continue;
|
||||
@@ -414,6 +387,7 @@ public class ComputerUtilMana {
|
||||
// then apply this one
|
||||
if (!replaceType.isEmpty()) {
|
||||
for (SpellAbility saMana : replaceAmount) {
|
||||
Card card = saMana.getHostCard();
|
||||
if (saMana.hasParam("ReplaceType")) {
|
||||
// replace color and colorless
|
||||
String color = saMana.getParam("ReplaceType");
|
||||
@@ -435,8 +409,8 @@ public class ComputerUtilMana {
|
||||
// replace color
|
||||
String color = saMana.getParam("ReplaceColor");
|
||||
if ("Chosen".equals(color)) {
|
||||
if (saMana.hasChosenColor()) {
|
||||
color = MagicColor.toShortString(saMana.getChosenColor());
|
||||
if (card.hasChosenColor()) {
|
||||
color = MagicColor.toShortString(card.getChosenColor());
|
||||
}
|
||||
}
|
||||
if (saMana.hasParam("ReplaceOnly")) {
|
||||
@@ -488,7 +462,7 @@ public class ComputerUtilMana {
|
||||
int pAmount = AbilityUtils.calculateAmount(trSA.getHostCard(), trSA.getParamOrDefault("Amount", "1"), trSA);
|
||||
String produced = trSA.getParam("Produced");
|
||||
if (produced.equals("Chosen")) {
|
||||
produced = MagicColor.toShortString(trSA.getHostCard().getChosenColor(trSA));
|
||||
produced = MagicColor.toShortString(trSA.getHostCard().getChosenColor());
|
||||
}
|
||||
manaProduced += " " + StringUtils.repeat(produced, pAmount);
|
||||
} else if (ApiType.ManaReflected.equals(trSA.getApi())) {
|
||||
@@ -629,13 +603,10 @@ public class ComputerUtilMana {
|
||||
int testEnergyPool = ai.getCounters(CounterEnumType.ENERGY);
|
||||
|
||||
boolean ignoreColor = false, ignoreType = false;
|
||||
StaticAbility mayPlay = sa.getMayPlay();
|
||||
if (mayPlay != null) {
|
||||
if (mayPlay.hasParam("MayPlayIgnoreColor")) {
|
||||
ignoreColor = true;
|
||||
} else if (mayPlay.hasParam("MayPlayIgnoreType")) {
|
||||
ignoreType = true;
|
||||
}
|
||||
if (sa.isIgnoreManaCostType()) {
|
||||
ignoreType = true;
|
||||
} else if (sa.isIgnoreManaCostColor()) {
|
||||
ignoreColor = true;
|
||||
}
|
||||
|
||||
List<SpellAbility> paymentList = Lists.newArrayList();
|
||||
|
||||
@@ -1,25 +1,9 @@
|
||||
package forge.ai;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import forge.StaticData;
|
||||
import forge.card.CardStateName;
|
||||
import forge.card.MagicColor;
|
||||
@@ -29,12 +13,7 @@ import forge.game.GameObject;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.effects.DetachedCardEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCloneStates;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactory;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.token.TokenInfo;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
@@ -53,6 +32,13 @@ import forge.item.IPaperCard;
|
||||
import forge.item.PaperCard;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.collect.FCollectionView;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public abstract class GameState {
|
||||
private static final Map<ZoneType, String> ZONES = new HashMap<>();
|
||||
@@ -89,7 +75,8 @@ public abstract class GameState {
|
||||
private final Map<Card, Integer> markedDamage = new HashMap<>();
|
||||
private final Map<Card, List<String>> cardToChosenClrs = new HashMap<>();
|
||||
private final Map<Card, CardCollection> cardToChosenCards = new HashMap<>();
|
||||
private final Map<Card, List<String>> cardToChosenTypes = new HashMap<>();
|
||||
private final Map<Card, String> cardToChosenType = new HashMap<>();
|
||||
private final Map<Card, String> cardToChosenType2 = new HashMap<>();
|
||||
private final Map<Card, List<String>> cardToRememberedId = new HashMap<>();
|
||||
private final Map<Card, List<String>> cardToImprintedId = new HashMap<>();
|
||||
private final Map<Card, List<String>> cardToMergedCards = new HashMap<>();
|
||||
@@ -340,16 +327,15 @@ public abstract class GameState {
|
||||
newText.append("|Damage:").append(c.getDamage());
|
||||
}
|
||||
|
||||
SpellAbility first = c.getFirstSpellAbility();
|
||||
if (first != null) {
|
||||
if (first.hasChosenColor()) {
|
||||
newText.append("|ChosenColor:").append(TextUtil.join(first.getChosenColors(), ","));
|
||||
}
|
||||
if (first.hasChosenType()) {
|
||||
newText.append("|ChosenType:").append(TextUtil.join(first.getChosenType(), ","));
|
||||
}
|
||||
if (!c.getChosenColor().isEmpty()) {
|
||||
newText.append("|ChosenColor:").append(TextUtil.join(c.getChosenColors(), ","));
|
||||
}
|
||||
if (!c.getChosenType().isEmpty()) {
|
||||
newText.append("|ChosenType:").append(c.getChosenType());
|
||||
}
|
||||
if (!c.getChosenType2().isEmpty()) {
|
||||
newText.append("|ChosenType2:").append(c.getChosenType2());
|
||||
}
|
||||
|
||||
if (!c.getNamedCard().isEmpty()) {
|
||||
newText.append("|NamedCard:").append(c.getNamedCard());
|
||||
}
|
||||
@@ -638,7 +624,8 @@ public abstract class GameState {
|
||||
markedDamage.clear();
|
||||
cardToChosenClrs.clear();
|
||||
cardToChosenCards.clear();
|
||||
cardToChosenTypes.clear();
|
||||
cardToChosenType.clear();
|
||||
cardToChosenType2.clear();
|
||||
cardToMergedCards.clear();
|
||||
cardToScript.clear();
|
||||
cardAttackMap.clear();
|
||||
@@ -733,7 +720,7 @@ public abstract class GameState {
|
||||
if (persistent) {
|
||||
produced.put("PersistentMana", "True");
|
||||
}
|
||||
final AbilityManaPart abMana = new AbilityManaPart(dummy, null, produced);
|
||||
final AbilityManaPart abMana = new AbilityManaPart(dummy, produced);
|
||||
game.getAction().invoke(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -828,7 +815,6 @@ public abstract class GameState {
|
||||
Card exiledWith = idToCard.get(Integer.parseInt(id));
|
||||
c.setExiledWith(exiledWith);
|
||||
c.setExiledBy(exiledWith.getController());
|
||||
exiledWith.addExiledWith(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1087,13 +1073,19 @@ public abstract class GameState {
|
||||
Card c = entry.getKey();
|
||||
List<String> colors = entry.getValue();
|
||||
|
||||
c.setChosenColors(colors, c.getFirstSpellAbility());
|
||||
c.setChosenColors(colors);
|
||||
}
|
||||
|
||||
// Chosen type
|
||||
for (Entry<Card, List<String>> entry : cardToChosenTypes.entrySet()) {
|
||||
for (Entry<Card, String> entry : cardToChosenType.entrySet()) {
|
||||
Card c = entry.getKey();
|
||||
c.setChosenType(entry.getValue(), c.getFirstSpellAbility());
|
||||
c.setChosenType(entry.getValue());
|
||||
}
|
||||
|
||||
// Chosen type 2
|
||||
for (Entry<Card, String> entry : cardToChosenType2.entrySet()) {
|
||||
Card c = entry.getKey();
|
||||
c.setChosenType2(entry.getValue());
|
||||
}
|
||||
|
||||
// Named card
|
||||
@@ -1379,7 +1371,9 @@ public abstract class GameState {
|
||||
} else if (info.startsWith("ChosenColor:")) {
|
||||
cardToChosenClrs.put(c, Arrays.asList(info.substring(info.indexOf(':') + 1).split(",")));
|
||||
} else if (info.startsWith("ChosenType:")) {
|
||||
cardToChosenTypes.put(c, Arrays.asList(info.substring(info.indexOf(':') + 1).split(",")));
|
||||
cardToChosenType.put(c, info.substring(info.indexOf(':') + 1));
|
||||
} else if (info.startsWith("ChosenType2:")) {
|
||||
cardToChosenType2.put(c, info.substring(info.indexOf(':') + 1));
|
||||
} else if (info.startsWith("ChosenCards:")) {
|
||||
CardCollection chosen = new CardCollection();
|
||||
String[] idlist = info.substring(info.indexOf(':') + 1).split(",");
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
package forge.ai;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.ai.ability.ProtectAi;
|
||||
import forge.card.CardStateName;
|
||||
@@ -33,43 +21,19 @@ import forge.game.GameObject;
|
||||
import forge.game.GameType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostAdjustment;
|
||||
import forge.game.cost.CostExile;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostPartMana;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.keyword.KeywordInterface;
|
||||
import forge.game.mana.Mana;
|
||||
import forge.game.mana.ManaConversionMatrix;
|
||||
import forge.game.mana.ManaCostBeingPaid;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.player.PlayerController;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.player.*;
|
||||
import forge.game.replacement.ReplacementEffect;
|
||||
import forge.game.spellability.Ability;
|
||||
import forge.game.spellability.AbilityStatic;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.LandAbility;
|
||||
import forge.game.spellability.OptionalCost;
|
||||
import forge.game.spellability.OptionalCostValue;
|
||||
import forge.game.spellability.Spell;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.spellability.TargetChoices;
|
||||
import forge.game.spellability.*;
|
||||
import forge.game.trigger.WrappedAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.item.PaperCard;
|
||||
@@ -78,6 +42,13 @@ import forge.util.ITriggerEvent;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.collect.FCollection;
|
||||
import forge.util.collect.FCollectionView;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* A prototype for player controller class
|
||||
@@ -106,7 +77,9 @@ public class PlayerControllerAi extends PlayerController {
|
||||
if (abilities.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return abilities.get(0);
|
||||
else {
|
||||
return abilities.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public AiController getAi() {
|
||||
@@ -543,12 +516,13 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> chooseSomeType(String kindOfType, SpellAbility sa, int min, int max, List<String> validTypes) {
|
||||
List<String> chosen = ComputerUtil.chooseSomeType(player, kindOfType, sa.getParam("AILogic"), min, max, validTypes);
|
||||
if (chosen.isEmpty()) {
|
||||
return validTypes.subList(0, min);
|
||||
public String chooseSomeType(String kindOfType, SpellAbility sa, Collection<String> validTypes, List<String> invalidTypes, boolean isOptional) {
|
||||
String chosen = ComputerUtil.chooseSomeType(player, kindOfType, sa.getParam("AILogic"), validTypes, invalidTypes);
|
||||
if (StringUtils.isBlank(chosen) && !validTypes.isEmpty()) {
|
||||
chosen = validTypes.iterator().next();
|
||||
System.err.println("AI has no idea how to choose " + kindOfType +", defaulting to arbitrary element: chosen");
|
||||
}
|
||||
getGame().getAction().notifyOfValue(sa, player, chosen.toString(), player);
|
||||
getGame().getAction().notifyOfValue(sa, player, chosen, player);
|
||||
return chosen;
|
||||
}
|
||||
|
||||
@@ -1005,11 +979,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
} else {
|
||||
if (sa.isCopied()) {
|
||||
if (sa.isSpell()) {
|
||||
if (!sa.getHostCard().isInZone(ZoneType.Stack)) {
|
||||
sa.setHostCard(player.getGame().getAction().moveToStack(sa.getHostCard(), sa));
|
||||
} else {
|
||||
player.getGame().getStackZone().add(sa.getHostCard());
|
||||
}
|
||||
player.getGame().getStackZone().add(sa.getHostCard());
|
||||
}
|
||||
|
||||
/* FIXME: the new implementation (below) requires implementing setupNewTargets in the AI controller, among other possible changes, otherwise breaks AI
|
||||
@@ -1189,7 +1159,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
} else if (logic.equals("MostProminentInHumanDeck")) {
|
||||
return ComputerUtilCard.getMostProminentCardName(oppLibrary);
|
||||
} else if (logic.equals("MostProminentCreatureInComputerDeck")) {
|
||||
CardCollectionView cards = CardLists.getValidCards(aiLibrary, "Creature", player, sa.getHostCard(), sa);
|
||||
CardCollectionView cards = CardLists.getValidCards(aiLibrary, "Creature", player, sa.getHostCard());
|
||||
return ComputerUtilCard.getMostProminentCardName(cards);
|
||||
} else if (logic.equals("BestCreatureInComputerDeck")) {
|
||||
Card bestCreature = ComputerUtilCard.getBestCreatureAI(aiLibrary);
|
||||
@@ -1197,7 +1167,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
} else if (logic.equals("RandomInComputerDeck")) {
|
||||
return Aggregates.random(aiLibrary).getName();
|
||||
} else if (logic.equals("MostProminentSpellInComputerDeck")) {
|
||||
CardCollectionView cards = CardLists.getValidCards(aiLibrary, "Card.Instant,Card.Sorcery", player, sa.getHostCard(), sa);
|
||||
CardCollectionView cards = CardLists.getValidCards(aiLibrary, "Card.Instant,Card.Sorcery", player, sa.getHostCard());
|
||||
return ComputerUtilCard.getMostProminentCardName(cards);
|
||||
} else if (logic.equals("CursedScroll")) {
|
||||
return SpecialCardAi.CursedScroll.chooseCard(player, sa);
|
||||
|
||||
@@ -9,13 +9,7 @@ import forge.ai.ability.TokenAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
|
||||
@@ -17,17 +17,10 @@
|
||||
*/
|
||||
package forge.ai;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ability.AnimateAi;
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.MagicColor;
|
||||
@@ -36,14 +29,7 @@ import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.CostPart;
|
||||
@@ -64,6 +50,11 @@ import forge.util.MyRandom;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.maps.LinkedHashMapToAmount;
|
||||
import forge.util.maps.MapToAmount;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Special logic for individual cards
|
||||
@@ -1000,7 +991,7 @@ public class SpecialCardAi {
|
||||
return false;
|
||||
}
|
||||
String prominentColor = ComputerUtilCard.getMostProminentColor(ai.getCardsIn(ZoneType.Battlefield));
|
||||
int devotion = AbilityUtils.calculateAmount(sa.getHostCard(), "Count$Devotion." + prominentColor, sa);
|
||||
int devotion = CardFactoryUtil.xCount(sa.getHostCard(), "Count$Devotion." + prominentColor);
|
||||
int activationCost = sa.getPayCosts().getTotalMana().getCMC() + (sa.getPayCosts().hasTapCost() ? 1 : 0);
|
||||
|
||||
// do not use this SA if devotion to most prominent color is less than its own activation cost + 1 (to actually get advantage)
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
package forge.ai;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.CardStateName;
|
||||
import forge.card.ICardFace;
|
||||
import forge.card.mana.ManaCost;
|
||||
@@ -26,6 +21,10 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityCondition;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Base class for API-specific AI logic
|
||||
* <p>
|
||||
@@ -127,7 +126,7 @@ public abstract class SpellAbilityAi {
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, source, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source, sa)) {
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source)) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, source, sa)) {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package forge.ai;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.ai.ability.*;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.util.ReflectionUtil;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public enum SpellApiToAi {
|
||||
Converter;
|
||||
|
||||
@@ -153,10 +152,9 @@ public enum SpellApiToAi {
|
||||
.put(ApiType.SetLife, LifeSetAi.class)
|
||||
.put(ApiType.SetState, SetStateAi.class)
|
||||
.put(ApiType.Shuffle, ShuffleAi.class)
|
||||
.put(ApiType.SkipPhase, SkipPhaseAi.class)
|
||||
.put(ApiType.SkipTurn, SkipTurnAi.class)
|
||||
.put(ApiType.StoreMap, StoreMapAi.class)
|
||||
.put(ApiType.StoreSVar, StoreSVarAi.class)
|
||||
.put(ApiType.Subgame, AlwaysPlayAi.class)
|
||||
.put(ApiType.Surveil, SurveilAi.class)
|
||||
.put(ApiType.Tap, TapAi.class)
|
||||
.put(ApiType.TapAll, TapAllAi.class)
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
@@ -13,6 +10,9 @@ import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ActivateAbilityAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_Turns class.
|
||||
|
||||
@@ -9,11 +9,7 @@ import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.token.TokenInfo;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.player.Player;
|
||||
@@ -30,38 +26,40 @@ public class AmassAi extends SpellAbilityAi {
|
||||
|
||||
if (!aiArmies.isEmpty()) {
|
||||
return CardLists.count(aiArmies, CardPredicates.canReceiveCounters(CounterEnumType.P1P1)) > 0;
|
||||
}
|
||||
final String tokenScript = "b_0_0_zombie_army";
|
||||
final int amount = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("Num", "1"), sa);
|
||||
} else {
|
||||
final String tokenScript = "b_0_0_zombie_army";
|
||||
final int amount = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("Num", "1"), sa);
|
||||
|
||||
Card token = TokenInfo.getProtoType(tokenScript, sa, false);
|
||||
Card token = TokenInfo.getProtoType(tokenScript, sa, false);
|
||||
|
||||
if (token == null) {
|
||||
return false;
|
||||
if (token == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
token.setController(ai, 0);
|
||||
token.setLastKnownZone(ai.getZone(ZoneType.Battlefield));
|
||||
|
||||
boolean result = true;
|
||||
|
||||
// need to check what the cards would be on the battlefield
|
||||
// do not attach yet, that would cause Events
|
||||
CardCollection preList = new CardCollection(token);
|
||||
game.getAction().checkStaticAbilities(false, Sets.newHashSet(token), preList);
|
||||
|
||||
if (token.canReceiveCounters(CounterEnumType.P1P1)) {
|
||||
token.setCounters(CounterEnumType.P1P1, amount);
|
||||
}
|
||||
|
||||
if (token.isCreature() && token.getNetToughness() < 1) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
//reset static abilities
|
||||
game.getAction().checkStaticAbilities(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
token.setController(ai, 0);
|
||||
token.setLastKnownZone(ai.getZone(ZoneType.Battlefield));
|
||||
|
||||
boolean result = true;
|
||||
|
||||
// need to check what the cards would be on the battlefield
|
||||
// do not attach yet, that would cause Events
|
||||
CardCollection preList = new CardCollection(token);
|
||||
game.getAction().checkStaticAbilities(false, Sets.newHashSet(token), preList);
|
||||
|
||||
if (token.canReceiveCounters(CounterEnumType.P1P1)) {
|
||||
token.setCounters(CounterEnumType.P1P1, amount);
|
||||
}
|
||||
|
||||
if (token.isCreature() && token.getNetToughness() < 1) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
//reset static abilities
|
||||
game.getAction().checkStaticAbilities(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,31 +1,14 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.CardType;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.ability.effects.AnimateEffectBase;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardTraitChanges;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.*;
|
||||
import forge.game.cost.CostPutCounter;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -36,6 +19,12 @@ import forge.game.staticability.StaticAbilityContinuous;
|
||||
import forge.game.staticability.StaticAbilityLayer;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.game.ability.effects.AnimateEffectBase;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactoryAnimate class.
|
||||
@@ -369,6 +358,7 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
// duplicating AnimateEffect.resolve
|
||||
final Card source = sa.getHostCard();
|
||||
final Game game = sa.getActivatingPlayer().getGame();
|
||||
final Map<String, String> svars = source.getSVars();
|
||||
final long timestamp = game.getNextTimestamp();
|
||||
card.setSickness(hasOriginalCardSickness);
|
||||
|
||||
@@ -401,7 +391,7 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
// allow ChosenType - overrides anything else specified
|
||||
if (types.hasSubtype("ChosenType")) {
|
||||
types.clear();
|
||||
types.addAll(sa.getChosenType());
|
||||
types.add(source.getChosenType());
|
||||
}
|
||||
|
||||
final List<String> keywords = Lists.newArrayList();
|
||||
@@ -421,8 +411,8 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
// allow SVar substitution for keywords
|
||||
for (int i = 0; i < keywords.size(); i++) {
|
||||
final String k = keywords.get(i);
|
||||
if (source.hasSVar(k)) {
|
||||
keywords.add(source.getSVar(k));
|
||||
if (svars.containsKey(k)) {
|
||||
keywords.add(svars.get(k));
|
||||
keywords.remove(k);
|
||||
}
|
||||
}
|
||||
@@ -432,7 +422,7 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
if (sa.hasParam("Colors")) {
|
||||
final String colors = sa.getParam("Colors");
|
||||
if (colors.equals("ChosenColor")) {
|
||||
tmpDesc = CardUtil.getShortColorsString(sa.getChosenColors());
|
||||
tmpDesc = CardUtil.getShortColorsString(source.getChosenColors());
|
||||
} else {
|
||||
tmpDesc = CardUtil.getShortColorsString(Lists.newArrayList(Arrays.asList(colors.split(","))));
|
||||
}
|
||||
|
||||
@@ -1,39 +1,17 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
@@ -53,6 +31,8 @@ import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AttachAi extends SpellAbilityAi {
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CanPlayAsDrawbackAi extends SpellAbilityAi {
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.player.Player;
|
||||
@@ -10,6 +7,9 @@ import forge.game.player.PlayerCollection;
|
||||
import forge.game.player.PlayerPredicates;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChangeCombatantsAi extends SpellAbilityAi {
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||
|
||||
@@ -1,35 +1,11 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.ai.AiBlockController;
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialAiLogic;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.SpellApiToAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
@@ -37,14 +13,8 @@ import forge.game.GlobalRuleChange;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostDiscard;
|
||||
@@ -59,6 +29,9 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ChangeZoneAi extends SpellAbilityAi {
|
||||
/*
|
||||
@@ -74,11 +47,9 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
protected boolean checkAiLogic(final Player ai, final SpellAbility sa, final String aiLogic) {
|
||||
Card host = sa.getHostCard();
|
||||
|
||||
if (host != null && host.hasSVar("AIPreferenceOverride")) {
|
||||
if (sa.getHostCard() != null && sa.getHostCard().hasSVar("AIPreferenceOverride")) {
|
||||
// currently used by SacAndUpgrade logic, might need simplification
|
||||
host.removeSVar("AIPreferenceOverride");
|
||||
sa.getHostCard().removeSVar("AIPreferenceOverride");
|
||||
}
|
||||
|
||||
if (aiLogic.equals("BeforeCombat")) {
|
||||
@@ -92,7 +63,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
} else if (aiLogic.equals("PriorityOptionalCost")) {
|
||||
boolean highPriority = false;
|
||||
// if we have more than one of these in hand, might not be worth waiting for optional cost payment on the additional copy
|
||||
highPriority |= CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.nameEquals(host.getName())).size() > 1;
|
||||
highPriority |= CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.nameEquals(sa.getHostCard().getName())).size() > 1;
|
||||
// if we are in danger in combat, no need to wait to pay the optional cost
|
||||
highPriority |= ai.getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)
|
||||
&& ai.getGame().getCombat() != null && ComputerUtilCombat.lifeInDanger(ai, ai.getGame().getCombat());
|
||||
@@ -127,40 +98,6 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
return true;
|
||||
} else if (aiLogic.equals("Pongify")) {
|
||||
return SpecialAiLogic.doPongifyLogic(ai, sa);
|
||||
} else if (aiLogic.equals("Ashiok")) {
|
||||
final int loyalty = host.getCurrentLoyalty() - 1;
|
||||
CardCollectionView choices = new CardCollection();
|
||||
for (int i = loyalty; i >= 0; i--) {
|
||||
sa.setXManaCostPaid(i);
|
||||
choices = ai.getGame().getCardsIn(ZoneType.listValueOf(sa.getParam("Origin")));
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("ChangeType"), host.getController(), host, sa);
|
||||
if (!choices.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (aiLogic.equals("BestCard")) {
|
||||
CardCollectionView choices = ai.getGame().getCardsIn(ZoneType.listValueOf(sa.getParam("Origin")));
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("ChangeType"), host.getController(), host, sa);
|
||||
if (!choices.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
} else if (aiLogic.startsWith("DiscardAllAndRetExiled")) {
|
||||
int numExiledWithSrc = CardLists.filter(ai.getCardsIn(ZoneType.Exile), CardPredicates.isExiledWith(host)).size();
|
||||
int curHandSize = ai.getCardsIn(ZoneType.Hand).size();
|
||||
|
||||
// minimum card advantage unless the hand will be fully reloaded
|
||||
int minAdv = aiLogic.contains(".minAdv") ? Integer.parseInt(aiLogic.substring(aiLogic.indexOf(".minAdv") + 7)) : 0;
|
||||
|
||||
if (numExiledWithSrc > curHandSize) {
|
||||
if (ComputerUtil.predictThreatenedObjects(ai, sa, true).contains(host)) {
|
||||
// Try to gain some card advantage if the card will die anyway
|
||||
// TODO: ideally, should evaluate the hand value and not discard good hands to it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return (curHandSize + minAdv - 1 < numExiledWithSrc) || (numExiledWithSrc >= ai.getMaxHandSize());
|
||||
}
|
||||
|
||||
return super.checkAiLogic(ai, sa, aiLogic);
|
||||
@@ -197,15 +134,8 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
return SpecialCardAi.MazesEnd.consider(aiPlayer, sa);
|
||||
} else if (aiLogic.equals("Pongify")) {
|
||||
return sa.isTargetNumberValid(); // Pre-targeted in checkAiLogic
|
||||
} else if (aiLogic.equals("Ashiok")) {
|
||||
return true; // If checkAiLogic returns true, then we should be good to go
|
||||
} else if (aiLogic.equals("BestCard")) {
|
||||
return true; // If checkAiLogic returns true, then we should be good to go
|
||||
} else if (aiLogic.startsWith("DiscardAllAndRetExiled")) {
|
||||
return true; // If checkAiLogic returns true, then we should be good to go
|
||||
}
|
||||
}
|
||||
|
||||
if (isHidden(sa)) {
|
||||
return hiddenOriginCanPlayAI(aiPlayer, sa);
|
||||
}
|
||||
@@ -331,7 +261,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source, sa)) {
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
||||
for (final CostPart part : abCost.getCostParts()) {
|
||||
if (part instanceof CostDiscard) {
|
||||
CostDiscard cd = (CostDiscard) part;
|
||||
@@ -427,7 +357,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
|
||||
if (type != null && p == ai) {
|
||||
// AI only "knows" about his information
|
||||
list = CardLists.getValidCards(list, type, source.getController(), source, sa);
|
||||
list = CardLists.getValidCards(list, type, source.getController(), source);
|
||||
list = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
@@ -440,7 +370,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
}
|
||||
// TODO: prevent ai seaching its own library when Ob Nixilis, Unshackled is in play
|
||||
if (origin != null && origin.isKnown()) {
|
||||
list = CardLists.getValidCards(list, type, source.getController(), source, sa);
|
||||
list = CardLists.getValidCards(list, type, source.getController(), source);
|
||||
}
|
||||
|
||||
if (!activateForCost && list.isEmpty()) {
|
||||
@@ -1177,7 +1107,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
|
||||
// Only care about combatants during combat
|
||||
if (game.getPhaseHandler().inCombat() && origin.contains(ZoneType.Battlefield)) {
|
||||
CardCollection newList = CardLists.getValidCards(list, "Card.attacking,Card.blocking", null, null, null);
|
||||
CardCollection newList = CardLists.getValidCards(list, "Card.attacking,Card.blocking", null, null);
|
||||
if (!newList.isEmpty() || !sa.isTrigger()) {
|
||||
list = newList;
|
||||
}
|
||||
@@ -1495,11 +1425,12 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
if (sa.getTargets().size() == 0 || sa.getTargets().size() < tgt.getMinTargets(sa.getHostCard(), sa)) {
|
||||
sa.resetTargets();
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtil.shouldCastLessThanMax(ai, source)) {
|
||||
return false;
|
||||
} else {
|
||||
if (!ComputerUtil.shouldCastLessThanMax(ai, source)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
list.remove(choice);
|
||||
@@ -1774,7 +1705,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
Card source = sa.getHostCard();
|
||||
String definedSac = StringUtils.split(source.getSVar("AIPreference"), "$")[1];
|
||||
|
||||
CardCollection listToSac = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), definedSac, ai, source, sa);
|
||||
CardCollection listToSac = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.restriction(definedSac.split(","), ai, source, sa));
|
||||
listToSac.sort(Collections.reverseOrder(CardLists.CmcComparatorInv));
|
||||
|
||||
CardCollection listToRet = CardLists.filter(ai.getCardsIn(ZoneType.Graveyard), Presets.CREATURES);
|
||||
@@ -1811,7 +1742,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
String definedGoal = sa.getParam("ChangeType");
|
||||
boolean anyCMC = !definedGoal.contains(".cmc");
|
||||
|
||||
CardCollection listToSac = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), definedSac, ai, source, sa);
|
||||
CardCollection listToSac = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.restriction(definedSac.split(","), ai, source, sa));
|
||||
listToSac.sort(!sacWorst ? CardLists.CmcComparatorInv : Collections.reverseOrder(CardLists.CmcComparatorInv));
|
||||
|
||||
for (Card sacCandidate : listToSac) {
|
||||
@@ -1825,12 +1756,12 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
curGoal = definedGoal.replace("X", String.format("%d", goalCMC));
|
||||
}
|
||||
|
||||
CardCollection listGoal = CardLists.getValidCards(ai.getCardsIn(ZoneType.Library), curGoal, ai, source, sa);
|
||||
CardCollection listGoal = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.restriction(curGoal.split(","), ai, source, sa));
|
||||
|
||||
if (!anyCMC) {
|
||||
listGoal = CardLists.getValidCards(listGoal, curGoal, source.getController(), source, sa);
|
||||
listGoal = CardLists.getValidCards(listGoal, curGoal, source.getController(), source);
|
||||
} else {
|
||||
listGoal = CardLists.getValidCards(listGoal, curGoal + (curGoal.contains(".") ? "+" : ".") + "cmcGE" + goalCMC, source.getController(), source, sa);
|
||||
listGoal = CardLists.getValidCards(listGoal, curGoal + (curGoal.contains(".") ? "+" : ".") + "cmcGE" + goalCMC, source.getController(), source);
|
||||
}
|
||||
|
||||
listGoal = CardLists.filter(listGoal, new Predicate<Card>() {
|
||||
@@ -2000,8 +1931,9 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
if (choice != null) {
|
||||
sa.getTargets().add(choice);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static CardCollection getSafeTargetsIfUnlessCostPaid(Player ai, SpellAbility sa, Iterable<Card> potentialTgts) {
|
||||
|
||||
@@ -1,29 +1,12 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiPlayerPredicates;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
@@ -34,6 +17,8 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class ChangeZoneAllAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||
@@ -51,7 +36,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source, sa)) {
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
||||
boolean aiLogicAllowsDiscard = sa.hasParam("AILogic") && sa.getParam("AILogic").startsWith("DiscardAll");
|
||||
|
||||
if (!aiLogicAllowsDiscard) {
|
||||
@@ -245,8 +230,25 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
||||
&& !ComputerUtil.isPlayingReanimator(ai);
|
||||
}
|
||||
} else if (origin.equals(ZoneType.Exile)) {
|
||||
// TODO: nothing to do here at the moment
|
||||
return false;
|
||||
String logic = sa.getParam("AILogic");
|
||||
|
||||
if (logic != null && logic.startsWith("DiscardAllAndRetExiled")) {
|
||||
int numExiledWithSrc = CardLists.filter(ai.getCardsIn(ZoneType.Exile), CardPredicates.isExiledWith(source)).size();
|
||||
int curHandSize = ai.getCardsIn(ZoneType.Hand).size();
|
||||
|
||||
// minimum card advantage unless the hand will be fully reloaded
|
||||
int minAdv = logic.contains(".minAdv") ? Integer.parseInt(logic.substring(logic.indexOf(".minAdv") + 7)) : 0;
|
||||
|
||||
if (numExiledWithSrc > curHandSize) {
|
||||
if (ComputerUtil.predictThreatenedObjects(ai, sa, true).contains(source)) {
|
||||
// Try to gain some card advantage if the card will die anyway
|
||||
// TODO: ideally, should evaluate the hand value and not discard good hands to it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return (curHandSize + minAdv - 1 < numExiledWithSrc) || (numExiledWithSrc >= ai.getMaxHandSize());
|
||||
}
|
||||
} else if (origin.equals(ZoneType.Stack)) {
|
||||
// time stop can do something like this:
|
||||
// Origin$ Stack | Destination$ Exile | SubAbility$ DBSkip
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiPlayDecision;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.effects.CharmEffect;
|
||||
import forge.game.card.Card;
|
||||
@@ -20,6 +12,9 @@ import forge.util.Aggregates;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CharmAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean checkApiLogic(Player ai, SpellAbility sa) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
@@ -20,6 +21,7 @@ import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -64,7 +66,7 @@ public class ChooseCardAi extends SpellAbilityAi {
|
||||
}
|
||||
CardCollectionView choices = ai.getGame().getCardsIn(choiceZone);
|
||||
if (sa.hasParam("Choices")) {
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host, sa);
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host);
|
||||
}
|
||||
if (sa.hasParam("TargetControls")) {
|
||||
choices = CardLists.filterControlledBy(choices, ai.getOpponents());
|
||||
@@ -77,7 +79,7 @@ public class ChooseCardAi extends SpellAbilityAi {
|
||||
final String filter = aiLogic.equals("Clone") ? "Permanent.YouDontCtrl,Permanent.nonLegendary"
|
||||
: "Permanent.YouDontCtrl+notnamedVesuva,Permanent.nonLegendary+notnamedVesuva";
|
||||
|
||||
choices = CardLists.getValidCards(choices, filter, host.getController(), host, sa);
|
||||
choices = CardLists.getValidCards(choices, filter, host.getController(), host);
|
||||
return !choices.isEmpty();
|
||||
} else if (aiLogic.equals("Never")) {
|
||||
return false;
|
||||
@@ -96,9 +98,21 @@ public class ChooseCardAi extends SpellAbilityAi {
|
||||
return ComputerUtilCombat.damageIfUnblocked(c, ai, combat, true) > ref;
|
||||
}
|
||||
});
|
||||
return !choices.isEmpty();
|
||||
} else if (aiLogic.equals("Ashiok")) {
|
||||
final int loyalty = host.getCounters(CounterEnumType.LOYALTY) - 1;
|
||||
for (int i = loyalty; i >= 0; i--) {
|
||||
sa.setXManaCostPaid(i);
|
||||
choices = ai.getGame().getCardsIn(choiceZone);
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host, sa);
|
||||
if (!choices.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return !choices.isEmpty();
|
||||
} else if (aiLogic.equals("RandomNonLand")) {
|
||||
return !CardLists.getValidCards(choices, "Card.nonLand", host.getController(), host, sa).isEmpty();
|
||||
return !CardLists.getValidCards(choices, "Card.nonLand", host.getController(), host).isEmpty();
|
||||
} else if (aiLogic.equals("Duneblast")) {
|
||||
CardCollection aiCreatures = ai.getCreaturesInPlay();
|
||||
CardCollection oppCreatures = ai.getWeakestOpponent().getCreaturesInPlay();
|
||||
@@ -172,7 +186,7 @@ public class ChooseCardAi extends SpellAbilityAi {
|
||||
choice = null;
|
||||
}
|
||||
} else if ("RandomNonLand".equals(logic)) {
|
||||
options = CardLists.getValidCards(options, "Card.nonLand", host.getController(), host, sa);
|
||||
options = CardLists.getValidCards(options, "Card.nonLand", host.getController(), host);
|
||||
choice = Aggregates.random(options);
|
||||
} else if (logic.equals("Untap")) {
|
||||
final String filter = "Permanent.YouCtrl,Permanent.tapped";
|
||||
@@ -275,8 +289,6 @@ public class ChooseCardAi extends SpellAbilityAi {
|
||||
// Choose the best (hopefully the fattest, whatever) creature so that hopefully it won't die too easily
|
||||
choice = ComputerUtilCard.getBestAI(creatures);
|
||||
}
|
||||
} else if (logic.equals("NextTurnAttacker")) {
|
||||
choice = ComputerUtilCard.getBestCreatureToAttackNextTurnAI(ai, options);
|
||||
} else {
|
||||
choice = ComputerUtilCard.getBestAI(options);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,7 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.StaticData;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.CardDb;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardSplitType;
|
||||
|
||||
@@ -8,9 +8,7 @@ import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChooseCompanionAi extends SpellAbilityAi {
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -1,29 +1,14 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.SpellApiToAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
@@ -32,11 +17,13 @@ import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.staticability.StaticAbilityCantBeCast;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
|
||||
@@ -172,10 +159,10 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
// FatespinnerSkipDraw,FatespinnerSkipMain,FatespinnerSkipCombat
|
||||
if (game.getReplacementHandler().wouldPhaseBeSkipped(player, "Draw")) {
|
||||
if (player.hasKeyword("Skip your draw step.")) {
|
||||
return skipDraw;
|
||||
}
|
||||
if (game.getReplacementHandler().wouldPhaseBeSkipped(player, "BeginCombat")) {
|
||||
if (player.hasKeyword("Skip your next combat phase.")) {
|
||||
return skipCombat;
|
||||
}
|
||||
|
||||
@@ -230,10 +217,11 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
return allow;
|
||||
}
|
||||
|
||||
SpellAbility firstSpell = imprinted.getFirstSpellAbility();
|
||||
// check if something would prevent it from casting
|
||||
if (firstSpell == null || StaticAbilityCantBeCast.cantBeCastAbility(firstSpell, imprinted, owner)) {
|
||||
return allow;
|
||||
//if Iona does prevent from casting, allow it to draw
|
||||
for (final Card io : player.getCardsIn(ZoneType.Battlefield, "Iona, Shield of Emeria")) {
|
||||
if (CardUtil.getColors(imprinted).hasAnyColor(MagicColor.fromName(io.getChosenColor()))) {
|
||||
return allow;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmg == 0) {
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChoosePlayerAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
@@ -46,7 +47,20 @@ public class ChooseSourceAi extends SpellAbilityAi {
|
||||
final Card source = sa.getHostCard();
|
||||
|
||||
if (abCost != null) {
|
||||
if (!willPayCosts(ai, sa, abCost, source)) {
|
||||
// AI currently disabled for these costs
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, abCost, source, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkRemoveCounterCost(abCost, source, sa)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -91,7 +105,7 @@ public class ChooseSourceAi extends SpellAbilityAi {
|
||||
}
|
||||
CardCollectionView choices = game.getCardsIn(ZoneType.Battlefield);
|
||||
if (sa.hasParam("Choices")) {
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host, sa);
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), host.getController(), host);
|
||||
}
|
||||
final Combat combat = game.getCombat();
|
||||
choices = CardLists.filter(choices, new Predicate<Card>() {
|
||||
@@ -141,26 +155,27 @@ public class ChooseSourceAi extends SpellAbilityAi {
|
||||
Card bestCreature = ComputerUtilCard.getBestCreatureAI(permanentSources);
|
||||
if (bestCreature != null) {
|
||||
return bestCreature;
|
||||
}
|
||||
// No optimal creature was found above, so try to broaden the choice.
|
||||
if (!Iterables.isEmpty(options)) {
|
||||
List<Card> oppCreatures = CardLists.filter(options, Predicates.and(CardPredicates.Presets.CREATURES,
|
||||
Predicates.not(CardPredicates.isOwner(aiChoser))));
|
||||
List<Card> aiNonCreatures = CardLists.filter(options, Predicates.and(Predicates.not(CardPredicates.Presets.CREATURES),
|
||||
CardPredicates.Presets.PERMANENTS, CardPredicates.isOwner(aiChoser)));
|
||||
} else {
|
||||
// No optimal creature was found above, so try to broaden the choice.
|
||||
if (!Iterables.isEmpty(options)) {
|
||||
List<Card> oppCreatures = CardLists.filter(options, Predicates.and(CardPredicates.Presets.CREATURES,
|
||||
Predicates.not(CardPredicates.isOwner(aiChoser))));
|
||||
List<Card> aiNonCreatures = CardLists.filter(options, Predicates.and(Predicates.not(CardPredicates.Presets.CREATURES),
|
||||
CardPredicates.Presets.PERMANENTS, CardPredicates.isOwner(aiChoser)));
|
||||
|
||||
if (!oppCreatures.isEmpty()) {
|
||||
return ComputerUtilCard.getBestCreatureAI(oppCreatures);
|
||||
} else if (!aiNonCreatures.isEmpty()) {
|
||||
return Aggregates.random(aiNonCreatures);
|
||||
} else {
|
||||
return Aggregates.random(options);
|
||||
if (!oppCreatures.isEmpty()) {
|
||||
return ComputerUtilCard.getBestCreatureAI(oppCreatures);
|
||||
} else if (!aiNonCreatures.isEmpty()) {
|
||||
return Aggregates.random(aiNonCreatures);
|
||||
} else {
|
||||
return Aggregates.random(options);
|
||||
}
|
||||
} else if (!game.getStack().isEmpty()) {
|
||||
// No permanent for the AI to choose. Should normally not happen unless using dev mode or something,
|
||||
// but when it does happen, choose the top card on stack if possible (generally it'll be the SA
|
||||
// source) in order to choose at least something, or the game will hang.
|
||||
return game.getStack().peekAbility().getHostCard();
|
||||
}
|
||||
} else if (!game.getStack().isEmpty()) {
|
||||
// No permanent for the AI to choose. Should normally not happen unless using dev mode or something,
|
||||
// but when it does happen, choose the top card on stack if possible (generally it'll be the SA
|
||||
// source) in order to choose at least something, or the game will hang.
|
||||
return game.getStack().peekAbility().getHostCard();
|
||||
}
|
||||
|
||||
// Should never get here
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.CardType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
@@ -25,6 +13,9 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class ChooseTypeAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||
|
||||
@@ -4,8 +4,8 @@ package forge.ai.ability;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollectionView;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
@@ -17,6 +14,9 @@ import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CloneAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
@@ -124,11 +124,11 @@ public class CloneAi extends SpellAbilityAi {
|
||||
private boolean cloneTgtAI(final SpellAbility sa) {
|
||||
// Specific logic for cards
|
||||
if ("CloneAttacker".equals(sa.getParam("AILogic"))) {
|
||||
CardCollection valid = CardLists.getValidCards(sa.getHostCard().getController().getCardsIn(ZoneType.Battlefield), sa.getParam("ValidTgts"), sa.getHostCard().getController(), sa.getHostCard(), sa);
|
||||
CardCollection valid = CardLists.getValidCards(sa.getHostCard().getController().getCardsIn(ZoneType.Battlefield), sa.getParam("ValidTgts"), sa.getHostCard().getController(), sa.getHostCard());
|
||||
sa.getTargets().add(ComputerUtilCard.getBestCreatureAI(valid));
|
||||
return true;
|
||||
} else if ("CloneBestCreature".equals(sa.getParam("AILogic"))) {
|
||||
CardCollection valid = CardLists.getValidCards(sa.getHostCard().getController().getGame().getCardsIn(ZoneType.Battlefield), sa.getParam("ValidTgts"), sa.getHostCard().getController(), sa.getHostCard(), sa);
|
||||
CardCollection valid = CardLists.getValidCards(sa.getHostCard().getController().getGame().getCardsIn(ZoneType.Battlefield), sa.getParam("ValidTgts"), sa.getHostCard().getController(), sa.getHostCard());
|
||||
sa.getTargets().add(ComputerUtilCard.getBestCreatureAI(valid));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ public class ControlExchangeAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aiWorst != bestFirstTgt) {
|
||||
if (aiWorst != null && aiWorst != bestFirstTgt) {
|
||||
if (bestFirstTgt.isCreature() && aiWorst.isCreature()) {
|
||||
if ((ComputerUtilCard.evaluateCreature(bestFirstTgt) > ComputerUtilCard.evaluateCreature(aiWorst) + creatureThreshold) || sa.isMandatory()) {
|
||||
sa.getTargets().add(aiWorst);
|
||||
|
||||
@@ -268,8 +268,9 @@ public class ControlGainAi extends SpellAbilityAi {
|
||||
List<Card> list = CardLists.getTargetableCards(ai.getCardsIn(ZoneType.Battlefield), sa);
|
||||
if (list.isEmpty()) {
|
||||
return false;
|
||||
} else {
|
||||
sa.getTargets().add(ComputerUtilCard.getWorstAI(list));
|
||||
}
|
||||
sa.getTargets().add(ComputerUtilCard.getWorstAI(list));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,29 +1,14 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.AiPlayDecision;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
@@ -32,6 +17,10 @@ import forge.game.player.PlayerCollection;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CopyPermanentAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||
@@ -184,7 +173,7 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
||||
} else if (sa.hasParam("Choices")) {
|
||||
// only check for options, does not select there
|
||||
CardCollectionView choices = game.getCardsIn(ZoneType.Battlefield);
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host, sa);
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host);
|
||||
Collection<Card> betterChoices = getBetterOptions(aiPlayer, sa, choices, !mandatory);
|
||||
if (betterChoices.isEmpty()) {
|
||||
return mandatory;
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.AiPlayDecision;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.player.Player;
|
||||
@@ -19,6 +10,9 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CopySpellAbilityAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
@@ -68,7 +62,7 @@ public class CopySpellAbilityAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
if (top.isWrapper() || top.isActivatedAbility()) {
|
||||
if (top.isWrapper() || !(top instanceof SpellAbility || top.isActivatedAbility())) {
|
||||
// Shouldn't even try with triggered or wrapped abilities at this time, will crash
|
||||
return false;
|
||||
} else if (top.getApi() == ApiType.CopySpellAbility) {
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
@@ -29,6 +16,11 @@ import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class CounterAi extends SpellAbilityAi {
|
||||
|
||||
|
||||
@@ -22,12 +22,7 @@ import java.util.List;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -26,6 +17,9 @@ import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CountersMoveAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean checkApiLogic(final Player ai, final SpellAbility sa) {
|
||||
|
||||
@@ -1,43 +1,19 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialAiLogic;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.CardStateName;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostPutCounter;
|
||||
import forge.game.cost.CostRemoveCounter;
|
||||
import forge.game.cost.CostSacrifice;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -51,6 +27,10 @@ import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CountersPutAi extends SpellAbilityAi {
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
@@ -21,6 +18,8 @@ import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CountersPutAllAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||
@@ -39,11 +38,11 @@ public class CountersPutAllAi extends SpellAbilityAi {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
|
||||
if ("OwnCreatsAndOtherPWs".equals(sa.getParam("AILogic"))) {
|
||||
hList = CardLists.getValidCards(ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), "Creature.YouCtrl,Planeswalker.YouCtrl+Other", source.getController(), source, sa);
|
||||
cList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), "Creature.YouCtrl,Planeswalker.YouCtrl+Other", source.getController(), source, sa);
|
||||
hList = CardLists.getValidCards(ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), "Creature.YouCtrl,Planeswalker.YouCtrl+Other", source.getController(), source);
|
||||
cList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), "Creature.YouCtrl,Planeswalker.YouCtrl+Other", source.getController(), source);
|
||||
} else {
|
||||
hList = CardLists.getValidCards(ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), valid, source.getController(), source, sa);
|
||||
cList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source, sa);
|
||||
hList = CardLists.getValidCards(ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
||||
cList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
||||
}
|
||||
|
||||
if (abCost != null) {
|
||||
@@ -52,7 +51,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source, sa)) {
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,27 +17,21 @@
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerController.BinaryChoiceType;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_PutOrRemoveCountersAi class.
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
@@ -13,13 +9,7 @@ import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -28,6 +18,9 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CountersRemoveAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
|
||||
@@ -1,39 +1,16 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostPartMana;
|
||||
import forge.game.cost.CostRemoveCounter;
|
||||
@@ -49,6 +26,12 @@ import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.MyRandom;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DamageDealAi extends DamageAiBase {
|
||||
@Override
|
||||
@@ -178,7 +161,7 @@ public class DamageDealAi extends DamageAiBase {
|
||||
}
|
||||
} else if ("WildHunt".equals(logic)) {
|
||||
// This dummy ability will just deal 0 damage, but holds the logic for the AI for Master of Wild Hunt
|
||||
List<Card> wolves = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), "Creature.Wolf+untapped+YouCtrl+Other", ai, source, sa);
|
||||
List<Card> wolves = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), "Creature.Wolf+untapped+YouCtrl+Other", ai, source);
|
||||
dmg = Aggregates.sum(wolves, CardPredicates.Accessors.fnGetNetPower);
|
||||
} else if ("Triskelion".equals(logic)) {
|
||||
final int n = source.getCounters(CounterEnumType.P1P1);
|
||||
@@ -245,7 +228,7 @@ public class DamageDealAi extends DamageAiBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ("DiscardLands".equals(sa.getParam("AILogic")) && !ComputerUtilCost.checkDiscardCost(ai, abCost, source, sa)) {
|
||||
if ("DiscardLands".equals(sa.getParam("AILogic")) && !ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
@@ -25,6 +19,9 @@ import forge.game.spellability.TargetChoices;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DamagePreventAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
@@ -36,7 +33,20 @@ public class DamagePreventAi extends SpellAbilityAi {
|
||||
|
||||
final Cost cost = sa.getPayCosts();
|
||||
|
||||
if (!willPayCosts(ai, sa, cost, hostCard)) {
|
||||
// temporarily disabled until better AI
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, hostCard, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, hostCard)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, hostCard, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkRemoveCounterCost(cost, hostCard, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.cost.Cost;
|
||||
@@ -20,7 +22,19 @@ public class DamagePreventAllAi extends SpellAbilityAi {
|
||||
final Cost cost = sa.getPayCosts();
|
||||
|
||||
// temporarily disabled until better AI
|
||||
if (!willPayCosts(ai, sa, cost, hostCard)) {
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, hostCard, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, hostCard)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, hostCard, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkRemoveCounterCost(cost, hostCard, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -25,6 +21,10 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class DebuffAi extends SpellAbilityAi {
|
||||
// *************************************************************************
|
||||
// ***************************** Debuff ************************************
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiPlayDecision;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.SpellApiToAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
|
||||
@@ -1,23 +1,10 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialAiLogic;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostSacrifice;
|
||||
|
||||
@@ -2,13 +2,7 @@ package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.ai.AiBlockController;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
|
||||
@@ -5,12 +5,7 @@ import java.util.Map;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.Card;
|
||||
@@ -14,6 +12,8 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DigUntilAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollectionView;
|
||||
@@ -22,6 +15,8 @@ import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DiscardAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
@@ -32,11 +27,26 @@ public class DiscardAi extends SpellAbilityAi {
|
||||
final Cost abCost = sa.getPayCosts();
|
||||
final String aiLogic = sa.getParamOrDefault("AILogic", "");
|
||||
|
||||
// temporarily disabled until better AI
|
||||
if (!willPayCosts(ai, sa, abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, abCost, source, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkRemoveCounterCost(abCost, source, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ("Chandra, Flamecaller".equals(sourceName)) {
|
||||
final int hand = ai.getCardsIn(ZoneType.Hand).size();
|
||||
return MyRandom.getRandom().nextFloat() < (1.0 / (1 + hand));
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
@@ -10,6 +8,8 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DrainManaAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,26 +18,14 @@
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.AiCostDecision;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostDiscard;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostPayLife;
|
||||
import forge.game.cost.PaymentDecision;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
@@ -102,7 +90,7 @@ public class DrawAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source,sa)) {
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source)) {
|
||||
AiCostDecision aiDecisions = new AiCostDecision(ai, sa);
|
||||
for (final CostPart part : cost.getCostParts()) {
|
||||
if (part instanceof CostDiscard) {
|
||||
@@ -265,8 +253,8 @@ public class DrawAi extends SpellAbilityAi {
|
||||
if (sa.getPayCosts().hasSpecificCostType(CostPayLife.class)) {
|
||||
// [Necrologia, Pay X Life : Draw X Cards]
|
||||
// Don't draw more than what's "safe" and don't risk a near death experience
|
||||
boolean aggroAI = (((PlayerControllerAi) ai.getController()).getAi()).getBooleanProperty(AiProps.PLAY_AGGRO);
|
||||
while ((ComputerUtil.aiLifeInDanger(ai, aggroAI, numCards) && (numCards > 0))) {
|
||||
// Maybe would be better to check for "serious danger" and take more risk?
|
||||
while ((ComputerUtil.aiLifeInDanger(ai, false, numCards) && (numCards > 0))) {
|
||||
numCards--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,12 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.SpellApiToAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
@@ -34,6 +18,8 @@ import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EffectAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean canPlayAI(final Player ai,final SpellAbility sa) {
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.ai.*;
|
||||
import forge.game.card.*;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
@@ -23,6 +16,9 @@ import forge.game.trigger.Trigger;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FightAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean checkAiLogic(final Player ai, final SpellAbility sa, final String aiLogic) {
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.card.Card;
|
||||
@@ -18,6 +12,8 @@ import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FogAi extends SpellAbilityAi {
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiPlayDecision;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.SpellApiToAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
@@ -3,7 +3,6 @@ package forge.ai.ability;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CounterEnumType;
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.keyword.Keyword;
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
@@ -43,14 +38,14 @@ public class LifeGainAi extends SpellAbilityAi {
|
||||
|
||||
if (!lifeCritical) {
|
||||
// return super.willPayCosts(ai, sa, cost, source);
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, source, sa, false)) {
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, source, sa,false)) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, source, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source, sa)) {
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +1,12 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.ai.AiPlayDecision;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.MagicColor;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostRemoveCounter;
|
||||
import forge.game.keyword.Keyword;
|
||||
@@ -32,6 +17,9 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ManaEffectAi extends SpellAbilityAi {
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
@@ -28,6 +24,9 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by friarsol on 1/23/15.
|
||||
*/
|
||||
@@ -142,7 +141,7 @@ public class ManifestAi extends SpellAbilityAi {
|
||||
}
|
||||
CardCollection choices = new CardCollection(game.getCardsIn(choiceZone));
|
||||
if (sa.hasParam("Choices")) {
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), ai, host, sa);
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), ai, host);
|
||||
}
|
||||
if (choices.isEmpty()) {
|
||||
return false;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpecialCardAi;
|
||||
@@ -25,6 +19,11 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MillAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
@@ -24,6 +17,9 @@ import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MustBlockAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.Card;
|
||||
@@ -16,6 +13,8 @@ import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class MutateAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.game.card.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
@@ -12,11 +13,6 @@ import forge.card.CardType.Supertype;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.Game;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.keyword.KeywordInterface;
|
||||
import forge.game.mana.ManaCostBeingPaid;
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.ApiType;
|
||||
@@ -66,7 +59,7 @@ public class PermanentCreatureAi extends PermanentAi {
|
||||
if (sa.isDash()) {
|
||||
//only checks that the dashed creature will attack
|
||||
if (ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
||||
if (game.getReplacementHandler().wouldPhaseBeSkipped(ai, "BeginCombat"))
|
||||
if (ai.hasKeyword("Skip your next combat phase."))
|
||||
return false;
|
||||
if (ComputerUtilCost.canPayCost(sa.getHostCard().getSpellPermanent(), ai)) {
|
||||
//do not dash if creature can be played normally
|
||||
@@ -84,7 +77,7 @@ public class PermanentCreatureAi extends PermanentAi {
|
||||
// after attacking
|
||||
if (card.hasSVar("EndOfTurnLeavePlay")
|
||||
&& (!ph.isPlayerTurn(ai) || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
||||
|| game.getReplacementHandler().wouldPhaseBeSkipped(ai, "BeginCombat"))) {
|
||||
|| ai.hasKeyword("Skip your next combat phase."))) {
|
||||
// AiPlayDecision.AnotherTime
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
@@ -19,6 +16,8 @@ import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PhasesAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||
|
||||
@@ -1,30 +1,16 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiPlayDecision;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.CardStateName;
|
||||
import forge.card.CardTypeView;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.player.Player;
|
||||
@@ -37,6 +23,10 @@ import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PlayAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
@@ -17,6 +14,9 @@ import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class PowerExchangeAi extends SpellAbilityAi {
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -5,12 +5,7 @@ import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.AiAttackController;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.cost.Cost;
|
||||
@@ -19,7 +21,19 @@ public class ProtectAllAi extends SpellAbilityAi {
|
||||
final Cost cost = sa.getPayCosts();
|
||||
|
||||
// temporarily disabled until better AI
|
||||
if (!willPayCosts(ai, sa, cost, hostCard)) {
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, hostCard, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, hostCard)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, hostCard, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkRemoveCounterCost(cost, hostCard, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +1,14 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpecialAiLogic;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostTapType;
|
||||
import forge.game.keyword.Keyword;
|
||||
@@ -38,6 +20,10 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PumpAi extends PumpAiBase {
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
@@ -13,12 +10,7 @@ import forge.ai.SpellAbilityAi;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.*;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.keyword.Keyword;
|
||||
@@ -29,6 +21,8 @@ import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class PumpAiBase extends SpellAbilityAi {
|
||||
|
||||
public boolean containsUsefulKeyword(final Player ai, final List<String> keywords, final Card card, final SpellAbility sa, final int attack) {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
@@ -26,6 +22,10 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PumpAllAi extends PumpAiBase {
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -69,8 +69,8 @@ public class PumpAllAi extends PumpAiBase {
|
||||
}
|
||||
|
||||
final Player opp = ai.getWeakestOpponent();
|
||||
CardCollection comp = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source, sa);
|
||||
CardCollection human = CardLists.getValidCards(opp.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source, sa);
|
||||
CardCollection comp = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
||||
CardCollection human = CardLists.getValidCards(opp.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
||||
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
if (tgt != null && sa.canTarget(opp) && sa.hasParam("IsCurse")) {
|
||||
@@ -144,7 +144,7 @@ public class PumpAllAi extends PumpAiBase {
|
||||
return (ComputerUtilCard.evaluateCreatureList(comp) + 200) < ComputerUtilCard.evaluateCreatureList(human);
|
||||
} // end Curse
|
||||
|
||||
return !CardLists.getValidCards(getPumpCreatures(ai, sa, defense, power, keywords, false), valid, source.getController(), source, sa).isEmpty();
|
||||
return !CardLists.getValidCards(getPumpCreatures(ai, sa, defense, power, keywords, false), valid, source.getController(), source).isEmpty();
|
||||
} // pumpAllCanPlayAI()
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
|
||||
import forge.ai.AiCardMemory;
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.AiProps;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardLists;
|
||||
|
||||
@@ -17,13 +17,7 @@
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
@@ -39,6 +33,9 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_Regenerate class.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
@@ -17,6 +15,8 @@ import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RegenerateAllAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
|
||||
import forge.ai.AiController;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.ai.*;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
@@ -21,6 +17,9 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class RepeatEachAi extends SpellAbilityAi {
|
||||
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
@@ -24,18 +16,13 @@ public class RestartGameAi extends SpellAbilityAi {
|
||||
*/
|
||||
@Override
|
||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||
if (ComputerUtil.aiLifeInDanger(ai, true, 0)) {
|
||||
return true;
|
||||
}
|
||||
// The only card that uses this is Karn Liberated
|
||||
|
||||
// check if enough good permanents will be available to be returned, so AI can "autowin"
|
||||
CardCollection exiled = new CardCollection(Iterables.filter(sa.getHostCard().getRemembered(), Card.class));
|
||||
exiled = CardLists.filter(exiled, Presets.PERMANENTS);
|
||||
if (ComputerUtilCard.evaluatePermanentList(exiled) > 20) {
|
||||
return true;
|
||||
}
|
||||
// TODO Add Logic, check if AI is losing game state, or life
|
||||
|
||||
return false;
|
||||
// TODO Add Logic, check if any good cards will be available to be returned
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -65,7 +65,7 @@ public class RevealAi extends RevealAiBase {
|
||||
for (SpellAbility s : c.getBasicSpells()) {
|
||||
Spell spell = (Spell) s.copy(ai);
|
||||
// timing restrictions still apply
|
||||
if (!spell.getRestrictions().checkTimingRestrictions(c, spell))
|
||||
if (!s.getRestrictions().checkTimingRestrictions(c, s))
|
||||
continue;
|
||||
|
||||
// use hard coded reduce cost
|
||||
|
||||
@@ -26,8 +26,6 @@ public class RollDiceAi extends SpellAbilityAi {
|
||||
return game.getCombat() != null && (game.getCombat().isAttacking(source) || game.getCombat().isBlocking(source));
|
||||
} else if (logic.equals("Main2")) {
|
||||
return ph.is(PhaseType.MAIN2, aiPlayer);
|
||||
} else if (logic.equals("AtOppEOT")) {
|
||||
return ph.getNextTurn() == aiPlayer && ph.is(PhaseType.END_OF_TURN);
|
||||
}
|
||||
|
||||
if (cost != null && (sa.getPayCosts().hasManaCost() || sa.getPayCosts().hasTapCost())) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
@@ -19,6 +17,8 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SacrificeAi extends SpellAbilityAi {
|
||||
// **************************************************************
|
||||
// *************************** Sacrifice ***********************
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.Card.SplitCMCMode;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.card.CardStateName;
|
||||
import forge.game.Game;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardState;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterEnumType;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
public class SkipPhaseAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
|
||||
return mandatory || canPlayAI(aiPlayer, sa);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
21
forge-ai/src/main/java/forge/ai/ability/StoreMapAi.java
Normal file
21
forge-ai/src/main/java/forge/ai/ability/StoreMapAi.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
public class StoreMapAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user