mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
- Revamped Planeswalkers logic: evaluate more expensive abilities first to prevent spamming of good "plus" abilities, try not to "minus" all loyalty if not under threat
- Added flag in TokensAi to allow Planeswalkers to create tokens in Main1 - AI can now use all the abilities of Gideon, Ally of Zendikar
This commit is contained in:
@@ -64,6 +64,8 @@ import forge.game.combat.CombatUtil;
|
|||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.cost.CostDiscard;
|
import forge.game.cost.CostDiscard;
|
||||||
import forge.game.cost.CostPart;
|
import forge.game.cost.CostPart;
|
||||||
|
import forge.game.cost.CostPutCounter;
|
||||||
|
import forge.game.cost.CostRemoveCounter;
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -857,8 +859,14 @@ public class AiController {
|
|||||||
if ("True".equals(source.getSVar("NonStackingEffect")) && ai.isCardInPlay(source.getName())) {
|
if ("True".equals(source.getSVar("NonStackingEffect")) && ai.isCardInPlay(source.getName())) {
|
||||||
p -= 9;
|
p -= 9;
|
||||||
}
|
}
|
||||||
// sort planeswalker abilities for ultimate
|
// sort planeswalker abilities with most costly first
|
||||||
if (sa.getRestrictions().isPwAbility()) {
|
if (sa.getRestrictions().isPwAbility()) {
|
||||||
|
final CostPart cost = sa.getPayCosts().getCostParts().get(0);
|
||||||
|
if (cost instanceof CostRemoveCounter) {
|
||||||
|
p += cost.convertAmount();
|
||||||
|
} else if (cost instanceof CostPutCounter) {
|
||||||
|
p -= cost.convertAmount();
|
||||||
|
}
|
||||||
if (sa.hasParam("Ultimate")) {
|
if (sa.hasParam("Ultimate")) {
|
||||||
p += 9;
|
p += 9;
|
||||||
}
|
}
|
||||||
@@ -867,10 +875,7 @@ public class AiController {
|
|||||||
if (ApiType.DestroyAll == sa.getApi()) {
|
if (ApiType.DestroyAll == sa.getApi()) {
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
if (ApiType.Token == sa.getApi() && noCreatures) {
|
|
||||||
//hack to force planeswalkers to defend themselves
|
|
||||||
p += 3;
|
|
||||||
}
|
|
||||||
else if (ApiType.Mana == sa.getApi()) {
|
else if (ApiType.Mana == sa.getApi()) {
|
||||||
p -= 9;
|
p -= 9;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -391,6 +391,17 @@ public class ComputerUtilCost {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try not to lose Planeswalker if not threatened
|
||||||
|
if (sa.getRestrictions().isPwAbility()) {
|
||||||
|
final CostPart cost = sa.getPayCosts().getCostParts().get(0);
|
||||||
|
if (cost instanceof CostRemoveCounter && cost.convertAmount() == sa.getHostCard().getCurrentLoyalty()) {
|
||||||
|
// refuse to pay if opponent has no creature threats or
|
||||||
|
if (player.getOpponent().getCreaturesInPlay().isEmpty() || MyRandom.getRandom().nextFloat() < .5f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ComputerUtilMana.canPayManaCost(sa, player, extraManaNeeded)
|
return ComputerUtilMana.canPayManaCost(sa, player, extraManaNeeded)
|
||||||
&& CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa);
|
&& CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa);
|
||||||
} // canPayCost()
|
} // canPayCost()
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import forge.game.card.CardFactory;
|
|||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
|
import forge.game.cost.CostPart;
|
||||||
|
import forge.game.cost.CostRemoveCounter;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -121,6 +123,22 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean pwAbility = sa.getRestrictions().isPwAbility();
|
||||||
|
if (pwAbility) {
|
||||||
|
// Planeswalker token ability with loyalty costs should be played in Main1 or it might
|
||||||
|
// never be used due to other positive abilities. AI is kept from spamming them by the
|
||||||
|
// loyalty cost of each usage. Zero/loyalty gain token abilities can be evaluated as
|
||||||
|
// per normal.
|
||||||
|
boolean hasCost = false;
|
||||||
|
for (CostPart c : sa.getPayCosts().getCostParts()) {
|
||||||
|
if (c instanceof CostRemoveCounter) {
|
||||||
|
hasCost = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pwAbility = hasCost;
|
||||||
|
}
|
||||||
|
|
||||||
PhaseHandler ph = game.getPhaseHandler();
|
PhaseHandler ph = game.getPhaseHandler();
|
||||||
// Don't generate tokens without haste before main 2 if possible
|
// Don't generate tokens without haste before main 2 if possible
|
||||||
if (ph.getPhase().isBefore(PhaseType.MAIN2)
|
if (ph.getPhase().isBefore(PhaseType.MAIN2)
|
||||||
@@ -133,13 +151,13 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
buff = true;
|
buff = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!buff && !sacOnStack) {
|
if (!buff && !sacOnStack && !pwAbility) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ph.isPlayerTurn(ai) || ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS))
|
if ((ph.isPlayerTurn(ai) || ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS))
|
||||||
&& !sa.hasParam("ActivationPhases") && !sa.hasParam("PlayerTurn")
|
&& !sa.hasParam("ActivationPhases") && !sa.hasParam("PlayerTurn")
|
||||||
&& !SpellAbilityAi.isSorcerySpeed(sa) && !haste && !sacOnStack) {
|
&& !SpellAbilityAi.isSorcerySpeed(sa) && !haste && !sacOnStack && !pwAbility) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((ph.getPhase().isAfter(PhaseType.COMBAT_BEGIN) || game.getPhaseHandler().isPlayerTurn(opp))
|
if ((ph.getPhase().isAfter(PhaseType.COMBAT_BEGIN) || game.getPhaseHandler().isPlayerTurn(opp))
|
||||||
|
|||||||
@@ -7,6 +7,5 @@ SVar:GideonPrevent:DB$ Pump | Defined$ Self | KW$ HIDDEN Prevent all damage that
|
|||||||
A:AB$ Token | Cost$ 0 | TokenAmount$ 1 | TokenName$ Knight Ally | TokenColors$ White | TokenTypes$ Creature,Knight,Ally | TokenOwner$ You | TokenPower$ 2 | TokenToughness$ 2 | Planeswalker$ True | SpellDescription$ Put a 2/2 white Knight Ally creature token onto the battlefield.
|
A:AB$ Token | Cost$ 0 | TokenAmount$ 1 | TokenName$ Knight Ally | TokenColors$ White | TokenTypes$ Creature,Knight,Ally | TokenOwner$ You | TokenPower$ 2 | TokenToughness$ 2 | Planeswalker$ True | SpellDescription$ Put a 2/2 white Knight Ally creature token onto the battlefield.
|
||||||
A:AB$ Effect | Cost$ SubCounter<4/LOYALTY> | Name$ Gideon, Ally of Zendikad emblem | Image$ gideon_ally_of_zendikar_emblem | StaticAbilities$ STPump | Planeswalker$ True | Ultimate$ True | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Creatures you control get +1/+1."
|
A:AB$ Effect | Cost$ SubCounter<4/LOYALTY> | Name$ Gideon, Ally of Zendikad emblem | Image$ gideon_ally_of_zendikar_emblem | StaticAbilities$ STPump | Planeswalker$ True | Ultimate$ True | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Creatures you control get +1/+1."
|
||||||
SVar:STPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.YouCtrl | AddPower$ 1 | AddToughness$ 1
|
SVar:STPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.YouCtrl | AddPower$ 1 | AddToughness$ 1
|
||||||
SVar:RemAIDeck:True
|
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/gideon_ally_of_zendikar.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/gideon_ally_of_zendikar.jpg
|
||||||
Oracle:[+1] Until end of turn, Gideon, Ally of Zendikar becomes a 5/5 Human Soldier Ally creature with indestructible that is still a planeswalker. Prevent all damage that would be dealt to him this turn.\n[0] Put a 2/2 white Knight Ally creature token onto the battlefield.\n[-4] You get an emblem with "Creatures you control get +1/+1."
|
Oracle:[+1] Until end of turn, Gideon, Ally of Zendikar becomes a 5/5 Human Soldier Ally creature with indestructible that is still a planeswalker. Prevent all damage that would be dealt to him this turn.\n[0] Put a 2/2 white Knight Ally creature token onto the battlefield.\n[-4] You get an emblem with "Creatures you control get +1/+1."
|
||||||
|
|||||||
Reference in New Issue
Block a user