mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
- Improved AI using Ulamog's Nullifier.
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user