From 6d599d2b8c64cd8e71802c53f732ec4a311fbdb8 Mon Sep 17 00:00:00 2001 From: Agetian Date: Thu, 13 Sep 2018 11:27:56 +0300 Subject: [PATCH] - Basic SurveilAi logic, largely inspired with the ScryAi logic. --- .../main/java/forge/ai/ability/SurveilAi.java | 72 +++++++++++++++++-- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ability/SurveilAi.java b/forge-ai/src/main/java/forge/ai/ability/SurveilAi.java index 47c64349396..fe7b1671e67 100644 --- a/forge-ai/src/main/java/forge/ai/ability/SurveilAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/SurveilAi.java @@ -1,9 +1,13 @@ package forge.ai.ability; import forge.ai.SpellAbilityAi; +import forge.game.phase.PhaseHandler; +import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; +import forge.util.MyRandom; public class SurveilAi extends SpellAbilityAi { @@ -14,10 +18,8 @@ public class SurveilAi extends SpellAbilityAi { @Override protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { - if (sa.usesTargeting()) { // It doesn't appear that Scry ever targets - // ability is targeted + if (sa.usesTargeting()) { // TODO: It doesn't appear that Surveil ever targets, is this necessary? sa.resetTargets(); - sa.getTargets().add(ai); } @@ -33,10 +35,68 @@ public class SurveilAi extends SpellAbilityAi { return doTriggerAINoCost(ai, sa, false); } - /* - * (non-Javadoc) - * @see forge.ai.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.game.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String) + /** + * Checks if the AI will play a SpellAbility based on its phase restrictions */ + @Override + protected boolean checkPhaseRestrictions(final Player ai, final SpellAbility sa, final PhaseHandler ph) { + // if the Surveil ability requires tapping and has a mana cost, it's best done at the end of opponent's turn + // and right before the beginning of AI's turn, if possible, to avoid mana locking the AI and also to + // try to scry right before drawing a card. Also, avoid tapping creatures in the AI's turn, if possible, + // even if there's no mana cost. + if (sa.getPayCosts() != null) { + if (sa.getPayCosts().hasTapCost() + && (sa.getPayCosts().hasManaCost() || (sa.getHostCard() != null && sa.getHostCard().isCreature())) + && !SpellAbilityAi.isSorcerySpeed(sa)) { + return ph.getNextTurn() == ai && ph.is(PhaseType.END_OF_TURN); + } + } + + // in the player's turn Surveil should only be done in Main1 or in Upkeep if able + if (ph.isPlayerTurn(ai)) { + if (SpellAbilityAi.isSorcerySpeed(sa)) { + return ph.is(PhaseType.MAIN1) || sa.hasParam("Planeswalker"); + } else { + return ph.is(PhaseType.UPKEEP); + } + } + return true; + } + + /** + * Checks if the AI will play a SpellAbility with the specified AiLogic + */ + @Override + protected boolean checkAiLogic(final Player ai, final SpellAbility sa, final String aiLogic) { + if ("Never".equals(aiLogic)) { + return false; + } + + // TODO: add card-specific Surveil AI logic here when/if necessary + + return true; + } + + @Override + protected boolean checkApiLogic(Player ai, SpellAbility sa) { + // Makes no sense to do Surveil when there's nothing in the library + if (ai.getCardsIn(ZoneType.Library).isEmpty()) { + return false; + } + + double chance = .4; // 40 percent chance for instant speed + if (SpellAbilityAi.isSorcerySpeed(sa)) { + chance = .667; // 66.7% chance for sorcery speed (since it will never activate EOT) + } + + boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1); + if (SpellAbilityAi.playReusable(ai, sa)) { + randomReturn = true; + } + + return randomReturn; + } + @Override public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) { return true;