From abfe517c17c1258181060f44a6065cc358de9a6c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 30 Apr 2014 07:15:01 +0200 Subject: [PATCH] * AI player - Fixed a problem that AI uses Sphinx of Jwar Isle ability in an endless loop. --- .../src/mage/player/ai/ComputerPlayer6.java | 19 ++++++----- .../ai/ma/optimizers/TreeOptimizer.java | 3 +- .../ma/optimizers/impl/BaseTreeOptimizer.java | 2 +- .../optimizers/impl/DiscardCardOptimizer.java | 3 +- .../ai/ma/optimizers/impl/EquipOptimizer.java | 3 +- .../ma/optimizers/impl/OutcomeOptimizer.java | 33 +++++++++++++++++++ .../mage/sets/zendikar/SphinxOfJwarIsle.java | 16 +++++---- 7 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/OutcomeOptimizer.java diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index e86c9ceee04..ce79182fe1d 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -62,6 +62,7 @@ import mage.target.Targets; import java.io.File; import java.util.*; import java.util.concurrent.*; +import mage.player.ai.ma.optimizers.impl.OutcomeOptimizer; /** * @@ -74,22 +75,23 @@ public class ComputerPlayer6 extends ComputerPlayer implements protected int maxDepth; protected int maxNodes; protected int maxThink; - protected LinkedList actions = new LinkedList(); - protected List targets = new ArrayList(); - protected List choices = new ArrayList(); + protected LinkedList actions = new LinkedList<>(); + protected List targets = new ArrayList<>(); + protected List choices = new ArrayList<>(); protected Combat combat; protected int currentScore; protected SimulationNode2 root; private static final String FILE_WITH_INSTRUCTIONS = "config/ai.please.cast.this.txt"; - private List suggested = new ArrayList(); + private final List suggested = new ArrayList<>(); protected Set actionCache; - private static final List optimizers = new ArrayList(); + private static final List optimizers = new ArrayList<>(); protected int lastLoggedTurn = 0; static { optimizers.add(new LevelUpOptimizer()); optimizers.add(new EquipOptimizer()); optimizers.add(new DiscardCardOptimizer()); + optimizers.add(new OutcomeOptimizer()); } public ComputerPlayer6(String name, RangeOfInfluence range, int skill) { @@ -102,7 +104,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements maxThink = skill * 3; maxNodes = Config2.maxNodes; getSuggestedActions(); - this.actionCache = new HashSet(); + this.actionCache = new HashSet<>(); } public ComputerPlayer6(final ComputerPlayer6 player) { @@ -275,7 +277,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements //GameStateEvaluator2.evaluate(playerId, root.getGame()); int bestScore = root.getScore(); //if (bestScore > currentScore) { - actions = new LinkedList(root.abilities); + actions = new LinkedList<>(root.abilities); combat = root.combat; //} else { //System.out.println("[" + game.getPlayer(playerId).getName() + "] Action: not better score"); @@ -314,7 +316,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements */ logger.info("simulating -- continuing previous action chain"); - actions = new LinkedList(root.abilities); + actions = new LinkedList<>(root.abilities); combat = root.combat; return true; } else { @@ -646,6 +648,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements /** * Various AI optimizations for actions. * + * @param game * @param allActions */ protected void optimize(Game game, List allActions) { diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/TreeOptimizer.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/TreeOptimizer.java index fe12e8ab2a2..0b10de819d9 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/TreeOptimizer.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/TreeOptimizer.java @@ -1,10 +1,9 @@ package mage.player.ai.ma.optimizers; +import java.util.List; import mage.abilities.Ability; import mage.game.Game; -import java.util.List; - /** * Interface for ai optimizer that cuts the tree of decision. * diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/BaseTreeOptimizer.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/BaseTreeOptimizer.java index 3c450416eae..4f55a961456 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/BaseTreeOptimizer.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/BaseTreeOptimizer.java @@ -54,7 +54,7 @@ public abstract class BaseTreeOptimizer implements TreeOptimizer { */ protected void removeAbility(Ability ability) { if (toRemove == null) { - toRemove = new ArrayList(); + toRemove = new ArrayList<>(); } toRemove.add(ability); } diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/DiscardCardOptimizer.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/DiscardCardOptimizer.java index a4875452add..3c905192c40 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/DiscardCardOptimizer.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/DiscardCardOptimizer.java @@ -1,10 +1,9 @@ package mage.player.ai.ma.optimizers.impl; +import java.util.List; import mage.abilities.Ability; import mage.game.Game; -import java.util.List; - /** * Removes abilities that require only discard a card for activation. * diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/EquipOptimizer.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/EquipOptimizer.java index e01379cdd7c..15466e35fe3 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/EquipOptimizer.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/EquipOptimizer.java @@ -1,12 +1,11 @@ package mage.player.ai.ma.optimizers.impl; +import java.util.List; import mage.abilities.Ability; import mage.abilities.keyword.EquipAbility; import mage.game.Game; import mage.game.permanent.Permanent; -import java.util.List; - /** * Make sure that AI won't equip the same creature equip already attached to. * diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/OutcomeOptimizer.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/OutcomeOptimizer.java new file mode 100644 index 00000000000..5c302b94b84 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/optimizers/impl/OutcomeOptimizer.java @@ -0,0 +1,33 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package mage.player.ai.ma.optimizers.impl; + +import java.util.List; +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.constants.Outcome; +import mage.game.Game; + +/** + * Removes abilities that require only discard a card for activation. + * + * @author LevelX2 + */ +public class OutcomeOptimizer extends BaseTreeOptimizer { + + @Override + public void filter(Game game, List actions) { + for (Ability ability : actions) { + for (Effect effect: ability.getEffects()) { + if (effect.getOutcome().equals(Outcome.AIDontUseIt)) { + removeAbility(ability); + break; + } + } + } + } +} diff --git a/Mage.Sets/src/mage/sets/zendikar/SphinxOfJwarIsle.java b/Mage.Sets/src/mage/sets/zendikar/SphinxOfJwarIsle.java index d773ae1772e..66af883f3b1 100644 --- a/Mage.Sets/src/mage/sets/zendikar/SphinxOfJwarIsle.java +++ b/Mage.Sets/src/mage/sets/zendikar/SphinxOfJwarIsle.java @@ -28,10 +28,6 @@ package mage.sets.zendikar; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -43,6 +39,10 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.Cards; import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.players.Player; @@ -61,8 +61,11 @@ public class SphinxOfJwarIsle extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(5); + // Flying, shroud this.addAbility(FlyingAbility.getInstance()); this.addAbility(ShroudAbility.getInstance()); + + // You may look at the top card of your library. (You may do this at any time.) this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new SphinxOfJwarIsleEffect(), new GenericManaCost(0))); } @@ -79,7 +82,7 @@ public class SphinxOfJwarIsle extends CardImpl { class SphinxOfJwarIsleEffect extends OneShotEffect { public SphinxOfJwarIsleEffect() { - super(Outcome.Neutral); + super(Outcome.AIDontUseIt); // AI can't use the information anyway and seems to do it again and again this.staticText = "You may look at the top card of your library"; } @@ -101,8 +104,7 @@ class SphinxOfJwarIsleEffect extends OneShotEffect { Card card = player.getLibrary().getFromTop(game); if (card != null) { - Cards cards = new CardsImpl(Zone.PICK); - cards.add(card); + Cards cards = new CardsImpl(card); player.lookAtCards("Sphinx of Jwar Isle", cards, game); } else { return false;