mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Improve Ward checking
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.)
|
||||
|
||||
Reference in New Issue
Block a user