- AI will now block and attack a little more sanely. The sim methods are not working right now, so they were commented out.

This commit is contained in:
jeff 2012-11-03 21:34:32 -05:00
parent fec750ef01
commit 1d7e9e55be

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed * authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package mage.player.ai; package mage.player.ai;
import mage.Constants.Outcome; import mage.Constants.Outcome;
@ -68,6 +67,7 @@ import mage.target.TargetCard;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import mage.player.ai.utils.RateCard;
/** /**
* *
@ -77,7 +77,6 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
private static final transient org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ComputerPlayer6.class); private static final transient org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ComputerPlayer6.class);
private static final ExecutorService pool = Executors.newFixedThreadPool(1); private static final ExecutorService pool = Executors.newFixedThreadPool(1);
protected int maxDepth; protected int maxDepth;
protected int maxNodes; protected int maxNodes;
protected int maxThink; protected int maxThink;
@ -87,11 +86,9 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
protected Combat combat; protected Combat combat;
protected int currentScore; protected int currentScore;
protected SimulationNode2 root; protected SimulationNode2 root;
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>();
protected Set<String> actionCache; protected Set<String> actionCache;
private static final List<TreeOptimizer> optimizers = new ArrayList<TreeOptimizer>(); private static final List<TreeOptimizer> optimizers = new ArrayList<TreeOptimizer>();
static { static {
@ -113,8 +110,9 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
super(player); super(player);
this.maxDepth = player.maxDepth; this.maxDepth = player.maxDepth;
this.currentScore = player.currentScore; this.currentScore = player.currentScore;
if (player.combat != null) if (player.combat != null) {
this.combat = player.combat.copy(); this.combat = player.combat.copy();
}
this.actions.addAll(player.actions); this.actions.addAll(player.actions);
this.targets.addAll(player.targets); this.targets.addAll(player.targets);
this.choices.addAll(player.choices); this.choices.addAll(player.choices);
@ -184,8 +182,8 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
protected void printOutState(Game game, UUID playerId) { protected void printOutState(Game game, UUID playerId) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
System.out.println("Turn::"+game.getTurnNum()); System.out.println("Turn::" + game.getTurnNum());
System.out.println("[" + game.getPlayer(playerId).getName() + "] " + game.getTurn().getStepType().name() +", life=" + player.getLife()); System.out.println("[" + game.getPlayer(playerId).getName() + "] " + game.getTurn().getStepType().name() + ", life=" + player.getLife());
Player opponent = game.getPlayer(game.getOpponents(playerId).iterator().next()); Player opponent = game.getPlayer(game.getOpponents(playerId).iterator().next());
System.out.println("[Opponent] life=" + opponent.getLife()); System.out.println("[Opponent] life=" + opponent.getLife());
@ -197,25 +195,25 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
System.out.println("Hand: " + s); System.out.println("Hand: " + s);
s = "["; s = "[";
for (Permanent permanent : game.getBattlefield().getAllPermanents()) { for (Permanent permanent : game.getBattlefield().getAllPermanents()) {
if (permanent.getOwnerId().equals(player.getId())) { if (permanent.getOwnerId().equals(player.getId())) {
s += permanent.getName(); s += permanent.getName();
if (permanent.isTapped()) { if (permanent.isTapped()) {
s+="(tapped)"; s += "(tapped)";
} }
if (permanent.isAttacking()) { if (permanent.isAttacking()) {
s+="(attacking)"; s += "(attacking)";
} }
s+=";"; s += ";";
} }
} }
s += "]"; s += "]";
System.out.println("Permanents: " + s); System.out.println("Permanents: " + s);
} }
protected void act(Game game) { protected void act(Game game) {
if (actions == null || actions.size() == 0) if (actions == null || actions.size() == 0) {
pass(); pass();
else { } else {
boolean usedStack = false; boolean usedStack = false;
while (actions.peek() != null) { while (actions.peek() != null) {
Ability ability = actions.poll(); Ability ability = actions.poll();
@ -232,23 +230,25 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
} }
this.activateAbility((ActivatedAbility) ability, game); this.activateAbility((ActivatedAbility) ability, game);
if (ability.isUsesStack()) if (ability.isUsesStack()) {
usedStack = true; usedStack = true;
}
if (!suggested.isEmpty() && !(ability instanceof PassAbility)) { if (!suggested.isEmpty() && !(ability instanceof PassAbility)) {
Iterator<String> it = suggested.iterator(); Iterator<String> it = suggested.iterator();
while (it.hasNext()) { while (it.hasNext()) {
Card card = game.getCard(ability.getSourceId()); Card card = game.getCard(ability.getSourceId());
String action = it.next(); String action = it.next();
System.out.println("action="+action+";card="+card); System.out.println("action=" + action + ";card=" + card);
if (action.equals(card.getName())) { if (action.equals(card.getName())) {
System.out.println("removed from suggested="+action); System.out.println("removed from suggested=" + action);
it.remove(); it.remove();
} }
} }
} }
} }
if (usedStack) if (usedStack) {
pass(); pass();
}
} }
} }
@ -266,10 +266,10 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
//GameStateEvaluator2.evaluate(playerId, root.getGame()); //GameStateEvaluator2.evaluate(playerId, root.getGame());
int bestScore = root.getScore(); int bestScore = root.getScore();
//if (bestScore > currentScore) { //if (bestScore > currentScore) {
actions = new LinkedList<Ability>(root.abilities); actions = new LinkedList<Ability>(root.abilities);
combat = root.combat; combat = root.combat;
//} else { //} else {
//System.out.println("[" + game.getPlayer(playerId).getName() + "] Action: not better score"); //System.out.println("[" + game.getPlayer(playerId).getName() + "] Action: not better score");
//} //}
} else { } else {
System.out.println("[" + game.getPlayer(playerId).getName() + "] Action: skip"); System.out.println("[" + game.getPlayer(playerId).getName() + "] Action: skip");
@ -292,25 +292,24 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
if (root.playerId.equals(playerId) && root.abilities != null && game.getState().getValue(true).hashCode() == test.gameValue) { if (root.playerId.equals(playerId) && root.abilities != null && game.getState().getValue(true).hashCode() == test.gameValue) {
/* /*
// Try to fix horizon effect // Try to fix horizon effect
if (root.combat == null || root.combat.getAttackers().size() == 0) { if (root.combat == null || root.combat.getAttackers().size() == 0) {
FilterCreatureForAttack attackFilter = new FilterCreatureForAttack(); FilterCreatureForAttack attackFilter = new FilterCreatureForAttack();
attackFilter.getControllerId().add(playerId); attackFilter.getControllerId().add(playerId);
List<Permanent> attackers = game.getBattlefield().getAllActivePermanents(attackFilter); List<Permanent> attackers = game.getBattlefield().getAllActivePermanents(attackFilter);
if (attackers.size() > 0) { if (attackers.size() > 0) {
// we have attackers but don't attack with any of them // we have attackers but don't attack with any of them
// let's try once again to avoid possible horizon effect // let's try once again to avoid possible horizon effect
return false; return false;
} }
} }
*/ */
logger.info("simulating -- continuing previous action chain"); logger.info("simulating -- continuing previous action chain");
actions = new LinkedList<Ability>(root.abilities); actions = new LinkedList<Ability>(root.abilities);
combat = root.combat; combat = root.combat;
return true; return true;
} } else {
else {
return false; return false;
} }
} }
@ -320,7 +319,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
protected int minimaxAB(SimulationNode2 node, int depth, int alpha, int beta) { protected int minimaxAB(SimulationNode2 node, int depth, int alpha, int beta) {
UUID currentPlayerId = node.getGame().getPlayerList().get(); UUID currentPlayerId = node.getGame().getPlayerList().get();
SimulationNode2 bestChild = null; SimulationNode2 bestChild = null;
for (SimulationNode2 child: node.getChildren()) { for (SimulationNode2 child : node.getChildren()) {
Combat _combat = child.getCombat(); Combat _combat = child.getCombat();
if (alpha >= beta) { if (alpha >= beta) {
//logger.info("alpha beta pruning"); //logger.info("alpha beta pruning");
@ -330,7 +329,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
//logger.info("simulating -- reached end-state, count=" + SimulationNode2.nodeCount); //logger.info("simulating -- reached end-state, count=" + SimulationNode2.nodeCount);
break; break;
} }
int val = addActions(child, depth-1, alpha, beta); int val = addActions(child, depth - 1, alpha, beta);
if (!currentPlayerId.equals(playerId)) { if (!currentPlayerId.equals(playerId)) {
if (val < beta) { if (val < beta) {
beta = val; beta = val;
@ -345,8 +344,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
logger.debug("lose - break"); logger.debug("lose - break");
break; break;
} }
} } else {
else {
if (val > alpha) { if (val > alpha) {
alpha = val; alpha = val;
bestChild = child; bestChild = child;
@ -363,20 +361,20 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
} }
node.children.clear(); node.children.clear();
if (bestChild != null) if (bestChild != null) {
node.children.add(bestChild); node.children.add(bestChild);
}
if (!currentPlayerId.equals(playerId)) { if (!currentPlayerId.equals(playerId)) {
//logger.info("returning minimax beta: " + beta); //logger.info("returning minimax beta: " + beta);
return beta; return beta;
} } else {
else {
//logger.info("returning minimax alpha: " + alpha); //logger.info("returning minimax alpha: " + alpha);
return alpha; return alpha;
} }
} }
protected SearchEffect getSearchEffect(StackAbility ability) { protected SearchEffect getSearchEffect(StackAbility ability) {
for (Effect effect: ability.getEffects()) { for (Effect effect : ability.getEffects()) {
if (effect instanceof SearchEffect) { if (effect instanceof SearchEffect) {
return (SearchEffect) effect; return (SearchEffect) effect;
} }
@ -391,7 +389,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
if (effect != null && ability.getControllerId().equals(playerId)) { if (effect != null && ability.getControllerId().equals(playerId)) {
Target target = effect.getTarget(); Target target = effect.getTarget();
if (!target.doneChosing()) { if (!target.doneChosing()) {
for (UUID targetId: target.possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) { for (UUID targetId : target.possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) {
Game sim = game.copy(); Game sim = game.copy();
StackAbility newAbility = (StackAbility) ability.copy(); StackAbility newAbility = (StackAbility) ability.copy();
SearchEffect newEffect = getSearchEffect((StackAbility) newAbility); SearchEffect newEffect = getSearchEffect((StackAbility) newAbility);
@ -416,8 +414,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
protected Integer addActionsTimed() { protected Integer addActionsTimed() {
FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() { FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
@Override @Override
public Integer call() throws Exception public Integer call() throws Exception {
{
return addActions(root, maxDepth, Integer.MIN_VALUE, Integer.MAX_VALUE); return addActions(root, maxDepth, Integer.MIN_VALUE, Integer.MAX_VALUE);
} }
}); });
@ -458,19 +455,16 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
UUID currentPlayerId = node.getGame().getPlayerList().get(); UUID currentPlayerId = node.getGame().getPlayerList().get();
//logger.info("reached - " + val + ", playerId=" + playerId + ", node.pid="+currentPlayerId); //logger.info("reached - " + val + ", playerId=" + playerId + ", node.pid="+currentPlayerId);
return val; return val;
} } else if (node.getChildren().size() > 0) {
else if (node.getChildren().size() > 0) {
logger.debug("simulating -- somthing added children:" + node.getChildren().size()); logger.debug("simulating -- somthing added children:" + node.getChildren().size());
val = minimaxAB(node, depth-1, alpha, beta); val = minimaxAB(node, depth - 1, alpha, beta);
return val; return val;
} } else {
else {
logger.debug("simulating -- alpha: " + alpha + " beta: " + beta + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + (node.getPlayerId().equals(playerId) ? "yes" : "no")); logger.debug("simulating -- alpha: " + alpha + " beta: " + beta + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + (node.getPlayerId().equals(playerId) ? "yes" : "no"));
if (allPassed(game)) { if (allPassed(game)) {
if (!game.getStack().isEmpty()) { if (!game.getStack().isEmpty()) {
resolve(node, depth, game); resolve(node, depth, game);
} } else {
else {
game.getPlayers().resetPassed(); game.getPlayers().resetPassed();
playNext(game, game.getActivePlayerId(), node); playNext(game, game.getActivePlayerId(), node);
} }
@ -481,9 +475,8 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} else if (node.getChildren().size() > 0) { } else if (node.getChildren().size() > 0) {
//declared attackers or blockers or triggered abilities //declared attackers or blockers or triggered abilities
logger.debug("simulating -- attack/block/trigger added children:" + node.getChildren().size()); logger.debug("simulating -- attack/block/trigger added children:" + node.getChildren().size());
val = minimaxAB(node, depth-1, alpha, beta); val = minimaxAB(node, depth - 1, alpha, beta);
} } else {
else {
val = simulatePriority(node, game, depth, alpha, beta); val = simulatePriority(node, game, depth, alpha, beta);
} }
} }
@ -506,7 +499,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
List<Ability> allActions = currentPlayer.simulatePriority(game); List<Ability> allActions = currentPlayer.simulatePriority(game);
optimize(game, allActions); optimize(game, allActions);
logger.debug("simulating -- adding " + allActions.size() + " children:" + allActions); logger.debug("simulating -- adding " + allActions.size() + " children:" + allActions);
for (Ability action: allActions) { for (Ability action : allActions) {
if (Thread.interrupted()) { if (Thread.interrupted()) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
logger.debug("interrupted"); logger.debug("interrupted");
@ -515,8 +508,9 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
Game sim = game.copy(); Game sim = game.copy();
if (sim.getPlayer(currentPlayer.getId()).activateAbility((ActivatedAbility) action.copy(), sim)) { if (sim.getPlayer(currentPlayer.getId()).activateAbility((ActivatedAbility) action.copy(), sim)) {
sim.applyEffects(); sim.applyEffects();
if (checkForRepeatedAction(sim, node, action, currentPlayer.getId())) if (checkForRepeatedAction(sim, node, action, currentPlayer.getId())) {
continue; continue;
}
if (!sim.isGameOver() && action.isUsesStack()) { if (!sim.isGameOver() && action.isUsesStack()) {
// only pass if the last action uses the stack // only pass if the last action uses the stack
sim.getPlayer(currentPlayer.getId()).pass(); sim.getPlayer(currentPlayer.getId()).pass();
@ -526,7 +520,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
int testVal = GameStateEvaluator2.evaluate(currentPlayer.getId(), sim); int testVal = GameStateEvaluator2.evaluate(currentPlayer.getId(), sim);
logger.debug("simulating -- node #:" + SimulationNode2.getCount() + " actions:" + action); logger.debug("simulating -- node #:" + SimulationNode2.getCount() + " actions:" + action);
sim.checkStateAndTriggered(); sim.checkStateAndTriggered();
int val = addActions(newNode, depth-1, alpha, beta); int val = addActions(newNode, depth - 1, alpha, beta);
logger.debug("val = " + val); logger.debug("val = " + val);
if (!currentPlayer.getId().equals(playerId)) { if (!currentPlayer.getId().equals(playerId)) {
if (val < beta) { if (val < beta) {
@ -543,8 +537,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
logger.debug("lose - break"); logger.debug("lose - break");
break; break;
} }
} } else {
else {
if (val > alpha) { if (val > alpha) {
alpha = val; alpha = val;
bestNode = newNode; bestNode = newNode;
@ -553,10 +546,10 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
bestNode.setCombat(newNode.getChildren().get(0).getCombat()); bestNode.setCombat(newNode.getChildren().get(0).getCombat());
} }
/*if (node.getTargets().size() > 0) /*if (node.getTargets().size() > 0)
targets = node.getTargets(); targets = node.getTargets();
if (node.getChoices().size() > 0) if (node.getChoices().size() > 0)
choices = node.getChoices(); choices = node.getChoices();
*/ */
if (depth == maxDepth) { if (depth == maxDepth) {
logger.info("saved"); logger.info("saved");
node.children.clear(); node.children.clear();
@ -588,19 +581,18 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
if (!currentPlayer.getId().equals(playerId)) { if (!currentPlayer.getId().equals(playerId)) {
/*if (beta == Integer.MAX_VALUE) { /*if (beta == Integer.MAX_VALUE) {
int val = GameStateEvaluator2.evaluate(playerId, game); int val = GameStateEvaluator2.evaluate(playerId, game);
logger.info("returning priority beta: " + val); logger.info("returning priority beta: " + val);
return val; return val;
}*/ }*/
//logger.info("returning priority beta: " + beta); //logger.info("returning priority beta: " + beta);
return beta; return beta;
} } else {
else {
/*if (alpha == Integer.MIN_VALUE) { /*if (alpha == Integer.MIN_VALUE) {
int val = GameStateEvaluator2.evaluate(playerId, game); int val = GameStateEvaluator2.evaluate(playerId, game);
logger.info("returning priority beta: " + val); logger.info("returning priority beta: " + val);
return val; return val;
}*/ }*/
//logger.info("returning priority alpha: " + alpha); //logger.info("returning priority alpha: " + alpha);
return alpha; return alpha;
} }
@ -644,19 +636,21 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
protected boolean allPassed(Game game) { protected boolean allPassed(Game game) {
for (Player player: game.getPlayers().values()) { for (Player player : game.getPlayers().values()) {
if (!player.isPassed() && !player.hasLost() && !player.hasLeft()) if (!player.isPassed() && !player.hasLost() && !player.hasLeft()) {
return false; return false;
}
} }
return true; return true;
} }
@Override @Override
public boolean choose(Outcome outcome, Choice choice, Game game) { public boolean choose(Outcome outcome, Choice choice, Game game) {
if (choices.isEmpty()) if (choices.isEmpty()) {
return super.choose(outcome, choice, game); return super.choose(outcome, choice, game);
}
if (!choice.isChosen()) { if (!choice.isChosen()) {
for (String achoice: choices) { for (String achoice : choices) {
choice.setChoice(achoice); choice.setChoice(achoice);
if (choice.isChosen()) { if (choice.isChosen()) {
choices.clear(); choices.clear();
@ -669,11 +663,12 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
@Override @Override
public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) {
if (targets.isEmpty()) if (targets.isEmpty()) {
return super.chooseTarget(outcome, cards, target, source, game); return super.chooseTarget(outcome, cards, target, source, game);
}
if (!target.doneChosing()) { if (!target.doneChosing()) {
for (UUID targetId: targets) { for (UUID targetId : targets) {
target.addTarget(targetId, source, game); target.addTarget(targetId, source, game);
if (target.doneChosing()) { if (target.doneChosing()) {
targets.clear(); targets.clear();
@ -686,11 +681,12 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
@Override @Override
public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) { public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) {
if (targets.isEmpty()) if (targets.isEmpty()) {
return super.choose(outcome, cards, target, game); return super.choose(outcome, cards, target, game);
}
if (!target.doneChosing()) { if (!target.doneChosing()) {
for (UUID targetId: targets) { for (UUID targetId : targets) {
target.add(targetId, game); target.add(targetId, game);
if (target.doneChosing()) { if (target.doneChosing()) {
targets.clear(); targets.clear();
@ -702,10 +698,10 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
return true; return true;
} }
@Override @Override
public boolean playXMana(VariableManaCost cost, ManaCosts<ManaCost> costs, Game game) { public boolean playXMana(VariableManaCost cost, ManaCosts<ManaCost> costs, Game game) {
//SimulatedPlayer.simulateVariableCosts method adds a generic mana cost for each option //SimulatedPlayer.simulateVariableCosts method adds a generic mana cost for each option
for (ManaCost manaCost: costs) { for (ManaCost manaCost : costs) {
if (manaCost instanceof GenericManaCost) { if (manaCost instanceof GenericManaCost) {
cost.setPayment(manaCost.getPayment()); cost.setPayment(manaCost.getPayment());
logger.debug("using X = " + cost.getPayment().count()); logger.debug("using X = " + cost.getPayment().count());
@ -721,8 +717,9 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
boolean skip = false; boolean skip = false;
while (true) { while (true) {
Phase currentPhase = game.getPhase(); Phase currentPhase = game.getPhase();
if (!skip) if (!skip) {
currentPhase.getStep().endStep(game, activePlayerId); currentPhase.getStep().endStep(game, activePlayerId);
}
game.applyEffects(); game.applyEffects();
switch (currentPhase.getStep().getType()) { switch (currentPhase.getStep().getType()) {
case UNTAP: case UNTAP:
@ -781,10 +778,10 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} else { } else {
game.getStep().beginStep(game, activePlayerId); game.getStep().beginStep(game, activePlayerId);
} }
if (game.getStep().getHasPriority()) if (game.getStep().getHasPriority()) {
break; break;
} }
else { } else {
skip = true; skip = true;
} }
} }
@ -874,34 +871,35 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_PRE, null, null, activePlayerId)); game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_PRE, null, null, activePlayerId));
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, activePlayerId, activePlayerId))) { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, activePlayerId, activePlayerId))) {
/*for (UUID defenderId: game.getCombat().getDefenders()) { /*for (UUID defenderId: game.getCombat().getDefenders()) {
//check if defender is being attacked //check if defender is being attacked
if (game.getCombat().isAttacked(defenderId, game)) { if (game.getCombat().isAttacked(defenderId, game)) {
for (Combat engagement: ((SimulatedPlayer2)game.getPlayer(defenderId)).addBlockers(game)) { for (Combat engagement: ((SimulatedPlayer2)game.getPlayer(defenderId)).addBlockers(game)) {
Game sim = game.copy(); Game sim = game.copy();
for (CombatGroup group: engagement.getGroups()) { for (CombatGroup group: engagement.getGroups()) {
List<UUID> blockers = new ArrayList<UUID>(); List<UUID> blockers = new ArrayList<UUID>();
blockers.addAll(group.getBlockers()); blockers.addAll(group.getBlockers());
for (UUID blockerId: blockers) { for (UUID blockerId: blockers) {
group.addBlocker(blockerId, defenderId, sim); group.addBlocker(blockerId, defenderId, sim);
} }
blockers = null; blockers = null;
} }
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, playerId, playerId)); sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, playerId, playerId));
SimulationNode2 newNode = new SimulationNode2(node, sim, node.getDepth()-1, defenderId); SimulationNode2 newNode = new SimulationNode2(node, sim, node.getDepth()-1, defenderId);
logger.debug("simulating -- node #:" + SimulationNode2.getCount() + " declare blockers"); logger.debug("simulating -- node #:" + SimulationNode2.getCount() + " declare blockers");
newNode.setCombat(sim.getCombat()); newNode.setCombat(sim.getCombat());
node.children.add(newNode); node.children.add(newNode);
} }
} }
}*/ }*/
} }
} }
/** /**
* Choose attackers based on static information. * Choose attackers based on static information. That means that AI won't
* That means that AI won't look to the future as it was before, but just choose attackers based on current state * look to the future as it was before, but just choose attackers based on
* of the game. This is worse, but at least it is easier to implement and won't lead to the case when AI doesn't * current state of the game. This is worse, but at least it is easier to
* do anything - neither attack nor block. * implement and won't lead to the case when AI doesn't do anything -
* neither attack nor block.
* *
* @param game * @param game
* @param activePlayerId * @param activePlayerId
@ -919,8 +917,22 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
return; return;
} }
for (Permanent attacker : attackersList) {
System.out.println("Number of potential attackers " + attackersList.size());
System.out.println("Potential attacker is " + attacker.getName());
}
if (attackersList.isEmpty()) {
return;
}
List<Permanent> possibleBlockers = defender.getAvailableBlockers(game); List<Permanent> possibleBlockers = defender.getAvailableBlockers(game);
for (Permanent blocker : possibleBlockers) {
System.out.println("Number of blockers " + possibleBlockers.size());
System.out.println("Blocker is " + blocker.getName());
}
List<Permanent> killers = CombatUtil.canKillOpponent(game, attackersList, possibleBlockers, defender); List<Permanent> killers = CombatUtil.canKillOpponent(game, attackersList, possibleBlockers, defender);
if (!killers.isEmpty()) { if (!killers.isEmpty()) {
for (Permanent attacker : killers) { for (Permanent attacker : killers) {
@ -929,148 +941,176 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
return; return;
} }
CombatUtil.handleExalted(); //CombatUtil.handleExalted();
//TODO: refactor -- extract to method //TODO: refactor -- extract to method
List<Permanent> counterAttackList = new ArrayList<Permanent>(); //List<Permanent> counterAttackList = new ArrayList<Permanent>();
int counterAttackDamage = 0; //int counterAttackDamage = 0;
int defenderForces = 0; //int defenderForces = 0;
int defenderForcesForBlock = 0; //int defenderForcesForBlock = 0;
/*
FilterCreatureForCombat filter = new FilterCreatureForCombat();
for (Permanent possibleAttacker : game.getBattlefield().getAllActivePermanents(filter, defender.getId(), game)) {
//TODO: it can be improved with next turn emulation
if (!possibleAttacker.getAbilities().contains(DefenderAbility.getInstance())) {
counterAttackList.add(possibleAttacker);
if (possibleAttacker.getPower().getValue() > 0) {
// TODO: DB and infect
counterAttackDamage += possibleAttacker.getPower().getValue();
defenderForces++;
}
if (CombatUtil.canBlock(game, possibleAttacker)) {
defenderForcesForBlock++;
}
}
}
FilterCreatureForCombat filter = new FilterCreatureForCombat(); double oppScore = 1000000;
for (Permanent possibleAttacker : game.getBattlefield().getAllActivePermanents(filter, defender.getId(), game)) { if (counterAttackDamage > 0) {
//TODO: it can be improved with next turn emulation oppScore = (double) attackingPlayer.getLife() / counterAttackDamage;
if (!possibleAttacker.getAbilities().contains(DefenderAbility.getInstance())) { }
counterAttackList.add(possibleAttacker);
if (possibleAttacker.getPower().getValue() > 0) {
// TODO: DB and infect
counterAttackDamage += possibleAttacker.getPower().getValue();
defenderForces++;
}
if (CombatUtil.canBlock(game, possibleAttacker)) {
defenderForcesForBlock++;
}
}
}
double oppScore = 1000000; List<Permanent> possibleAttackersList = new ArrayList<Permanent>();
if (counterAttackDamage > 0) { int possibleAttackersDamage = 0;
oppScore = (double) attackingPlayer.getLife() / counterAttackDamage; int ourForces = 0;
}
List<Permanent> possibleAttackersList = new ArrayList<Permanent>(); for (Permanent possibleAttacker : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) {
int possibleAttackersDamage = 0; //TODO: it can be improved with next turn emulation
int ourForces = 0; if (!possibleAttacker.getAbilities().contains(DefenderAbility.getInstance())) {
possibleAttackersList.add(possibleAttacker);
for (Permanent possibleAttacker : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) { if (possibleAttacker.getPower().getValue() > 0) {
//TODO: it can be improved with next turn emulation // TODO: DB and infect
if (!possibleAttacker.getAbilities().contains(DefenderAbility.getInstance())) { possibleAttackersDamage += possibleAttacker.getPower().getValue();
possibleAttackersList.add(possibleAttacker); ourForces++;
}
}
}
if (possibleAttacker.getPower().getValue() > 0) { double ourScore = 1000000;
// TODO: DB and infect if (possibleAttackersDamage > 0) {
possibleAttackersDamage += possibleAttacker.getPower().getValue(); ourScore = (double) defender.getLife() / possibleAttackersDamage;
ourForces++; }
}
}
}
double ourScore = 1000000; int outNumber = ourForces - defenderForces;
if (possibleAttackersDamage > 0) {
ourScore = (double) defender.getLife() / possibleAttackersDamage;
}
int outNumber = ourForces - defenderForces; double score = ourScore - oppScore;
double score = ourScore - oppScore; boolean doAttack = false;
boolean doAttack = false; //attackersList
CombatUtil.sortByPower(attackersList, false);
int opponentLife = defender.getLife();
//attackersList List<Permanent> notBlockedAttackers = new ArrayList<Permanent>();
CombatUtil.sortByPower(attackersList, false); for (int i = 0; i < (attackersList.size() - defenderForces); i++) {
int opponentLife = defender.getLife(); notBlockedAttackers.add(attackersList.get(i));
}
List<Permanent> notBlockedAttackers = new ArrayList<Permanent>(); int attackRound = 1;
for (int i = 0; i < (attackersList.size() - defenderForces); i++) { while (notBlockedAttackers.size() > 0 && opponentLife > 0 && attackRound < 99) {
notBlockedAttackers.add(attackersList.get(i)); int damageThisRound = 0;
} for (Permanent attacker : notBlockedAttackers) {
damageThisRound += attacker.getPower().getValue();
}
opponentLife -= damageThisRound;
for (int i = 0; i < defenderForcesForBlock && !notBlockedAttackers.isEmpty(); i++) {
notBlockedAttackers.remove(notBlockedAttackers.size() - 1);
}
attackRound++;
if (opponentLife <= 0) {
doAttack = true;
}
}
int attackRound = 1; double unblockableDamage = 0;
while (notBlockedAttackers.size() > 0 && opponentLife > 0 && attackRound < 99) { double turnsUntilDeathByUnblockable = 0;
int damageThisRound = 0; boolean doUnblockableAttack = false;
for (Permanent attacker : notBlockedAttackers) { for (Permanent attacker : attackersList) {
damageThisRound += attacker.getPower().getValue(); boolean isUnblockableCreature = true;
} for (Permanent blocker : possibleBlockers) {
opponentLife -= damageThisRound; if (blocker.canBlock(attacker.getId(), game)) {
for (int i = 0; i < defenderForcesForBlock && !notBlockedAttackers.isEmpty(); i++) { isUnblockableCreature = false;
notBlockedAttackers.remove(notBlockedAttackers.size() - 1); }
} }
attackRound++; if (isUnblockableCreature) {
if (opponentLife <= 0) { unblockableDamage += attacker.getPower().getValue();
doAttack = true; }
} }
} if (unblockableDamage > 0) {
turnsUntilDeathByUnblockable = defender.getLife() / unblockableDamage;
}
if (unblockableDamage > defender.getLife()) {
doUnblockableAttack = true;
}
int aggressionRate = 5;
//aggressionRate = getAggressionRate(oppScore, ourScore, outNumber, score, doAttack, turnsUntilDeathByUnblockable, doUnblockableAttack, aggressionRate);
System.out.println("AI aggression = " + String.valueOf(aggressionRate));
System.out.println("AI attackers size: " + attackersList.size());
List<Permanent> finalAttackers = new ArrayList<Permanent>();
for (int i = 0; i < attackersList.size(); i++) {
Permanent attacker = attackersList.get(i);
int totalFirstStrikeBlockPower = 0;
if (!attacker.getAbilities().contains(FirstStrikeAbility.getInstance()) && !attacker.getAbilities().contains(DoubleStrikeAbility.getInstance())) {
for (Permanent blockerWithFSorDB : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) {
if (blockerWithFSorDB.getAbilities().contains(DoubleStrikeAbility.getInstance())) {
totalFirstStrikeBlockPower += 2 * blockerWithFSorDB.getPower().getValue();
} else
if (blockerWithFSorDB.getAbilities().contains(FirstStrikeAbility.getInstance())) {
totalFirstStrikeBlockPower += blockerWithFSorDB.getPower().getValue();
}
}
}
boolean shouldAttack = shouldAttack(game, attackingPlayer.getId(), defenderId, attacker, possibleBlockers, aggressionRate);
if (aggressionRate == 5 || shouldAttack && (totalFirstStrikeBlockPower < attacker.getToughness().getValue()) ) {
finalAttackers.add(attacker);
}
}
*/
// The AI will now attack more sanely. Simple, but good enough for now.
// The sim minmax does not work at the moment.
boolean safeToAttack;
CombatEvaluator eval = new CombatEvaluator();
double unblockableDamage = 0;
double turnsUntilDeathByUnblockable = 0;
boolean doUnblockableAttack = false;
for (Permanent attacker : attackersList) { for (Permanent attacker : attackersList) {
boolean isUnblockableCreature = true; safeToAttack = true;
int attackerValue = eval.evaluate(attacker, game);
for (Permanent blocker : possibleBlockers) { for (Permanent blocker : possibleBlockers) {
if (blocker.canBlock(attacker.getId(), game)) { int blockerValue = eval.evaluate(blocker, game);
isUnblockableCreature = false; if (attacker.getPower().getValue() <= blocker.getToughness().getValue()
&& attacker.getToughness().getValue() <= blocker.getPower().getValue()) {
safeToAttack = false;
} }
}
if (isUnblockableCreature) {
unblockableDamage += attacker.getPower().getValue();
}
}
if (unblockableDamage > 0) {
turnsUntilDeathByUnblockable = defender.getLife() / unblockableDamage;
}
if (unblockableDamage > defender.getLife()) {
doUnblockableAttack = true;
}
int aggressionRate = 5; if (attacker.getToughness().getValue() == blocker.getPower().getValue()
//aggressionRate = getAggressionRate(oppScore, ourScore, outNumber, score, doAttack, turnsUntilDeathByUnblockable, doUnblockableAttack, aggressionRate); && attacker.getPower().getValue() == blocker.getToughness().getValue()) {
System.out.println("AI aggression = " + String.valueOf(aggressionRate)); if (attackerValue < blockerValue
|| blocker.getAbilities().containsKey(FirstStrikeAbility.getInstance().getId())
|| blocker.getAbilities().containsKey(DoubleStrikeAbility.getInstance().getId())) {
System.out.println("AI attackers size: " + attackersList.size()); safeToAttack = false;
List<Permanent> finalAttackers = new ArrayList<Permanent>();
for (int i = 0; i < attackersList.size(); i++) {
Permanent attacker = attackersList.get(i);
int totalFirstStrikeBlockPower = 0;
if (!attacker.getAbilities().contains(FirstStrikeAbility.getInstance()) && !attacker.getAbilities().contains(DoubleStrikeAbility.getInstance())) {
for (Permanent blockerWithFSorDB : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) {
if (blockerWithFSorDB.getAbilities().contains(DoubleStrikeAbility.getInstance())) {
totalFirstStrikeBlockPower += 2 * blockerWithFSorDB.getPower().getValue();
} else
if (blockerWithFSorDB.getAbilities().contains(FirstStrikeAbility.getInstance())) {
totalFirstStrikeBlockPower += blockerWithFSorDB.getPower().getValue();
} }
} }
} }
if (attacker.getAbilities().containsKey(DeathtouchAbility.getInstance().getId())) {
boolean shouldAttack = shouldAttack(game, attackingPlayer.getId(), defenderId, attacker, possibleBlockers, aggressionRate); safeToAttack = true;
}
if (aggressionRate == 5 || shouldAttack && (totalFirstStrikeBlockPower < attacker.getToughness().getValue()) ) { if (safeToAttack) {
finalAttackers.add(attacker); attackingPlayer.declareAttacker(attacker.getId(), defenderId, game);
} }
}
System.out.println("AI final attackers size: " + attackersList.size());
for (Permanent attacker : finalAttackers) {
attackingPlayer.declareAttacker(attacker.getId(), defenderId, game);
} }
} }
} }
/*
private boolean shouldAttack(Game game, UUID attackingPlayerId, UUID defenderId, Permanent attacker, List<Permanent> blockers, int aggressionRate) { private boolean shouldAttack(Game game, UUID attackingPlayerId, UUID defenderId, Permanent attacker, List<Permanent> blockers, int aggressionRate) {
boolean canBeKilledByOne = false; boolean canBeKilledByOne = false;
boolean canKillAll = true; boolean canKillAll = true;
@ -1080,17 +1120,22 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
boolean canBeBlocked = false; boolean canBeBlocked = false;
int numberOfPossibleBlockers = 0; int numberOfPossibleBlockers = 0;
int life = game.getPlayer(defenderId).getLife(); //int life = game.getPlayer(defenderId).getLife();
int poison = game.getPlayer(defenderId).getCounters().getCount(CounterType.POISON); //int poison = game.getPlayer(defenderId).getCounters().getCount(CounterType.POISON);
if (!isEffectiveAttacker(game, attackingPlayerId, defenderId, attacker, life, poison)) {
return false;
}
if (!isEffectiveAttacker(game, attackingPlayerId, defenderId, attacker, life, poison)) {
System.out.println("Ahh, this is why it is not attacking");
return false;
}
for (Permanent defender : blockers) { for (Permanent defender : blockers) {
System.out.println("The blocker is " + defender.getName());
if (defender.canBlock(attacker.getId(), game)) { if (defender.canBlock(attacker.getId(), game)) {
System.out.println("The blocker can block the attacker" + defender.getName() + attacker.getName());
numberOfPossibleBlockers += 1; numberOfPossibleBlockers += 1;
System.out.println("The number of possible blockers is " + numberOfPossibleBlockers);
SurviveInfo info = CombatUtil.willItSurvive(game, attackingPlayerId, defenderId, attacker, defender); SurviveInfo info = CombatUtil.willItSurvive(game, attackingPlayerId, defenderId, attacker, defender);
System.out.println("Did the attacker die? " + info.isAttackerDied());
if (info.isAttackerDied()) { if (info.isAttackerDied()) {
boolean canBeReallyKilled = true; boolean canBeReallyKilled = true;
for (Ability ability : attacker.getAbilities()) { for (Ability ability : attacker.getAbilities()) {
@ -1128,9 +1173,12 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
if (numberOfPossibleBlockers >= 1) { if (numberOfPossibleBlockers >= 1) {
canBeBlocked = true; canBeBlocked = true;
} }
// This is how I know this does quite work. Something is wrong with the sim part.
System.out.println("canKillAll, canKillAllDangerous, canbeKilledByOne, canBeBlocked " + canKillAll + canKillAllDangerous + canBeKilledByOne + canBeBlocked);
switch (aggressionRate) { switch (aggressionRate) {
case 4: case 4:
if (canKillAll || (canKillAllDangerous && !canBeKilledByOne) || !canBeBlocked) { if (canKillAll || (canKillAllDangerous && !canBeKilledByOne) || !canBeBlocked) {
System.out.println(attacker.getName() + " = attacking expecting to at least trade with something"); System.out.println(attacker.getName() + " = attacking expecting to at least trade with something");
return true; return true;
@ -1185,7 +1233,6 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
return false; return false;
} }
private int getAggressionRate(double oppScore, double ourScore, int outNumber, double score, boolean doAttack, double turnsUntilDeathByUnblockable, boolean doUnblockableAttack, int aggressionRate) { private int getAggressionRate(double oppScore, double ourScore, int outNumber, double score, boolean doAttack, double turnsUntilDeathByUnblockable, boolean doUnblockableAttack, int aggressionRate) {
if (score > 0 && doAttack) { if (score > 0 && doAttack) {
aggressionRate = 5; aggressionRate = 5;
@ -1203,20 +1250,20 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
return aggressionRate; return aggressionRate;
} }
*/
private void declareAttackers(Game game, UUID activePlayerId, SimulationNode2 node) { private void declareAttackers(Game game, UUID activePlayerId, SimulationNode2 node) {
game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_ATTACKERS_STEP_PRE, null, null, activePlayerId)); game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_ATTACKERS_STEP_PRE, null, null, activePlayerId));
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, activePlayerId, activePlayerId))) { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, activePlayerId, activePlayerId))) {
for (Combat engagement: ((SimulatedPlayer2)game.getPlayer(activePlayerId)).addAttackers(game)) { for (Combat engagement : ((SimulatedPlayer2) game.getPlayer(activePlayerId)).addAttackers(game)) {
Game sim = game.copy(); Game sim = game.copy();
UUID defenderId = game.getOpponents(playerId).iterator().next(); UUID defenderId = game.getOpponents(playerId).iterator().next();
for (CombatGroup group: engagement.getGroups()) { for (CombatGroup group : engagement.getGroups()) {
for (UUID attackerId: group.getAttackers()) { for (UUID attackerId : group.getAttackers()) {
sim.getPlayer(activePlayerId).declareAttacker(attackerId, defenderId, sim); sim.getPlayer(activePlayerId).declareAttacker(attackerId, defenderId, sim);
} }
} }
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_ATTACKERS, playerId, playerId)); sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_ATTACKERS, playerId, playerId));
SimulationNode2 newNode = new SimulationNode2(node, sim, node.getDepth()-1, activePlayerId); SimulationNode2 newNode = new SimulationNode2(node, sim, node.getDepth() - 1, activePlayerId);
logger.debug("simulating -- node #:" + SimulationNode2.getCount() + " declare attakers"); logger.debug("simulating -- node #:" + SimulationNode2.getCount() + " declare attakers");
newNode.setCombat(sim.getCombat()); newNode.setCombat(sim.getCombat());
node.children.add(newNode); node.children.add(newNode);
@ -1229,34 +1276,36 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
logger.debug("selectAttackers"); logger.debug("selectAttackers");
declareAttackers(game, playerId); declareAttackers(game, playerId);
/*if (combat != null) { /*if (combat != null) {
UUID opponentId = game.getCombat().getDefenders().iterator().next(); UUID opponentId = game.getCombat().getDefenders().iterator().next();
String attackers = ""; String attackers = "";
for (UUID attackerId: combat.getAttackers()) { for (UUID attackerId: combat.getAttackers()) {
Permanent attacker = game.getPermanent(attackerId); Permanent attacker = game.getPermanent(attackerId);
if (attacker != null) { if (attacker != null) {
attackers = "[" + attacker.getName() + "]"; attackers = "[" + attacker.getName() + "]";
this.declareAttacker(attackerId, opponentId, game); this.declareAttacker(attackerId, opponentId, game);
} }
} }
logger.info("declare attackers: " + (attackers.isEmpty() ? "none" : attackers)); logger.info("declare attackers: " + (attackers.isEmpty() ? "none" : attackers));
}*/ }*/
} }
@Override @Override
public void selectBlockers(Game game, UUID defendingPlayerId) { public void selectBlockers(Game game, UUID defendingPlayerId) {
logger.debug("selectBlockers"); logger.debug("selectBlockers");
if (combat != null && combat.getGroups().size() > 0) { declareBlockers(game, playerId);
List<CombatGroup> groups = game.getCombat().getGroups(); /*if (combat != null && combat.getGroups().size() > 0) {
for (int i = 0; i < groups.size(); i++) { List<CombatGroup> groups = game.getCombat().getGroups();
if (i < combat.getGroups().size()) { for (int i = 0; i < groups.size(); i++) {
for (UUID blockerId: combat.getGroups().get(i).getBlockers()) { if (i < combat.getGroups().size()) {
logger.info("select blocker: " + blockerId + " vs " + groups.get(i).getAttackers().get(0)); for (UUID blockerId: combat.getGroups().get(i).getBlockers()) {
this.declareBlocker(blockerId, groups.get(i).getAttackers().get(0), game); logger.info("select blocker: " + blockerId + " vs " + groups.get(i).getAttackers().get(0));
} this.declareBlocker(blockerId, groups.get(i).getAttackers().get(0), game);
} }
} }
} }
}
*/
} }
/** /**
@ -1268,7 +1317,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
protected Game createSimulation(Game game) { protected Game createSimulation(Game game) {
Game sim = game.copy(); Game sim = game.copy();
for (Player copyPlayer: sim.getState().getPlayers().values()) { for (Player copyPlayer : sim.getState().getPlayers().values()) {
Player origPlayer = game.getState().getPlayers().get(copyPlayer.getId()).copy(); Player origPlayer = game.getState().getPlayers().get(copyPlayer.getId()).copy();
System.out.println("suggested=" + suggested); System.out.println("suggested=" + suggested);
SimulatedPlayer2 newPlayer = new SimulatedPlayer2(copyPlayer.getId(), copyPlayer.getId().equals(playerId), suggested); SimulatedPlayer2 newPlayer = new SimulatedPlayer2(copyPlayer.getId(), copyPlayer.getId().equals(playerId), suggested);
@ -1279,8 +1328,9 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
private boolean checkForRepeatedAction(Game sim, SimulationNode2 node, Ability action, UUID playerId) { private boolean checkForRepeatedAction(Game sim, SimulationNode2 node, Ability action, UUID playerId) {
if (action instanceof PassAbility) if (action instanceof PassAbility) {
return false; return false;
}
int newVal = GameStateEvaluator2.evaluate(playerId, sim); int newVal = GameStateEvaluator2.evaluate(playerId, sim);
SimulationNode2 test = node.getParent(); SimulationNode2 test = node.getParent();
while (test != null) { while (test != null) {