- Improved AI using Ulamog's Nullifier.

This commit is contained in:
Sloth
2015-09-28 08:42:05 +00:00
parent e922e3dea3
commit 7145da0e53
4 changed files with 35 additions and 6 deletions

View File

@@ -226,7 +226,7 @@ public class AiController {
} }
// if trigger is not mandatory - no problem // if trigger is not mandatory - no problem
if (params.get("OptionalDecider") != null) { if (params.get("OptionalDecider") != null && api == null) {
continue; continue;
} }
@@ -243,6 +243,11 @@ public class AiController {
} else { } else {
rightapi = true; rightapi = true;
} }
if (!(exSA instanceof AbilitySub)) {
if (!ComputerUtilCost.canPayCost(exSA, player)) {
return false;
}
}
} }
if (sa != null) { if (sa != null) {
@@ -255,7 +260,7 @@ public class AiController {
// Run non-mandatory trigger. // Run non-mandatory trigger.
// These checks only work if the Executing SpellAbility is an Ability_Sub. // These checks only work if the Executing SpellAbility is an Ability_Sub.
if ((exSA instanceof AbilitySub) && !doTrigger(exSA, false)) { if (exSA instanceof AbilitySub && !doTrigger(exSA, false)) {
// AI would not run this trigger if given the chance // AI would not run this trigger if given the chance
return false; return false;
} }
@@ -691,6 +696,7 @@ public class AiController {
&& (game.getPhaseHandler().isPlayerTurn(player) && (game.getPhaseHandler().isPlayerTurn(player)
|| game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) || game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS))
&& (!card.hasETBTrigger(true) || card.hasSVar("AmbushAI")) && (!card.hasETBTrigger(true) || card.hasSVar("AmbushAI"))
&& game.getStack().isEmpty()
&& !ComputerUtil.castPermanentInMain1(player, sa)) { && !ComputerUtil.castPermanentInMain1(player, sa)) {
return AiPlayDecision.AnotherTime; return AiPlayDecision.AnotherTime;
} }

View File

@@ -1,5 +1,7 @@
package forge.ai.ability; package forge.ai.ability;
import java.util.Iterator;
import forge.ai.ComputerUtilCost; import forge.ai.ComputerUtilCost;
import forge.ai.ComputerUtilMana; import forge.ai.ComputerUtilMana;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
@@ -10,6 +12,7 @@ import forge.game.card.CardFactoryUtil;
import forge.game.cost.Cost; import forge.game.cost.Cost;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.spellability.TargetRestrictions; import forge.game.spellability.TargetRestrictions;
import forge.util.MyRandom; import forge.util.MyRandom;
@@ -119,7 +122,24 @@ public class CounterAi extends SpellAbilityAi {
if (game.getStack().isEmpty()) { if (game.getStack().isEmpty()) {
return false; return false;
} }
final SpellAbility topSA = game.getStack().peekAbility();
SpellAbility topSA = game.getStack().peekAbility();
// triggered abilities see themselves on the stack, so find another spell on the stack
if (sa.isTrigger() && topSA.isTrigger() && game.getStack().size() > 1) {
Iterator<SpellAbilityStackInstance> it = game.getStack().iterator();
SpellAbilityStackInstance si = game.getStack().peek();
while (it.hasNext()) {
si = it.next();
if (si.isTrigger()) {
it.remove();
} else {
break;
}
}
topSA = si.getSpellAbility(true);
}
if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || topSA.getActivatingPlayer() == ai) { if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || topSA.getActivatingPlayer() == ai) {
return false; return false;
} }
@@ -170,7 +190,6 @@ public class CounterAi extends SpellAbilityAi {
// force the Human into making decisions) // force the Human into making decisions)
// But really it should be more picky about how it counters things // But really it should be more picky about how it counters things
return true; return true;
} }

View File

@@ -79,7 +79,7 @@ public class PermanentCreatureAi extends SpellAbilityAi {
} }
// Wait for Main2 if possible // Wait for Main2 if possible
if (ph.is(PhaseType.MAIN1) if (ph.is(PhaseType.MAIN1) && ph.isPlayerTurn(aiPlayer)
&& !ComputerUtil.castPermanentInMain1(aiPlayer, sa)) { && !ComputerUtil.castPermanentInMain1(aiPlayer, sa)) {
return false; return false;
} }

View File

@@ -2,6 +2,8 @@ package forge.ai.ability;
import forge.ai.ComputerUtil; import forge.ai.ComputerUtil;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
import forge.game.Game;
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;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -18,13 +20,15 @@ public class PermanentNoncreatureAi extends SpellAbilityAi {
@Override @Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) { protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
String logic = sa.getParam("AILogic"); String logic = sa.getParam("AILogic");
Game game = aiPlayer.getGame();
final PhaseHandler ph = game.getPhaseHandler();
if ("DontCast".equals(logic)) { if ("DontCast".equals(logic)) {
return false; return false;
} }
// Wait for Main2 if possible // Wait for Main2 if possible
if (aiPlayer.getGame().getPhaseHandler().is(PhaseType.MAIN1) if (ph.is(PhaseType.MAIN1) && ph.isPlayerTurn(aiPlayer)
&& !ComputerUtil.castPermanentInMain1(aiPlayer, sa)) { && !ComputerUtil.castPermanentInMain1(aiPlayer, sa)) {
return false; return false;
} }