Improve Ward checking

This commit is contained in:
tool4EvEr
2021-10-31 10:07:35 +01:00
parent b580daee8e
commit bc7867c58c
11 changed files with 29 additions and 25 deletions

View File

@@ -733,20 +733,6 @@ public class AiController {
AiPlayDecision canPlay = canPlaySa(sa); // this is the "heaviest" check, which also sets up targets, defines X, etc.
// Account for possible Ward after the spell is fully targeted
// TODO: ideally, this should be done while targeting, so that a different target can be preferred if the best
// one is warded and can't be paid for.
if (sa.usesTargeting()) {
for (Card tgt : sa.getTargets().getTargetCards()) {
if (tgt.hasKeyword(Keyword.WARD)) {
int amount = tgt.getKeywordMagnitude(Keyword.WARD);
if (amount > 0 && !ComputerUtilCost.canPayCost(sa, player)) {
return AiPlayDecision.CantAfford;
}
}
}
}
if (sa.getCardState() != null && !sa.getHostCard().isInPlay() && sa.getCardState().getStateName() == CardStateName.Modal) {
sa.getHostCard().setState(CardStateName.Original, false);
}
@@ -755,6 +741,20 @@ public class AiController {
return canPlay;
}
// Account for possible Ward after the spell is fully targeted
// TODO: ideally, this should be done while targeting, so that a different target can be preferred if the best
// one is warded and can't be paid for.
if (sa.usesTargeting()) {
for (Card tgt : sa.getTargets().getTargetCards()) {
if (tgt.hasKeyword(Keyword.WARD) && tgt.getController().isOpponentOf(sa.getHostCard().getController())) {
int amount = tgt.getKeywordMagnitude(Keyword.WARD);
if (amount > 0 && !ComputerUtilCost.canPayCost(sa, player)) {
return AiPlayDecision.CantAfford;
}
}
}
}
// check if some target raised cost
if (oldCMC > -1) {
int finalCMC = CostAdjustment.adjust(sa.getPayCosts(), sa).getTotalMana().getCMC();

View File

@@ -289,7 +289,7 @@ public class ComputerUtil {
final Card source = newSA.getHostCard();
if (newSA.isSpell() && !source.isCopiedSpell()) {
newSA.setHostCard(game.getAction().moveToStack(source, sa));
newSA.setHostCard(game.getAction().moveToStack(source, newSA));
if (newSA.getApi() == ApiType.Charm && !newSA.isWrapper()) {
if (!CharmEffect.makeChoices(newSA)) {

View File

@@ -592,7 +592,7 @@ public class ComputerUtilCost {
// Ward - will be accounted for when rechecking a targeted ability
if (sa.usesTargeting()) {
for (Card tgt : sa.getTargets().getTargetCards()) {
if (tgt.hasKeyword(Keyword.WARD)) {
if (tgt.hasKeyword(Keyword.WARD) && tgt.getController().isOpponentOf(sa.getHostCard().getController())) {
extraManaNeeded += tgt.getKeywordMagnitude(Keyword.WARD);
}
}

View File

@@ -492,4 +492,10 @@ public class CountersMoveAi extends SpellAbilityAi {
// like keeping the last counter on a 0/0 creature
return max;
}
@Override
public CounterType chooseCounterType(List<CounterType> options, SpellAbility sa, Map<String, Object> params) {
// TODO
return super.chooseCounterType(options, sa, params);
}
}

View File

@@ -144,7 +144,6 @@ public class CountersRemoveAi extends SpellAbilityAi {
sa.getTargets().add(ComputerUtilCard.getBestPlaneswalkerAI(planeswalkerList));
return true;
}
} else if (type.matches("Any")) {
// variable amount for Hex Parasite
int amount;
@@ -264,7 +263,6 @@ public class CountersRemoveAi extends SpellAbilityAi {
sa.getTargets().add(ComputerUtilCard.getBestCreatureAI(aiList));
return true;
}
} else if (type.equals("P1P1")) {
// no special amount for that one yet
int amount = AbilityUtils.calculateAmount(source, amountStr, sa);
@@ -298,7 +296,6 @@ public class CountersRemoveAi extends SpellAbilityAi {
return true;
}
}
} else if (type.equals("TIME")) {
int amount;
boolean xPay = false;

View File

@@ -94,7 +94,7 @@ public class PumpAi extends PumpAiBase {
return true;
}
return ph.getNextTurn().equals(ai) && !ph.getPhase().isBefore(PhaseType.END_OF_TURN);
return SpellAbilityAi.isSorcerySpeed(sa) || (ph.getNextTurn().equals(ai) && !ph.getPhase().isBefore(PhaseType.END_OF_TURN));
} else if (logic.equals("Aristocrat")) {
final boolean isThreatened = ComputerUtil.predictThreatenedObjects(ai, null, true).contains(sa.getHostCard());
if (!ph.is(PhaseType.COMBAT_DECLARE_BLOCKERS) && !isThreatened) {

View File

@@ -105,6 +105,7 @@ public final class GameActionUtil {
lkicheck = true;
}
// 601.3e
if (lkicheck) {
// double freeze tracker, so it doesn't update view
game.getTracker().freeze();
@@ -377,6 +378,7 @@ public final class GameActionUtil {
lkicheck = true;
}
// 601.3e
if (lkicheck) {
// double freeze tracker, so it doesn't update view
game.getTracker().freeze();

View File

@@ -60,8 +60,7 @@ public class TriggerTokenCreated extends Trigger {
/** {@inheritDoc} */
@Override
public final void setTriggeringObjects(final SpellAbility sa, Map<AbilityKey, Object> runParams) {
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Player);
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Card);
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Player, AbilityKey.Card);
}
/** {@inheritDoc}

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Human Warrior
PT:0/0
K:Vigilance
K:etbCounter:P1P1:4
A:AB$ Pump | Cost$ 1 BG BG | ValidTgts$ Creature | TgtPrompt$ Select target creature to remove a +1/+1 counter from | SubAbility$ DBMove | StackDescription$ None | SpellDescription$ Move a +1/+1 counter from target creature onto a second target creature.
A:AB$ Pump | Cost$ 1 BG BG | ValidTgts$ Creature | TgtPrompt$ Select target creature to remove a +1/+1 counter from | AILogic$ MoveCounter | SubAbility$ DBMove | StackDescription$ None | SpellDescription$ Move a +1/+1 counter from target creature onto a second target creature.
SVar:DBMove:DB$ MoveCounter | Source$ ParentTarget | ValidTgts$ Creature | TgtPrompt$ Select target creature to move a +1/+1 counter to | TargetUnique$ True | CounterType$ P1P1 | CounterNum$ 1
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/daghatar_the_adamant.jpg

View File

@@ -4,4 +4,5 @@ Types:Land
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ Pump | Cost$ 1 T | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | SubAbility$ DBMove | SorcerySpeed$ True | StackDescription$ SpellDescription | SpellDescription$ Move a counter from target permanent you control onto another target permanent. Activate only as a sorcery.
SVar:DBMove:DB$ MoveCounter | Source$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent to move counter to | TargetUnique$ True | CounterType$ Any | CounterNum$ 1 | StackDescription$ None
AI:RemoveDeck:All
Oracle:{T}: Add {C}.\n{1}, {T}: Move a counter from target permanent you control onto another target permanent. Activate only as a sorcery.

View File

@@ -19,5 +19,4 @@ T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigDestroy | TriggerDescripti
SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Artifact.ControlledBy TriggeredDefendingPlayer,Enchantment.ControlledBy TriggeredDefendingPlayer | TgtPrompt$ Select target artifact or enchantment defending player controls
K:Nightbound
SVar:HasAttackEffect:TRUE
Oracle:{1}, Sacrifice Frenzied Trapbreaker: Destroy target artifact or enchantment.
Whenever Frenzied Trapbreaker attacks, destroy target artifact or enchantment defending player controls.\nNightbound (If a player casts at least two spells during their own turn, it becomes day next turn.)
Oracle:{1}, Sacrifice Frenzied Trapbreaker: Destroy target artifact or enchantment.\nWhenever Frenzied Trapbreaker attacks, destroy target artifact or enchantment defending player controls.\nNightbound (If a player casts at least two spells during their own turn, it becomes day next turn.)