MCPcopy Create free account
hub / github.com/Card-Forge/forge / canPlay

Method canPlay

forge-ai/src/main/java/forge/ai/ability/DebuffAi.java:25–87  ·  view source on GitHub ↗
(final Player ai, final SpellAbility sa)

Source from the content-addressed store, hash-verified

23public class DebuffAi extends SpellAbilityAi {
24
25 @Override
26 protected AiAbilityDecision canPlay(final Player ai, final SpellAbility sa) {
27 // if there is no target and host card isn't in play, don't activate
28 final Card source = sa.getHostCard();
29 final Game game = ai.getGame();
30 if (!sa.usesTargeting() && !source.isInPlay()) {
31 return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
32 }
33
34 final Cost cost = sa.getPayCosts();
35
36 // temporarily disabled until AI is improved
37 if (!ComputerUtilCost.checkCreatureSacrificeCost(ai, cost, source, sa)) {
38 return new AiAbilityDecision(0, AiPlayDecision.CantAfford);
39 }
40
41 if (!ComputerUtilCost.checkLifeCost(ai, cost, source, 40, sa)) {
42 return new AiAbilityDecision(0, AiPlayDecision.CantAfford);
43 }
44
45 if (!ComputerUtilCost.checkRemoveCounterCost(cost, source, sa)) {
46 return new AiAbilityDecision(0, AiPlayDecision.CantAfford);
47 }
48
49 final PhaseHandler ph = game.getPhaseHandler();
50
51 // Phase Restrictions
52 if (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
53 || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)
54 || !game.getStack().isEmpty()) {
55 // Instant-speed pumps should not be cast outside of combat when the
56 // stack is empty, unless there are specific activation phase requirements
57 if (!isSorcerySpeed(sa, ai) && !sa.hasParam("ActivationPhases")) {
58 return new AiAbilityDecision(0, AiPlayDecision.AnotherTime);
59 }
60 }
61
62 if (!sa.usesTargeting()) {
63 List<Card> cards = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
64
65 final Combat combat = game.getCombat();
66 if (cards.stream().anyMatch(c -> {
67 if (c.getController().equals(sa.getActivatingPlayer()) || combat == null)
68 return false;
69
70 if (!combat.isBlocking(c) && !combat.isAttacking(c)) {
71 return false;
72 }
73 // don't add duplicate negative keywords
74 return sa.hasParam("Keywords") && c.hasAnyKeyword(Arrays.asList(sa.getParam("Keywords").split(" & ")));
75 })) {
76 return new AiAbilityDecision(100, AiPlayDecision.WillPlay);
77 } else {
78 return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
79 }
80 } else {
81 if (debuffTgtAI(ai, sa, sa.hasParam("Keywords") ? Arrays.asList(sa.getParam("Keywords").split(" & ")) : null, false)) {
82 return new AiAbilityDecision(100, AiPlayDecision.WillPlay);

Callers

nothing calls this directly

Calls 15

isInPlayMethod · 0.95
checkLifeCostMethod · 0.95
getPhaseHandlerMethod · 0.95
getPhaseMethod · 0.95
getStackMethod · 0.95
getDefinedCardsMethod · 0.95
getCombatMethod · 0.95
isBlockingMethod · 0.95
isAttackingMethod · 0.95
debuffTgtAIMethod · 0.95

Tested by

no test coverage detected