Some changes to AI player.

This commit is contained in:
LevelX2 2015-06-03 17:08:01 +02:00
parent 59c50436ac
commit f63fae06de
5 changed files with 49 additions and 27 deletions

View file

@ -63,6 +63,7 @@ import mage.target.Targets;
import java.io.File;
import java.util.*;
import java.util.concurrent.*;
import mage.constants.AbilityType;
/**
*
@ -86,7 +87,8 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
protected Set<String> actionCache;
private static final List<TreeOptimizer> optimizers = new ArrayList<>();
protected int lastLoggedTurn = 0;
Random random = new Random();
protected static final String BLANKS = "...............................................";
static {
optimizers.add(new LevelUpOptimizer());
optimizers.add(new EquipOptimizer());
@ -436,8 +438,12 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
});
pool.execute(task);
try {
logger.debug("maxThink: " + maxThink + " seconds");
return task.get(maxThink, TimeUnit.SECONDS);
int maxSeconds = maxThink;
if (!ALLOW_INTERRUPT) {
maxSeconds = 3600;
}
logger.debug("maxThink: " + maxSeconds + " seconds ");
return task.get(maxSeconds, TimeUnit.SECONDS);
} catch (TimeoutException e) {
logger.info("simulating - timed out");
task.cancel(true);
@ -461,7 +467,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
}
Game game = node.getGame();
int val;
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
val = GameStateEvaluator2.evaluate(playerId, game);
logger.trace("interrupted - " + val);
@ -505,7 +511,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
}
protected int simulatePriority(SimulationNode2 node, Game game, int depth, int alpha, int beta) {
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.info("interrupted");
return GameStateEvaluator2.evaluate(playerId, game);
@ -522,7 +528,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
int counter = 0;
for (Ability action : allActions) {
counter++;
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.info("Sim Prio [" + depth + "] -- interrupted");
break;
@ -537,16 +543,24 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
}
if (!sim.gameOver(null) && action.isUsesStack()) {
// only pass if the last action uses the stack
sim.getPlayer(currentPlayer.getId()).pass(game);
sim.getPlayerList().getNext();
UUID nextPlayerId = sim.getPlayerList().get();
do {
sim.getPlayer(nextPlayerId).pass(game);
nextPlayerId = sim.getPlayerList().getNext();
} while (nextPlayerId != this.getId());
}
SimulationNode2 newNode = new SimulationNode2(node, sim, action, depth, currentPlayer.getId());
logger.trace(new StringBuilder("Sim Prio [").append(depth).append("]#").append(counter).append(" -- newNode (").append(action.toString()).append(") ").append(newNode.hashCode()).append(" parent node ").append(node.hashCode()));
// int testVal = GameStateEvaluator2.evaluate(currentPlayer.getId(), sim);
sim.checkStateAndTriggered();
int val = addActions(newNode, depth - 1, alpha, beta);
int val;
if (action instanceof PassAbility) {
// Stop to simulate deeper if PassAbility
val = GameStateEvaluator2.evaluate(this.getId(), sim);
// logger.info("evaluate = " + val );
} else {
val = addActions(newNode, depth - 1, alpha, beta);
// logger.info("addAction = " + val );
}
logger.debug("Sim Prio " + BLANKS.substring(0, 2 + (maxDepth-depth) * 3)+ "["+depth+"]#"+counter+" <" + val +"> - ("+action.toString()+") "+newNode.hashCode()+" parent node "+node.hashCode());
if (logger.isInfoEnabled() && depth == maxDepth) {
StringBuilder sb = new StringBuilder("Sim Prio [").append(depth).append("] #").append(counter)
.append(" <").append(val).append("> (").append(action)
@ -564,10 +578,10 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
}
if (currentPlayer.getId().equals(playerId)) {
if (action instanceof PassAbility) {
val = val -15; // passivity penalty
if (depth == maxDepth && action instanceof PassAbility) {
val = val - PASSIVITY_PENALTY; // passivity penalty
}
if (val > alpha) {
if (val > alpha || (depth == maxDepth && val == alpha && random.nextBoolean())) { // Adding random for equal value to get change sometimes
alpha = val;
bestNode = newNode;
bestNode.setScore(val);
@ -1311,7 +1325,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
private boolean checkForRepeatedAction(Game sim, SimulationNode2 node, Ability action, UUID playerId) {
// pass or casting two times a spell multiple times on hand is ok
if (action instanceof PassAbility || action instanceof SpellAbility) {
if (action instanceof PassAbility || action instanceof SpellAbility || action.getAbilityType().equals(AbilityType.MANA)) {
return false;
}
int newVal = GameStateEvaluator2.evaluate(playerId, sim);

View file

@ -244,7 +244,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
logger.trace("Add Action [" + depth + "] " + node.getAbilities().toString() + " a: " + alpha + " b: " + beta);
}
Game game = node.getGame();
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return GameStateEvaluator2.evaluate(playerId, game);
@ -349,7 +349,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
protected int simulateCombat(Game game, SimulationNode2 node, int depth, int alpha, int beta, boolean counter) {
Integer val = null;
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return GameStateEvaluator2.evaluate(playerId, game);
@ -395,7 +395,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
protected int simulateAttackers(Game game, SimulationNode2 node, UUID attackerId, int depth, int alpha, int beta, boolean counter) {
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return GameStateEvaluator2.evaluate(playerId, game);
@ -472,7 +472,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
}
protected int simulateBlockers(Game game, SimulationNode2 node, UUID defenderId, int depth, int alpha, int beta, boolean counter) {
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return GameStateEvaluator2.evaluate(playerId, game);
@ -556,7 +556,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
}
/*protected int simulateCounterAttack(Game game, SimulationNode2 node, int depth, int alpha, int beta) {
if (Thread.interrupted()) {
if (ALLOW_INTERRUP && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return GameStateEvaluator2.evaluate(playerId, game);
@ -583,7 +583,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
}*/
protected void simulateStep(Game game, Step step) {
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return;
@ -603,7 +603,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
}
protected void finishCombat(Game game) {
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return;
@ -614,7 +614,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
}
protected int simulatePostCombatMain(Game game, SimulationNode2 node, int depth, int alpha, int beta) {
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return GameStateEvaluator2.evaluate(playerId, game);
@ -632,7 +632,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
}
protected void simulateToEnd(Game game) {
if (Thread.interrupted()) {
if (ALLOW_INTERRUPT && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return;

View file

@ -46,6 +46,7 @@ import mage.abilities.costs.mana.VariableManaCost;
import mage.abilities.effects.Effect;
import mage.cards.Card;
import mage.choices.Choice;
import mage.constants.AbilityType;
import mage.game.Game;
import mage.game.combat.Combat;
import mage.game.events.GameEvent;
@ -124,6 +125,9 @@ public class SimulatedPlayer2 extends ComputerPlayer {
List<Ability> playables = game.getPlayer(playerId).getPlayable(game, isSimulatedPlayer);
playables = filterAbilities(game, playables, suggested);
for (Ability ability: playables) {
if (ability.getAbilityType().equals(AbilityType.MANA)) {
continue;
}
List<Ability> options = game.getPlayer(playerId).getPlayableOptions(ability, game);
options = filterOptions(game, options, ability, suggested);
options = optimizeOptions(game, options, ability);

View file

@ -129,7 +129,7 @@ public class ArtificialScoringSystem {
if (permanent.getCardType().contains(CardType.CREATURE)) {
return -100;
} else if (permanent.getCardType().contains(CardType.LAND)) {
return -1;
return -20; // means probably no mana available (should be greater than passivity penalty
} else {
return -2;
}

View file

@ -160,6 +160,10 @@ import org.apache.log4j.Logger;
public class ComputerPlayer extends PlayerImpl implements Player {
private transient final static Logger log = Logger.getLogger(ComputerPlayer.class);
protected int PASSIVITY_PENALTY = 5; // Penalty value for doing nothing if some actions are availble
protected boolean ALLOW_INTERRUPT = true; // change this for test purposes to switch off interrupts while debugging
private transient Map<Mana, Card> unplayable = new TreeMap<>();
private transient List<Card> playableNonInstant = new ArrayList<>();
private transient List<Card> playableInstant = new ArrayList<>();