mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 11:32:00 -08:00
- 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:
parent
fec750ef01
commit
1d7e9e55be
1 changed files with 323 additions and 273 deletions
|
|
@ -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)) {
|
if (!isEffectiveAttacker(game, attackingPlayerId, defenderId, attacker, life, poison)) {
|
||||||
return false;
|
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()) {
|
||||||
|
|
@ -1129,8 +1174,11 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
|
||||||
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) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue