Tree optimizers. Fixed Issue 420.

This commit is contained in:
magenoxx 2011-12-26 12:52:31 +04:00
parent a71ce5c405
commit eb0bc89597
8 changed files with 166 additions and 23 deletions

View file

@ -40,20 +40,20 @@ import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.costs.mana.VariableManaCost;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.SearchEffect; import mage.abilities.effects.SearchEffect;
import mage.abilities.keyword.LevelUpAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.Cards; import mage.cards.Cards;
import mage.choices.Choice; import mage.choices.Choice;
import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
import mage.game.combat.Combat; import mage.game.combat.Combat;
import mage.game.combat.CombatGroup; import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.game.stack.StackAbility; import mage.game.stack.StackAbility;
import mage.game.stack.StackObject; import mage.game.stack.StackObject;
import mage.game.turn.*; import mage.game.turn.*;
import mage.player.ai.ma.optimizers.TreeOptimizer;
import mage.player.ai.ma.optimizers.impl.EquipOptimizer;
import mage.player.ai.ma.optimizers.impl.LevelUpOptimizer;
import mage.players.Player; import mage.players.Player;
import mage.target.Target; import mage.target.Target;
import mage.target.TargetCard; import mage.target.TargetCard;
@ -84,6 +84,13 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
private static final String FILE_WITH_INSTRUCTIONS = "config/ai.please.cast.this.txt"; private static final String FILE_WITH_INSTRUCTIONS = "config/ai.please.cast.this.txt";
private List<String> suggested = new ArrayList<String>(); private List<String> suggested = new ArrayList<String>();
private static final List<TreeOptimizer> optimizers = new ArrayList<TreeOptimizer>();
static {
optimizers.add(new LevelUpOptimizer());
optimizers.add(new EquipOptimizer());
}
public ComputerPlayer6(String name, RangeOfInfluence range, int skill) { public ComputerPlayer6(String name, RangeOfInfluence range, int skill) {
super(name, range); super(name, range);
maxDepth = skill * 2; maxDepth = skill * 2;
@ -582,26 +589,8 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
* @param allActions * @param allActions
*/ */
protected void optimize(Game game, List<Ability> allActions) { protected void optimize(Game game, List<Ability> allActions) {
List<Ability> toRemove = null; for (TreeOptimizer optimizer : optimizers) {
for (Ability ability : allActions) { optimizer.optimize(game, allActions);
if (ability instanceof LevelUpAbility) {
Permanent permanent = game.getPermanent(ability.getSourceId());
if (permanent != null && permanent instanceof PermanentCard) {
PermanentCard leveler = (PermanentCard) permanent;
// check already existing Level counters and compare to maximum that make sense
if (permanent.getCounters().getCount(CounterType.LEVEL) >= leveler.getMaxLevelCounters()) {
if (toRemove == null) {
toRemove = new ArrayList<Ability>();
}
toRemove.add(ability);
}
}
}
}
if (toRemove != null) {
for (Ability r : toRemove) {
allActions.remove(r);
}
} }
} }

View file

@ -0,0 +1,22 @@
package mage.player.ai.ma.optimizers;
import mage.abilities.Ability;
import mage.game.Game;
import java.util.List;
/**
* Interface for ai optimizer that cuts the tree of decision.
*
* @author ayratn
*/
public interface TreeOptimizer {
/**
* Optimize provided actions removing those of them that are redundant or lead to combinatorial explosion.
*
* @param game
* @param actions
*/
void optimize(Game game, List<Ability> actions);
}

View file

@ -0,0 +1,61 @@
package mage.player.ai.ma.optimizers.impl;
import mage.abilities.Ability;
import mage.game.Game;
import mage.player.ai.ma.optimizers.TreeOptimizer;
import java.util.ArrayList;
import java.util.List;
/**
* Base class for tree optimizers.
*
* @author ayratn
*/
public abstract class BaseTreeOptimizer implements TreeOptimizer {
/**
* List of abilities that should be removed because of optimization.
*
*/
protected List<Ability> toRemove;
/**
* Inner method for filtering actions.
* Should be implemented by classes.
*
* @param game
* @param actions
*/
abstract void filter(Game game, List<Ability> actions);
/**
* Template method for optimization.
*
* @param game
* @param actions
*/
@Override
public final void optimize(Game game, List<Ability> actions) {
filter(game, actions);
if (toRemove != null) {
for (Ability r : toRemove) {
actions.remove(r);
}
}
}
/**
* Mark an ability to be removed
* Not thread-safe for performance reasons.
*
* @param ability
*/
protected void removeAbility(Ability ability) {
if (toRemove == null) {
toRemove = new ArrayList<Ability>();
}
toRemove.add(ability);
}
}

View file

@ -0,0 +1,31 @@
package mage.player.ai.ma.optimizers.impl;
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.
*
* @author ayratn
*/
public class EquipOptimizer extends BaseTreeOptimizer {
@Override
public void filter(Game game, List<Ability> actions) {
for (Ability ability : actions) {
if (ability instanceof EquipAbility) {
Permanent permanent = game.getPermanent(ability.getFirstTarget());
if (permanent != null) {
// check that equipment is not already attached to {this}
if (permanent.getAttachments().contains(ability.getSourceId())) {
removeAbility(ability);
}
}
}
}
}
}

View file

@ -0,0 +1,40 @@
package mage.player.ai.ma.optimizers.impl;
import mage.abilities.Ability;
import mage.abilities.keyword.LevelUpAbility;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import java.util.List;
/**
* Make sure that AI won't level up whenever there are maximum possible level up counters.
*
* @author ayratn
*/
public class LevelUpOptimizer extends BaseTreeOptimizer {
/**
* Check that ability is level up ability, then compare the current counters of Level type to maximum.
*
* @param game
* @param actions
*/
@Override
public void filter(Game game, List<Ability> actions) {
for (Ability ability : actions) {
if (ability instanceof LevelUpAbility) {
Permanent permanent = game.getPermanent(ability.getSourceId());
if (permanent != null && permanent instanceof PermanentCard) {
PermanentCard leveler = (PermanentCard) permanent;
// check already existing Level counters and compare to maximum that make sense
if (permanent.getCounters().getCount(CounterType.LEVEL) >= leveler.getMaxLevelCounters()) {
removeAbility(ability);
}
}
}
}
}
}