mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
AI cleanup (#9210)
* Cherry pick priority improvement * Align signatures
This commit is contained in:
@@ -938,10 +938,9 @@ public class ComputerUtil {
|
||||
}
|
||||
}
|
||||
|
||||
for (int ip = 0; ip < 6; ip++) { // priority 0 is the lowest, priority 5 the highest
|
||||
final int priority = 6 - ip;
|
||||
for (int prio = 6; prio > 0; prio--) {
|
||||
for (Card card : remaining) {
|
||||
if (card.hasSVar("SacMe") && Integer.parseInt(card.getSVar("SacMe")) == priority) {
|
||||
if (card.hasSVar("SacMe") && Integer.parseInt(card.getSVar("SacMe")) == prio) {
|
||||
return card;
|
||||
}
|
||||
}
|
||||
@@ -1153,7 +1152,7 @@ public class ComputerUtil {
|
||||
if (card.getSVar("PlayMain1").equals("ALWAYS") || sa.getPayCosts().hasNoManaCost()) {
|
||||
return true;
|
||||
} else if (card.getSVar("PlayMain1").equals("OPPONENTCREATURES")) {
|
||||
//Only play these main1 when the opponent has creatures (stealing and giving them haste)
|
||||
// Only play these main1 when the opponent has creatures (stealing and giving them haste)
|
||||
if (!ai.getOpponents().getCreaturesInPlay().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
@@ -1323,8 +1322,8 @@ public class ComputerUtil {
|
||||
}
|
||||
}
|
||||
|
||||
final CardCollectionView buffed = ai.getCardsIn(ZoneType.Battlefield);
|
||||
boolean checkThreshold = sa.isSpell() && !ai.hasThreshold() && !source.isInZone(ZoneType.Graveyard);
|
||||
final CardCollectionView buffed = ai.getCardsIn(ZoneType.Battlefield);
|
||||
for (Card buffedCard : buffed) {
|
||||
if (buffedCard.hasSVar("BuffedBy")) {
|
||||
final String buffedby = buffedCard.getSVar("BuffedBy");
|
||||
@@ -3068,16 +3067,16 @@ public class ComputerUtil {
|
||||
}
|
||||
|
||||
// this function should be called by most API to give scripters the option of helping AI
|
||||
public static CardCollection filterAITgts(SpellAbility sa, Player ai, CardCollection srcList, boolean alwaysStrict) {
|
||||
public static CardCollection filterAITgts(SpellAbility sa, Player ai, CardCollection targetables, boolean alwaysStrict) {
|
||||
// TODO support players
|
||||
final Card source = sa.getHostCard();
|
||||
if (source == null || !sa.hasParam("AITgts")) {
|
||||
return srcList;
|
||||
return targetables;
|
||||
}
|
||||
|
||||
// TODO randomize the order, just so human can't predict in advance which of two equal cards AI might pick
|
||||
|
||||
CardCollection list;
|
||||
CardCollection filtered;
|
||||
String aiTgts = sa.getParam("AITgts");
|
||||
if (aiTgts.startsWith("BetterThan")) {
|
||||
int value = 0;
|
||||
@@ -3097,28 +3096,28 @@ public class ComputerUtil {
|
||||
value = ComputerUtilCard.evaluateCreature(source);
|
||||
}
|
||||
final int totalValue = value;
|
||||
list = CardLists.filter(srcList, c -> ComputerUtilCard.evaluateCreature(c) > totalValue + 30);
|
||||
filtered = CardLists.filter(targetables, c -> ComputerUtilCard.evaluateCreature(c) > totalValue + 30);
|
||||
} else {
|
||||
list = CardLists.getValidCards(srcList, aiTgts, sa.getActivatingPlayer(), source, sa);
|
||||
filtered = CardLists.getValidCards(targetables, aiTgts, sa.getActivatingPlayer(), source, sa);
|
||||
}
|
||||
|
||||
if (sa.hasParam("AITgtsStrict") || alwaysStrict) {
|
||||
return list;
|
||||
return filtered;
|
||||
}
|
||||
if (!list.isEmpty()) {
|
||||
if (!filtered.isEmpty()) {
|
||||
// try to fill up with other regular targets to increase chance of playing
|
||||
for (Card tgt : srcList) {
|
||||
if (list.size() >= sa.getMinTargets()) {
|
||||
for (Card tgt : targetables) {
|
||||
if (filtered.size() >= sa.getMinTargets()) {
|
||||
break;
|
||||
}
|
||||
if (list.contains(tgt)) {
|
||||
if (filtered.contains(tgt)) {
|
||||
continue;
|
||||
}
|
||||
list.add(tgt);
|
||||
filtered.add(tgt);
|
||||
}
|
||||
return list;
|
||||
return filtered;
|
||||
}
|
||||
return srcList;
|
||||
return targetables;
|
||||
}
|
||||
|
||||
// Check if AI life is in danger/serious danger based on next expected combat
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.ai;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
@@ -25,6 +26,10 @@ import forge.game.spellability.OptionalCost;
|
||||
import forge.game.spellability.OptionalCostValue;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.game.staticability.StaticAbilityMode;
|
||||
import forge.game.trigger.Trigger;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class ComputerUtilAbility {
|
||||
@@ -366,15 +371,32 @@ public class ComputerUtilAbility {
|
||||
p -= 9;
|
||||
}
|
||||
// move snap-casted spells to front
|
||||
if (source.isInZone(ZoneType.Graveyard)) {
|
||||
if (sa.getMayPlay() != null && source.mayPlay(sa.getMayPlay()) != null) {
|
||||
p += 50;
|
||||
}
|
||||
if (source.isInZone(ZoneType.Graveyard) && source.mayPlay(sa.getMayPlay()) != null) {
|
||||
p += 50;
|
||||
}
|
||||
// if the profile specifies it, deprioritize Storm spells in an attempt to build up storm count
|
||||
if (source.hasKeyword(Keyword.STORM) && ai.getController() instanceof PlayerControllerAi) {
|
||||
p -= (((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.PRIORITY_REDUCTION_FOR_STORM_SPELLS));
|
||||
}
|
||||
|
||||
for (Trigger trig : source.getTriggers()) {
|
||||
if (!"Battlefield".equals(trig.getParam("TriggerZones"))) {
|
||||
continue;
|
||||
}
|
||||
final TriggerType mode = trig.getMode();
|
||||
// benefit from Magecraft abilities
|
||||
if ((mode == TriggerType.SpellCast || mode == TriggerType.SpellCastOrCopy) && "You".equals(sa.getParam("ValidActivatingPlayer"))) {
|
||||
p += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (StaticAbility sta : source.getStaticAbilities()) {
|
||||
final Set<StaticAbilityMode> mode = sta.getMode();
|
||||
// reduce cost to enable more plays
|
||||
if (mode.contains(StaticAbilityMode.ReduceCost) && "You".equals(sta.getParam("Activator"))) {
|
||||
p += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// use Surge and Prowl costs when able to
|
||||
|
||||
@@ -1225,7 +1225,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
@Override
|
||||
public boolean payCostToPreventEffect(Cost cost, SpellAbility sa, boolean alreadyPaid, FCollectionView<Player> allPayers) {
|
||||
if (SpellApiToAi.Converter.get(sa).willPayUnlessCost(sa, player, cost, alreadyPaid, allPayers)) {
|
||||
if (SpellApiToAi.Converter.get(sa).willPayUnlessCost(player, sa, cost, alreadyPaid, allPayers)) {
|
||||
if (!ComputerUtilCost.canPayCost(cost, sa, player, true)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1586,7 +1586,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
@Override
|
||||
public List<OptionalCostValue> chooseOptionalCosts(SpellAbility chosen, List<OptionalCostValue> optionalCostValues) {
|
||||
return SpellApiToAi.Converter.get(chosen).chooseOptionalCosts(chosen, player, optionalCostValues);
|
||||
return SpellApiToAi.Converter.get(chosen).chooseOptionalCosts(player, chosen, optionalCostValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -247,7 +247,7 @@ public abstract class SpellAbilityAi {
|
||||
*/
|
||||
public AiAbilityDecision chkDrawbackWithSubs(Player aiPlayer, AbilitySub ab) {
|
||||
final AbilitySub subAb = ab.getSubAbility();
|
||||
AiAbilityDecision decision = SpellApiToAi.Converter.get(ab).chkDrawback(ab, aiPlayer);
|
||||
AiAbilityDecision decision = SpellApiToAi.Converter.get(ab).chkDrawback(aiPlayer, ab);
|
||||
if (!decision.willingToPlay()) {
|
||||
return decision;
|
||||
}
|
||||
@@ -262,7 +262,7 @@ public abstract class SpellAbilityAi {
|
||||
/**
|
||||
* Handles the AI decision to play a sub-SpellAbility
|
||||
*/
|
||||
public AiAbilityDecision chkDrawback(final SpellAbility sa, final Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(final Player aiPlayer, final SpellAbility sa) {
|
||||
// sub-SpellAbility might use targets too
|
||||
if (sa.usesTargeting()) {
|
||||
// no Candidates, no adding to Stack
|
||||
@@ -365,14 +365,14 @@ public abstract class SpellAbilityAi {
|
||||
* <p>
|
||||
* Evaluated costs are: life, discard, sacrifice and counter-removal
|
||||
*/
|
||||
protected boolean willPayCosts(final Player ai, final SpellAbility sa, final Cost cost, final Card source) {
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, source, 4, sa)) {
|
||||
protected boolean willPayCosts(final Player payer, final SpellAbility sa, final Cost cost, final Card source) {
|
||||
if (!ComputerUtilCost.checkLifeCost(payer, cost, source, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source, sa)) {
|
||||
if (!ComputerUtilCost.checkDiscardCost(payer, cost, source, sa)) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, source, sa)) {
|
||||
if (!ComputerUtilCost.checkSacrificeCost(payer, cost, source, sa)) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCost.checkRemoveCounterCost(cost, source, sa)) {
|
||||
@@ -381,7 +381,7 @@ public abstract class SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final Card source = sa.getHostCard();
|
||||
final String aiLogic = sa.getParam("UnlessAI");
|
||||
boolean payNever = "Never".equals(aiLogic);
|
||||
@@ -400,7 +400,7 @@ public abstract class SpellAbilityAi {
|
||||
&& (isMine || ComputerUtilCost.checkDiscardCost(payer, cost, source, sa));
|
||||
}
|
||||
|
||||
public List<OptionalCostValue> chooseOptionalCosts(SpellAbility chosen, Player player, List<OptionalCostValue> optionalCostValues) {
|
||||
public List<OptionalCostValue> chooseOptionalCosts(Player payer, SpellAbility chosen, List<OptionalCostValue> optionalCostValues) {
|
||||
List<OptionalCostValue> chosenOptCosts = Lists.newArrayList();
|
||||
Cost costSoFar = chosen.getPayCosts().copy();
|
||||
|
||||
@@ -420,7 +420,7 @@ public abstract class SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
if (ComputerUtilCost.canPayCost(fullCostSa, player, false)) {
|
||||
if (ComputerUtilCost.canPayCost(fullCostSa, payer, false)) {
|
||||
chosenOptCosts.add(opt);
|
||||
costSoFar.add(opt.getCost());
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class ActivateAbilityAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
final Card source = sa.getHostCard();
|
||||
if (!sa.usesTargeting()) {
|
||||
final List<Player> defined = AbilityUtils.getDefinedPlayers(source, sa.getParam("Defined"), sa);
|
||||
|
||||
@@ -234,7 +234,7 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
if (sa.usesTargeting()) {
|
||||
sa.resetTargets();
|
||||
return animateTgtAI(sa);
|
||||
@@ -605,10 +605,10 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
if (sa.isKeyword(Keyword.RIOT)) {
|
||||
return !SpecialAiLogic.preferHasteForRiot(sa, payer);
|
||||
}
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,9 +93,9 @@ public class AssembleContraptionAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
if(getDeck(aiPlayer, sa).isEmpty())
|
||||
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
|
||||
return super.chkDrawback(sa, aiPlayer);
|
||||
return super.chkDrawback(aiPlayer, sa);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -968,7 +968,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(final SpellAbility sa, final Player ai) {
|
||||
public AiAbilityDecision chkDrawback(final Player ai, final SpellAbility sa) {
|
||||
if (sa.isTrigger() && sa.usesTargeting()) {
|
||||
CardCollection targetables = CardLists.getTargetableCards(ai.getCardsIn(ZoneType.Battlefield), sa);
|
||||
CardCollection source = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Object"), sa);
|
||||
|
||||
@@ -54,7 +54,7 @@ public class BecomesBlockedAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
// TODO - implement AI
|
||||
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class CannotPlayAi extends SpellAbilityAi {
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class ChangeCombatantsAi extends SpellAbilityAi {
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
final String logic = sa.getParamOrDefault("AILogic", "");
|
||||
|
||||
if (logic.equals("WeakestOppExceptCtrl")) {
|
||||
|
||||
@@ -45,23 +45,23 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
// cards where multiple cards are fetched at once and they need to be coordinated
|
||||
private static CardCollection multipleCardsToChoose = new CardCollection();
|
||||
|
||||
protected boolean willPayCosts(Player ai, SpellAbility sa, Cost cost, Card source) {
|
||||
protected boolean willPayCosts(Player payer, SpellAbility sa, Cost cost, Card source) {
|
||||
if (sa.isHidden()) {
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, source, sa)
|
||||
if (!ComputerUtilCost.checkSacrificeCost(payer, cost, source, sa)
|
||||
&& !"Battlefield".equals(sa.getParam("Destination")) && !source.isLand()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, source, 4, sa)) {
|
||||
if (!ComputerUtilCost.checkLifeCost(payer, cost, source, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source, sa)) {
|
||||
if (!ComputerUtilCost.checkDiscardCost(payer, cost, source, sa)) {
|
||||
for (final CostPart part : cost.getCostParts()) {
|
||||
if (part instanceof CostDiscard) {
|
||||
CostDiscard cd = (CostDiscard) part;
|
||||
// this is mainly for typecycling
|
||||
if (!cd.payCostFromSource() || !ComputerUtil.isWorseThanDraw(ai, source)) {
|
||||
if (!cd.payCostFromSource() || !ComputerUtil.isWorseThanDraw(payer, source)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
}
|
||||
int amt = part.getAbilityAmount(sa);
|
||||
needed += amt;
|
||||
CardCollection toAdd = ComputerUtil.chooseExileFrom(ai, (CostExile) part, source, amt, sa, true);
|
||||
CardCollection toAdd = ComputerUtil.chooseExileFrom(payer, (CostExile) part, source, amt, sa, true);
|
||||
if (toAdd != null) {
|
||||
payingCards.addAll(toAdd);
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayCosts(ai, sa, cost, source);
|
||||
return super.willPayCosts(payer, sa, cost, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,13 +198,12 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
* <p>
|
||||
* changeZonePlayDrawbackAI.
|
||||
* </p>
|
||||
* @param sa
|
||||
* a {@link forge.game.spellability.SpellAbility} object.
|
||||
*
|
||||
* @param sa a {@link SpellAbility} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
if (sa.isHidden()) {
|
||||
return hiddenOriginPlayDrawbackAI(aiPlayer, sa);
|
||||
}
|
||||
@@ -2105,7 +2104,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final Card host = sa.getHostCard();
|
||||
|
||||
int lifeLoss = 0;
|
||||
@@ -2132,6 +2131,6 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,15 +237,13 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
||||
* <p>
|
||||
* changeZoneAllPlayDrawbackAI.
|
||||
* </p>
|
||||
* @param sa
|
||||
* a {@link forge.game.spellability.SpellAbility} object.
|
||||
* @param aiPlayer
|
||||
* a {@link forge.game.player.Player} object.
|
||||
*
|
||||
*
|
||||
* @param aiPlayer a {@link Player} object.
|
||||
* @param sa a {@link SpellAbility} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
// if putting cards from hand to library and parent is drawing cards
|
||||
// make sure this will actually do something:
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ public class ChooseCardAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
if (sa.hasParam("AILogic") && !checkAiLogic(ai, sa, sa.getParam("AILogic"))) {
|
||||
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class ChooseDirectionAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return canPlay(ai, sa);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ public class ChooseGenericAi extends SpellAbilityAi {
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
AiAbilityDecision decision;
|
||||
if (sa.isTrigger()) {
|
||||
decision = doTriggerNoCost(aiPlayer, sa, sa.isMandatory());
|
||||
@@ -99,7 +99,7 @@ public class ChooseGenericAi extends SpellAbilityAi {
|
||||
String unlessCost = sp.getParam("UnlessCost");
|
||||
sp.setActivatingPlayer(sa.getActivatingPlayer());
|
||||
Cost unless = new Cost(unlessCost, false);
|
||||
if (SpellApiToAi.Converter.get(sp).willPayUnlessCost(sp, player, unless, false, new FCollection<>(player))
|
||||
if (SpellApiToAi.Converter.get(sp).willPayUnlessCost(player, sp, unless, false, new FCollection<>(player))
|
||||
&& ComputerUtilCost.canPayCost(unless, sp, player, true)) {
|
||||
return sp;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class ChoosePlayerAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return canPlay(ai, sa);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ public class CloneAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
// AI should only activate this during Human's turn
|
||||
boolean chance = true;
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public class ControlExchangeAi extends SpellAbilityAi {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
} else if (mandatory) {
|
||||
AiAbilityDecision decision = chkDrawback(sa, aiPlayer);
|
||||
AiAbilityDecision decision = chkDrawback(aiPlayer, sa);
|
||||
if (sa.isTargetNumberValid()) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class ControlExchangeAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
if (!sa.usesTargeting()) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
|
||||
@@ -299,12 +299,12 @@ public class ControlGainAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, final Player ai) {
|
||||
public AiAbilityDecision chkDrawback(final Player ai, SpellAbility sa) {
|
||||
final Game game = ai.getGame();
|
||||
|
||||
// Special card logic that is processed elsewhere
|
||||
if (sa.hasParam("AILogic")) {
|
||||
if (("DonateTargetPerm").equals(sa.getParam("AILogic"))) {
|
||||
if ("DonateTargetPerm".equals(sa.getParam("AILogic"))) {
|
||||
// Donate step 2 - target a donatable permanent.
|
||||
return SpecialCardAi.Donate.considerDonatingPermanent(ai, sa);
|
||||
}
|
||||
@@ -346,7 +346,7 @@ public class ControlGainAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
// Pay to gain Control
|
||||
if (sa.hasParam("UnlessSwitched")) {
|
||||
final Card host = sa.getHostCard();
|
||||
@@ -360,6 +360,6 @@ public class ControlGainAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public class CopySpellAbilityAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(final SpellAbility sa, final Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(final Player aiPlayer, final SpellAbility sa) {
|
||||
if ("ChainOfSmog".equals(sa.getParam("AILogic"))) {
|
||||
return SpecialCardAi.ChainOfSmog.consider(aiPlayer, sa);
|
||||
}
|
||||
@@ -132,7 +132,7 @@ public class CopySpellAbilityAi extends SpellAbilityAi {
|
||||
AiAbilityDecision decision = canPlay(aiPlayer, sa);
|
||||
if (!decision.willingToPlay()) {
|
||||
if (sa.isMandatory()) {
|
||||
return super.chkDrawback(sa, aiPlayer);
|
||||
return super.chkDrawback(aiPlayer, sa);
|
||||
}
|
||||
}
|
||||
return decision;
|
||||
@@ -156,7 +156,7 @@ public class CopySpellAbilityAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final String aiLogic = sa.getParam("UnlessAI");
|
||||
if ("Never".equals(aiLogic)) { return false; }
|
||||
|
||||
@@ -172,6 +172,6 @@ public class CopySpellAbilityAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ public class CounterAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
return doTriggerNoCost(aiPlayer, sa, true);
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ public class CounterAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final Card source = sa.getHostCard();
|
||||
final Game game = source.getGame();
|
||||
List<SpellAbility> spells = AbilityUtils.getDefinedSpellAbilities(source, sa.getParamOrDefault("Defined", "Targeted"), sa);
|
||||
@@ -388,6 +388,6 @@ public class CounterAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ public class CountersMoveAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
if (sa.usesTargeting()) {
|
||||
sa.resetTargets();
|
||||
return moveTgtAI(ai, sa);
|
||||
|
||||
@@ -93,7 +93,7 @@ public class CountersProliferateAi extends SpellAbilityAi {
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
if ("Always".equals(sa.getParam("AILogic"))) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
|
||||
@@ -44,11 +44,11 @@ public class CountersPutAi extends CountersAi {
|
||||
* forge.game.card.Card)
|
||||
*/
|
||||
@Override
|
||||
protected boolean willPayCosts(Player ai, SpellAbility sa, Cost cost, Card source) {
|
||||
protected boolean willPayCosts(Player payer, SpellAbility sa, Cost cost, Card source) {
|
||||
final String type = sa.getParam("CounterType");
|
||||
final String aiLogic = sa.getParamOrDefault("AILogic", "");
|
||||
|
||||
if (!super.willPayCosts(ai, sa, cost, source)) {
|
||||
if (!super.willPayCosts(payer, sa, cost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -669,7 +669,7 @@ public class CountersPutAi extends CountersAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(final SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, final SpellAbility sa) {
|
||||
final Game game = ai.getGame();
|
||||
Card choice = null;
|
||||
final String type = sa.getParam("CounterType");
|
||||
|
||||
@@ -115,7 +115,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return canPlay(ai, sa);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -175,7 +175,7 @@ public class DamageAllAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
final Card source = sa.getHostCard();
|
||||
final String validP = sa.getParamOrDefault("ValidPlayers", "");
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ import java.util.Map;
|
||||
|
||||
public class DamageDealAi extends DamageAiBase {
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
final SpellAbility root = sa.getRootAbility();
|
||||
final String damage = sa.getParam("NumDmg");
|
||||
Card source = sa.getHostCard();
|
||||
@@ -1165,8 +1165,8 @@ public class DamageDealAi extends DamageAiBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid,
|
||||
FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid,
|
||||
FCollectionView<Player> payers) {
|
||||
if (!payer.canLoseLife() || payer.cantLoseForZeroOrLessLife()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1185,6 +1185,6 @@ public class DamageDealAi extends DamageAiBase {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class DamageEachAi extends DamageAiBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
// check AI life before playing this drawback?
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class DebuffAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
if (!sa.usesTargeting()) {
|
||||
// TODO - copied from AF_Pump.pumpDrawbackAI() - what should be here?
|
||||
} else {
|
||||
|
||||
@@ -15,7 +15,7 @@ import forge.game.zone.ZoneType;
|
||||
public class DelayedTriggerAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
if ("Always".equals(sa.getParam("AILogic"))) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import forge.util.collect.FCollectionView;
|
||||
|
||||
public class DestroyAi extends SpellAbilityAi {
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return checkApiLogic(ai, sa);
|
||||
}
|
||||
|
||||
@@ -454,7 +454,7 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final Card host = sa.getHostCard();
|
||||
if (alreadyPaid) {
|
||||
return false;
|
||||
@@ -467,6 +467,6 @@ public class DestroyAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class DestroyAllAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
return doMassRemovalLogic(aiPlayer, sa);
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ public class DestroyAllAi extends SpellAbilityAi {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final Card source = sa.getHostCard();
|
||||
if (payers.size() > 1) {
|
||||
if (alreadyPaid) {
|
||||
@@ -206,6 +206,6 @@ public class DestroyAllAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ public class DigAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
// TODO: improve this check in ways that may be specific to a subability
|
||||
return canPlay(aiPlayer, sa);
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ public class DiscardAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
// Drawback AI improvements
|
||||
// if parent draws cards, make sure cards in hand + cards drawn > 0
|
||||
if (sa.usesTargeting()) {
|
||||
@@ -219,7 +219,7 @@ public class DiscardAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final Card host = sa.getHostCard();
|
||||
final String aiLogic = sa.getParam("UnlessAI");
|
||||
if ("Never".equals(aiLogic)) { return false; }
|
||||
@@ -268,6 +268,6 @@ public class DiscardAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class DrainManaAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
// AI cannot use this properly until he can use SAs during Humans turn
|
||||
final Card source = sa.getHostCard();
|
||||
|
||||
|
||||
@@ -87,24 +87,24 @@ public class DrawAi extends SpellAbilityAi {
|
||||
* forge.game.card.Card)
|
||||
*/
|
||||
@Override
|
||||
protected boolean willPayCosts(Player ai, SpellAbility sa, Cost cost, Card source) {
|
||||
if (!ComputerUtilCost.checkCreatureSacrificeCost(ai, cost, source, sa)) {
|
||||
protected boolean willPayCosts(Player payer, SpellAbility sa, Cost cost, Card source) {
|
||||
if (!ComputerUtilCost.checkCreatureSacrificeCost(payer, cost, source, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, source, 4, sa)) {
|
||||
if (!ComputerUtilCost.checkLifeCost(payer, cost, source, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source, sa)) {
|
||||
AiCostDecision aiDecisions = new AiCostDecision(ai, sa, false);
|
||||
if (!ComputerUtilCost.checkDiscardCost(payer, cost, source, sa)) {
|
||||
AiCostDecision aiDecisions = new AiCostDecision(payer, sa, false);
|
||||
for (final CostPart part : cost.getCostParts()) {
|
||||
if (part instanceof CostDiscard) {
|
||||
PaymentDecision decision = part.accept(aiDecisions);
|
||||
if (null == decision)
|
||||
return false;
|
||||
for (Card discard : decision.cards) {
|
||||
if (!ComputerUtil.isWorseThanDraw(ai, discard)) {
|
||||
if (!ComputerUtil.isWorseThanDraw(payer, discard)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,7 @@ public class DrawAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
if (targetAI(ai, sa, sa.isTrigger() && sa.getHostCard().isInPlay())) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
@@ -558,7 +558,7 @@ public class DrawAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final Card host = sa.getHostCard();
|
||||
final String aiLogic = sa.getParam("UnlessAI");
|
||||
|
||||
@@ -586,6 +586,6 @@ public class DrawAi extends SpellAbilityAi {
|
||||
}
|
||||
// TODO add logic for Discard + Draw Effects
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,7 +640,7 @@ public class EffectAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final String aiLogic = sa.getParam("UnlessAI");
|
||||
if ("WillAttack".equals(aiLogic)) {
|
||||
// TODO use AiController::getPredictedCombat
|
||||
@@ -651,6 +651,6 @@ public class EffectAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public final class EncodeAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public class EndTurnAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) { return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi); }
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) { return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi); }
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||
|
||||
@@ -108,7 +108,7 @@ public class FightAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(final SpellAbility sa, final Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(final Player aiPlayer, final SpellAbility sa) {
|
||||
if ("Always".equals(sa.getParam("AILogic"))) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay); // e.g. Hunt the Weak, the AI logic was already checked through canFightAi
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class FlipACoinAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return canPlay(ai, sa);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ public class FogAi extends SpellAbilityAi {
|
||||
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
// AI should only activate this during Human's turn
|
||||
boolean chance;
|
||||
final Game game = ai.getGame();
|
||||
|
||||
@@ -10,7 +10,7 @@ public class ImmediateTriggerAi extends SpellAbilityAi {
|
||||
// TODO: this class is largely reused from DelayedTriggerAi, consider updating
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
String logic = sa.getParamOrDefault("AILogic", "");
|
||||
if (logic.equals("Always")) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
|
||||
@@ -29,7 +29,7 @@ public class LearnAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
return canPlay(aiPlayer, sa);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,27 +26,27 @@ public class LifeGainAi extends SpellAbilityAi {
|
||||
* forge.game.card.Card)
|
||||
*/
|
||||
@Override
|
||||
protected boolean willPayCosts(Player ai, SpellAbility sa, Cost cost, Card source) {
|
||||
protected boolean willPayCosts(Player payer, SpellAbility sa, Cost cost, Card source) {
|
||||
final Game game = source.getGame();
|
||||
final PhaseHandler ph = game.getPhaseHandler();
|
||||
final int life = ai.getLife();
|
||||
final int life = payer.getLife();
|
||||
|
||||
boolean lifeCritical = life <= 5 || (ph.getPhase().isBefore(PhaseType.COMBAT_DAMAGE)
|
||||
&& ComputerUtilCombat.lifeInDanger(ai, game.getCombat()));
|
||||
&& ComputerUtilCombat.lifeInDanger(payer, game.getCombat()));
|
||||
|
||||
if (!lifeCritical) {
|
||||
// return super.willPayCosts(ai, sa, cost, source);
|
||||
if ("CriticalOnly".equals(sa.getParam("AILogic"))) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, source, sa, false)) {
|
||||
if (!ComputerUtilCost.checkSacrificeCost(payer, cost, source, sa, false)) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, source, 4, sa)) {
|
||||
if (!ComputerUtilCost.checkLifeCost(payer, cost, source, 4, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, cost, source, sa)) {
|
||||
if (!ComputerUtilCost.checkDiscardCost(payer, cost, source, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class LifeGainAi extends SpellAbilityAi {
|
||||
} else {
|
||||
// don't sac possible blockers
|
||||
if (!ph.getPhase().equals(PhaseType.COMBAT_DECLARE_BLOCKERS)
|
||||
|| !game.getCombat().getDefenders().contains(ai)) {
|
||||
|| !game.getCombat().getDefenders().contains(payer)) {
|
||||
boolean skipCheck = false;
|
||||
// if it's a sac self cost and the effect source is not a
|
||||
// creature, skip this check
|
||||
@@ -64,7 +64,7 @@ public class LifeGainAi extends SpellAbilityAi {
|
||||
skipCheck |= ComputerUtilCost.isSacrificeSelfCost(cost) && !source.isCreature();
|
||||
|
||||
if (!skipCheck) {
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, cost, source, sa,false)) {
|
||||
if (!ComputerUtilCost.checkSacrificeCost(payer, cost, source, sa,false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -217,7 +217,7 @@ public class LifeGainAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return doTriggerNoCost(ai, sa, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public class LifeLoseAi extends SpellAbilityAi {
|
||||
* SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
final PlayerCollection tgtPlayers = getPlayers(ai, sa);
|
||||
|
||||
final Card source = sa.getHostCard();
|
||||
@@ -67,24 +67,24 @@ public class LifeLoseAi extends SpellAbilityAi {
|
||||
* forge.game.card.Card)
|
||||
*/
|
||||
@Override
|
||||
protected boolean willPayCosts(Player ai, SpellAbility sa, Cost cost, Card source) {
|
||||
protected boolean willPayCosts(Player payer, SpellAbility sa, Cost cost, Card source) {
|
||||
final String amountStr = sa.getParam("LifeAmount");
|
||||
int amount = 0;
|
||||
|
||||
if (amountStr.equals("X") && sa.getSVar(amountStr).equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
amount = ComputerUtilCost.getMaxXValue(sa, ai, sa.isTrigger());
|
||||
amount = ComputerUtilCost.getMaxXValue(sa, payer, sa.isTrigger());
|
||||
} else {
|
||||
amount = AbilityUtils.calculateAmount(source, amountStr, sa);
|
||||
}
|
||||
|
||||
// special logic for checkLifeCost
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, cost, source, amount, sa)) {
|
||||
if (!ComputerUtilCost.checkLifeCost(payer, cost, source, amount, sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// other cost as the same
|
||||
return super.willPayCosts(ai, sa, cost, source);
|
||||
return super.willPayCosts(payer, sa, cost, source);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -200,8 +200,8 @@ public class LifeLoseAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid,
|
||||
FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid,
|
||||
FCollectionView<Player> payers) {
|
||||
if (!payer.canLoseLife() || payer.cantLoseForZeroOrLessLife()) {
|
||||
return false;
|
||||
}
|
||||
@@ -224,7 +224,7 @@ public class LifeLoseAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
|
||||
protected boolean doTgt(Player ai, SpellAbility sa, boolean mandatory) {
|
||||
|
||||
@@ -157,7 +157,7 @@ public class MillAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
return targetAI(aiPlayer, sa, true) ? new AiAbilityDecision(100, AiPlayDecision.WillPlay) : new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public class MustBlockAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
if (sa.hasParam("DefinedAttacker")) {
|
||||
// The AI can't handle "target creature blocks another target creature" abilities yet
|
||||
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
|
||||
|
||||
@@ -80,7 +80,7 @@ public class PhasesAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
|
||||
if (tgt != null) {
|
||||
|
||||
@@ -329,7 +329,7 @@ public class ProtectAi extends SpellAbilityAi {
|
||||
} // protectTriggerAI
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
if (sa.usesTargeting()) {
|
||||
return protectTgtAI(ai, sa, false);
|
||||
}
|
||||
|
||||
@@ -665,7 +665,7 @@ public class PumpAi extends PumpAiBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
final SpellAbility root = sa.getRootAbility();
|
||||
final Card source = sa.getHostCard();
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ public class PumpAllAi extends PumpAiBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public class RemoveFromCombatAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
// AI should only activate this during Human's turn
|
||||
|
||||
if ("RemoveBestAttacker".equals(sa.getParam("AILogic"))) {
|
||||
|
||||
@@ -43,7 +43,7 @@ public abstract class RevealAiBase extends SpellAbilityAi {
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
revealHandTargetAI(ai, sa, false);
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ public class RollPlanarDiceAi extends SpellAbilityAi {
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
// for potential implementation of drawback checks?
|
||||
return canPlay(aiPlayer, sa);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class SacrificeAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
// AI should only activate this during Human's turn
|
||||
|
||||
return sacrificeTgtAI(ai, sa, false);
|
||||
@@ -211,7 +211,7 @@ public class SacrificeAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
// Icy Prison
|
||||
if (payers.size() > 1) {
|
||||
final Player p = sa.getActivatingPlayer();
|
||||
@@ -221,6 +221,6 @@ public class SacrificeAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class SacrificeAllAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
//TODO: Add checks for bad outcome
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ public class ScryAi extends SpellAbilityAi {
|
||||
} // scryTargetAI()
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return doTriggerNoCost(ai, sa, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public class SetStateAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
// Gross generalization, but this always considers alternate states more powerful
|
||||
return sa.getHostCard().isInAlternateState() ? new AiAbilityDecision(0, AiPlayDecision.CantPlayAi) : new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class ShuffleAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
return shuffleTargetAI(sa);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public class SkipTurnAi extends SpellAbilityAi {
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
return canPlay(aiPlayer, sa);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class StoreSVarAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
// Join Forces cards
|
||||
if (sa.hasParam("UnlessSwitched") && payers.size() > 1) {
|
||||
final Player p = sa.getActivatingPlayer();
|
||||
@@ -39,6 +39,6 @@ public class StoreSVarAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class SurveilAi extends SpellAbilityAi {
|
||||
* @see forge.ai.SpellAbilityAi#chkAIDrawback(forge.game.spellability.SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return doTriggerNoCost(ai, sa, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import forge.game.zone.ZoneType;
|
||||
import forge.util.collect.FCollectionView;
|
||||
|
||||
public class TapAi extends TapAiBase {
|
||||
|
||||
@Override
|
||||
protected AiAbilityDecision checkApiLogic(Player ai, SpellAbility sa) {
|
||||
final PhaseHandler phase = ai.getGame().getPhaseHandler();
|
||||
@@ -43,7 +44,6 @@ public class TapAi extends TapAiBase {
|
||||
}
|
||||
|
||||
final Card source = sa.getHostCard();
|
||||
final Cost abCost = sa.getPayCosts();
|
||||
|
||||
final String aiLogic = sa.getParamOrDefault("AILogic", "");
|
||||
if ("GoblinPolkaBand".equals(aiLogic)) {
|
||||
@@ -52,7 +52,20 @@ public class TapAi extends TapAiBase {
|
||||
return SpecialCardAi.Arena.consider(ai, sa);
|
||||
}
|
||||
|
||||
if (!sa.usesTargeting()) {
|
||||
if (sa.usesTargeting()) {
|
||||
// X controls the minimum targets
|
||||
if ("X".equals(sa.getTargetRestrictions().getMinTargets()) && sa.getSVar("X").equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
// TODO need to set XManaCostPaid for targets, maybe doesn't need PayX anymore?
|
||||
sa.setXManaCostPaid(ComputerUtilCost.getMaxXValue(sa, ai, sa.isTrigger()));
|
||||
}
|
||||
|
||||
sa.resetTargets();
|
||||
if (tapPrefTargeting(ai, source, sa, false)) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
}
|
||||
return new AiAbilityDecision(0, AiPlayDecision.TargetingFailed);
|
||||
} else {
|
||||
CardCollection untap;
|
||||
if (sa.hasParam("CardChoices")) {
|
||||
untap = CardLists.getValidCards(source.getGame().getCardsIn(ZoneType.Battlefield), sa.getParam("CardChoices"), ai, source, sa);
|
||||
@@ -69,28 +82,13 @@ public class TapAi extends TapAiBase {
|
||||
|
||||
if (value > 0) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
} else {
|
||||
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
|
||||
}
|
||||
} else {
|
||||
// X controls the minimum targets
|
||||
if ("X".equals(sa.getTargetRestrictions().getMinTargets()) && sa.getSVar("X").equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
// TODO need to set XManaCostPaid for targets, maybe doesn't need PayX anymore?
|
||||
sa.setXManaCostPaid(ComputerUtilCost.getMaxXValue(sa, ai, sa.isTrigger()));
|
||||
}
|
||||
|
||||
sa.resetTargets();
|
||||
if (tapPrefTargeting(ai, source, sa, false)) {
|
||||
return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
|
||||
} else {
|
||||
return new AiAbilityDecision(0, AiPlayDecision.TargetingFailed);
|
||||
}
|
||||
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
// Check for shocklands and similar ETB replacement effects
|
||||
if (sa.hasParam("ETB")) {
|
||||
final Card source = sa.getHostCard();
|
||||
@@ -134,6 +132,6 @@ public class TapAi extends TapAiBase {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
final Card source = sa.getHostCard();
|
||||
final boolean oppTargetsChoice = sa.hasParam("TargetingPlayer");
|
||||
|
||||
|
||||
@@ -409,7 +409,7 @@ public class TokenAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
final Card source = sa.getHostCard();
|
||||
Player p = sa.getActivatingPlayer();
|
||||
if (sa.isKeyword(Keyword.FABRICATE)) {
|
||||
@@ -508,6 +508,6 @@ public class TokenAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class UnattachAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
return doTriggerNoCost(ai, sa, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,12 +42,12 @@ public class UntapAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean willPayCosts(final Player ai, final SpellAbility sa, final Cost cost, final Card source) {
|
||||
protected boolean willPayCosts(final Player payer, final SpellAbility sa, final Cost cost, final Card source) {
|
||||
if (!ComputerUtilCost.checkAddM1M1CounterCost(cost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ComputerUtilCost.checkDiscardCost(ai, cost, source, sa);
|
||||
return ComputerUtilCost.checkDiscardCost(payer, cost, source, sa);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,7 +102,7 @@ public class UntapAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player ai) {
|
||||
public AiAbilityDecision chkDrawback(Player ai, SpellAbility sa) {
|
||||
if (!sa.usesTargeting()) {
|
||||
// who cares if its already untapped, it's only a subability?
|
||||
} else {
|
||||
@@ -471,7 +471,7 @@ public class UntapAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
public boolean willPayUnlessCost(Player payer, SpellAbility sa, Cost cost, boolean alreadyPaid, FCollectionView<Player> payers) {
|
||||
// Paralyze effects
|
||||
if (sa.hasParam("UnlessSwitched")) {
|
||||
final Card host = sa.getHostCard();
|
||||
@@ -493,6 +493,6 @@ public class UntapAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
return super.willPayUnlessCost(sa, payer, cost, alreadyPaid, payers);
|
||||
return super.willPayUnlessCost(payer, sa, cost, alreadyPaid, payers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class VoteAi extends SpellAbilityAi {
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#chkAIDrawback(java.util.Map, forge.card.spellability.SpellAbility, forge.game.player.Player)
|
||||
*/
|
||||
@Override
|
||||
public AiAbilityDecision chkDrawback(SpellAbility sa, Player aiPlayer) {
|
||||
public AiAbilityDecision chkDrawback(Player aiPlayer, SpellAbility sa) {
|
||||
return canPlay(aiPlayer, sa);
|
||||
}
|
||||
|
||||
|
||||
@@ -550,20 +550,20 @@ public class CountersPutEffect extends SpellAbilityEffect {
|
||||
if (sa.hasParam("Monstrosity")) {
|
||||
gameCard.setMonstrous(true);
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(gameCard);
|
||||
// CR 701.37c
|
||||
runParams.put(AbilityKey.MonstrosityAmount, counterAmount);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.BecomeMonstrous, runParams, false);
|
||||
}
|
||||
if (sa.isKeyword(Keyword.RENOWN)) {
|
||||
gameCard.setRenowned(true);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.BecomeRenowned,
|
||||
AbilityKey.mapFromCard(gameCard), false);
|
||||
}
|
||||
if (sa.hasParam("Adapt")) {
|
||||
game.getTriggerHandler().runTrigger(TriggerType.Adapt, AbilityKey.mapFromCard(gameCard), false);
|
||||
}
|
||||
if (sa.isKeyword(Keyword.RENOWN)) {
|
||||
gameCard.setRenowned(true);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.BecomeRenowned, AbilityKey.mapFromCard(gameCard), false);
|
||||
}
|
||||
if (sa.isKeyword(Keyword.MENTOR)) {
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(gameCard);
|
||||
runParams.put(AbilityKey.Source, sa.getHostCard());
|
||||
runParams.put(AbilityKey.Source, card);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.Mentored, runParams, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@ Name:Act of Treason
|
||||
ManaCost:2 R
|
||||
Types:Sorcery
|
||||
A:SP$ GainControl | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SpellDescription$ Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.
|
||||
SVar:PlayMain1:OPPONENTCREATURES
|
||||
SVar:PlayMain1:ALWAYS
|
||||
Oracle:Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. (It can attack and {T} this turn.)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Bloodsoaked Insight
|
||||
ManaCost:5 BR BR
|
||||
Types:Sorcery
|
||||
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Activator$ You | Amount$ X | EffectZone$ All | Description$ This spell costs {1} less to cast for each 1 life your opponents have lost this turn.
|
||||
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ This spell costs {1} less to cast for each 1 life your opponents have lost this turn.
|
||||
SVar:X:Count$LifeOppsLostThisTurn
|
||||
A:SP$ Dig | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | DigNum$ 3 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True | SubAbility$ DBEffect | SpellDescription$ Target opponent exiles the top three cards of their library. Until the end of your next turn, you may play those cards. If you cast a spell this way, mana of any type can be spent to cast it.
|
||||
SVar:DBEffect:DB$ Effect | RememberObjects$ Remembered | StaticAbilities$ STLookPlay | Duration$ UntilTheEndOfYourNextTurn | ForgetOnMoved$ Exile | SubAbility$ DBCleanup
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Hatching Plans
|
||||
ManaCost:1 U
|
||||
Types:Enchantment
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME is put into a graveyard from the battlefield, draw three cards.
|
||||
SVar:TrigDraw:DB$ Draw | Defined$ TriggeredCardController | NumCards$ 3
|
||||
SVar:TrigDraw:DB$ Draw | NumCards$ 3
|
||||
SVar:SacMe:5
|
||||
AI:RemoveDeck:Random
|
||||
Oracle:When Hatching Plans is put into a graveyard from the battlefield, draw three cards.
|
||||
|
||||
@@ -3,6 +3,6 @@ ManaCost:2 R
|
||||
Types:Sorcery
|
||||
A:SP$ GainControl | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SubAbility$ DBScry | SpellDescription$ Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. If you control a Wolf or Werewolf, scry 2.
|
||||
SVar:DBScry:DB$ Scry | ScryNum$ 2 | ConditionPresent$ Wolf.YouCtrl,Werewolf.YouCtrl | StackDescription$ If you control a Wolf or Werewolf, scry 2. (Look at the top two cards of your library, then put any number of them on the bottom of your library and the rest on top in any order.)
|
||||
SVar:PlayMain1:OPPONENTCREATURES
|
||||
SVar:PlayMain1:ALWAYS
|
||||
DeckHints:Type$Wolf|Werewolf
|
||||
Oracle:Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. If you control a Wolf or Werewolf, scry 2. (Look at the top two cards of your library, then put any number of them on the bottom of your library and the rest on top in any order.)
|
||||
|
||||
@@ -3,6 +3,6 @@ ManaCost:3 R
|
||||
Types:Sorcery
|
||||
A:SP$ GainControl | ValidTgts$ Creature,Artifact | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SubAbility$ DBToken | SpellDescription$ Gain control of target artifact or creature until end of turn. Untap it. It gains haste until end of turn. Create a tapped Powerstone token. (It's an artifact with "{T}: Add {C}. This mana can't be spent to cast a nonartifact spell.")
|
||||
SVar:DBToken:DB$ Token | TokenTapped$ True | TokenScript$ c_a_powerstone
|
||||
SVar:PlayMain1:OPPONENTCREATURES
|
||||
SVar:PlayMain1:ALWAYS
|
||||
DeckHas:Ability$Token & Type$Artifact
|
||||
Oracle:Gain control of target artifact or creature until end of turn. Untap it. It gains haste until end of turn. Create a tapped Powerstone token. (It's an artifact with "{T}: Add {C}. This mana can't be spent to cast a nonartifact spell.")
|
||||
|
||||
@@ -3,5 +3,5 @@ ManaCost:2 R
|
||||
Types:Sorcery
|
||||
S:Mode$ Continuous | CharacteristicDefining$ True | AddKeyword$ Flash | CheckSVar$ Count$CommittedCrimeThisTurn.1.0 | Description$ CARDNAME has flash as long as you've committed a crime this turn. (Targeting opponents, anything they control, and/or cards in their graveyards is a crime.)
|
||||
A:SP$ GainControl | ValidTgts$ Creature | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SpellDescription$ Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.
|
||||
SVar:PlayMain1:OPPONENTCREATURES
|
||||
SVar:PlayMain1:ALWAYS
|
||||
Oracle:Take for a Ride has flash as long as you've committed a crime this turn. (Targeting opponents, anything they control, and/or cards in their graveyards is a crime.)\nGain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.
|
||||
|
||||
@@ -3,5 +3,5 @@ ManaCost:2 R
|
||||
Types:Sorcery
|
||||
A:SP$ GainControl | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SubAbility$ DBDraw | SpellDescription$ Gain control of target creature until end of turn. Untap it. It gains haste until end of turn. You may discard a card. If you do, draw a card.
|
||||
SVar:DBDraw:DB$ Draw | UnlessCost$ Discard<1/Card> | UnlessSwitched$ True | UnlessPayer$ You
|
||||
SVar:PlayMain1:OPPONENTCREATURES
|
||||
SVar:PlayMain1:ALWAYS
|
||||
Oracle:Gain control of target creature until end of turn. Untap it. It gains haste until end of turn. You may discard a card. If you do, draw a card.
|
||||
|
||||
Reference in New Issue
Block a user