Fixed AI doesn't play spells that targets creatureOrPlayer. The fix applied to ai-ma only, other ai jar still needs to be recompiled.

This commit is contained in:
magenoxx 2011-02-12 23:21:20 +03:00
parent 6f576f74f5
commit e189543699
5 changed files with 88 additions and 30 deletions

View file

@ -48,6 +48,7 @@ import mage.abilities.Ability;
import mage.abilities.ActivatedAbility; import mage.abilities.ActivatedAbility;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.SearchEffect; import mage.abilities.effects.SearchEffect;
import mage.cards.Card;
import mage.cards.Cards; import mage.cards.Cards;
import mage.choices.Choice; import mage.choices.Choice;
import mage.filter.FilterAbility; import mage.filter.FilterAbility;
@ -55,6 +56,7 @@ import mage.game.Game;
import mage.game.combat.Combat; import mage.game.combat.Combat;
import mage.game.combat.CombatGroup; import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility; import mage.game.stack.StackAbility;
import mage.game.stack.StackObject; import mage.game.stack.StackObject;
import mage.game.turn.BeginCombatStep; import mage.game.turn.BeginCombatStep;
@ -136,18 +138,39 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
pass(); pass();
break; break;
case PRECOMBAT_MAIN: case PRECOMBAT_MAIN:
case BEGIN_COMBAT:
case DECLARE_ATTACKERS:
case DECLARE_BLOCKERS:
case COMBAT_DAMAGE:
case END_COMBAT:
case POSTCOMBAT_MAIN: case POSTCOMBAT_MAIN:
if (game.getActivePlayerId().equals(playerId)) {
Player player = game.getPlayer(playerId);
System.out.println("Turn::"+game.getTurnNum());
System.out.println("[" + game.getPlayer(playerId).getName() + "] " + game.getTurn().getStepType().name() +", life=" + player.getLife());
String s = "[";
for (Card card : player.getHand().getCards(game)) {
s += card.getName() + ";";
}
s += "]";
System.out.println("Hand: " + s);
s = "[";
for (Permanent permanent : game.getBattlefield().getAllPermanents()) {
if (permanent.getOwnerId().equals(player.getId())) {
s += permanent.getName() + ";";
}
}
s += "]";
System.out.println("Permanents: " + s);
}
if (actions.size() == 0) { if (actions.size() == 0) {
calculateActions(game); calculateActions(game);
} }
act(game); act(game);
break; break;
case BEGIN_COMBAT:
case DECLARE_ATTACKERS:
case DECLARE_BLOCKERS:
case COMBAT_DAMAGE:
case END_COMBAT:
case END_TURN: case END_TURN:
pass();
break;
case CLEANUP: case CLEANUP:
pass(); pass();
break; break;
@ -181,8 +204,11 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
addActionsTimed(new FilterAbility()); addActionsTimed(new FilterAbility());
if (root.children.size() > 0) { if (root.children.size() > 0) {
root = root.children.get(0); root = root.children.get(0);
actions = new LinkedList<Ability>(root.abilities); int bestScore = GameStateEvaluator2.evaluate(playerId, root.getGame());
combat = root.combat; if (bestScore > currentScore) {
actions = new LinkedList<Ability>(root.abilities);
combat = root.combat;
}
} }
} }
} }
@ -243,11 +269,11 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
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;
} }
} }
@ -311,7 +337,7 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
} }
protected int addActions(SimulationNode2 node, FilterAbility filter, int depth, int alpha, int beta) { protected int addActions(SimulationNode2 node, FilterAbility filter, int depth, int alpha, int beta) {
logger.info("addActions: " + depth + ", alpha=" + alpha + ", beta=" + beta); logger.fine("addActions: " + depth + ", alpha=" + alpha + ", beta=" + beta);
Game game = node.getGame(); Game game = node.getGame();
int val; int val;
if (Thread.interrupted()) { if (Thread.interrupted()) {
@ -320,16 +346,16 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
return GameStateEvaluator2.evaluate(playerId, game); return GameStateEvaluator2.evaluate(playerId, game);
} }
if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.isGameOver()) { if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.isGameOver()) {
logger.info("simulating -- reached end state, node count="+ SimulationNode2.nodeCount + ", depth="+depth); logger.fine("simulating -- reached end state, node count="+ SimulationNode2.nodeCount + ", depth="+depth);
val = GameStateEvaluator2.evaluate(playerId, game); val = GameStateEvaluator2.evaluate(playerId, game);
} }
else if (node.getChildren().size() > 0) { else if (node.getChildren().size() > 0) {
logger.info("simulating -- somthing added children:" + node.getChildren().size()); logger.fine("simulating -- somthing added children:" + node.getChildren().size());
val = minimaxAB(node, filter, depth-1, alpha, beta); val = minimaxAB(node, filter, depth-1, alpha, beta);
} }
else { else {
if (logger.isLoggable(Level.FINE)) if (logger.isLoggable(Level.FINE))
logger.info("simulating -- alpha: " + alpha + " beta: " + beta + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + (node.getPlayerId().equals(playerId)?"yes":"no")); logger.fine("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);
@ -350,10 +376,9 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
val = GameStateEvaluator2.evaluate(playerId, game); val = GameStateEvaluator2.evaluate(playerId, game);
} }
else if (node.getChildren().size() > 0) { else if (node.getChildren().size() > 0) {
throw new RuntimeException("This shouldn't happen.");
//declared attackers or blockers or triggered abilities //declared attackers or blockers or triggered abilities
///logger.info("simulating -- attack/block/trigger added children:" + node.getChildren().size()); logger.fine("simulating -- attack/block/trigger added children:" + node.getChildren().size());
///val = minimaxAB(node, filter, depth-1, alpha, beta); val = minimaxAB(node, filter, depth-1, alpha, beta);
} }
else { else {
val = simulatePriority(node, game, filter, depth, alpha, beta); val = simulatePriority(node, game, filter, depth, alpha, beta);
@ -361,7 +386,7 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
} }
if (logger.isLoggable(Level.FINE)) if (logger.isLoggable(Level.FINE))
logger.info("returning -- score: " + val + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + game.getPlayer(node.getPlayerId()).getName()); logger.fine("returning -- score: " + val + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + game.getPlayer(node.getPlayerId()).getName());
return val; return val;
} }
@ -378,7 +403,7 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
SimulationNode2 bestNode = null; SimulationNode2 bestNode = null;
List<Ability> allActions = currentPlayer.simulatePriority(game, filter); List<Ability> allActions = currentPlayer.simulatePriority(game, filter);
if (logger.isLoggable(Level.FINE)) if (logger.isLoggable(Level.FINE))
logger.info("simulating -- adding " + allActions.size() + " children:" + allActions); logger.fine("simulating -- adding " + allActions.size() + " children:" + allActions);
for (Ability action: allActions) { for (Ability action: allActions) {
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)) {
@ -390,7 +415,7 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
} }
SimulationNode2 newNode = new SimulationNode2(sim, action, depth, currentPlayer.getId()); SimulationNode2 newNode = new SimulationNode2(sim, action, depth, currentPlayer.getId());
if (logger.isLoggable(Level.FINE)) if (logger.isLoggable(Level.FINE))
logger.info("simulating -- node #:" + SimulationNode2.getCount() + " actions:" + action); logger.fine("simulating -- node #:" + SimulationNode2.getCount() + " actions:" + action);
sim.checkStateAndTriggered(); sim.checkStateAndTriggered();
int val = addActions(newNode, filter, depth-1, alpha, beta); int val = addActions(newNode, filter, depth-1, alpha, beta);
if (!currentPlayer.getId().equals(playerId)) { if (!currentPlayer.getId().equals(playerId)) {
@ -416,7 +441,7 @@ public class ComputerPlayer4 extends ComputerPlayer<ComputerPlayer4> implements
break; break;
} }
if (SimulationNode2.nodeCount > maxNodes) { if (SimulationNode2.nodeCount > maxNodes) {
logger.info("simulating -- reached end-state"); logger.fine("simulating -- reached end-state");
break; break;
} }
} }

View file

@ -112,6 +112,7 @@ public class ComputerPlayer5 extends ComputerPlayer4 implements Player {
case PRECOMBAT_MAIN: case PRECOMBAT_MAIN:
if (game.getActivePlayerId().equals(playerId)) { if (game.getActivePlayerId().equals(playerId)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
System.out.println("Turn:"+game.getTurnNum());
System.out.println("[" + game.getPlayer(playerId).getName() + "] Precombat Main, life=" + player.getLife()); System.out.println("[" + game.getPlayer(playerId).getName() + "] Precombat Main, life=" + player.getLife());
String s = "["; String s = "[";
for (Card card : player.getHand().getCards(game)) { for (Card card : player.getHand().getCards(game)) {
@ -181,8 +182,11 @@ public class ComputerPlayer5 extends ComputerPlayer4 implements Player {
addActionsTimed(new FilterAbility()); addActionsTimed(new FilterAbility());
if (root.children.size() > 0) { if (root.children.size() > 0) {
root = root.children.get(0); root = root.children.get(0);
actions = new LinkedList<Ability>(root.abilities); int bestScore = GameStateEvaluator2.evaluate(playerId, root.getGame());
combat = root.combat; if (bestScore > currentScore) {
actions = new LinkedList<Ability>(root.abilities);
combat = root.combat;
}
} }
//} //}
} }
@ -197,8 +201,11 @@ public class ComputerPlayer5 extends ComputerPlayer4 implements Player {
addActionsTimed(new FilterAbility()); addActionsTimed(new FilterAbility());
if (root.children.size() > 0) { if (root.children.size() > 0) {
root = root.children.get(0); root = root.children.get(0);
actions = new LinkedList<Ability>(root.abilities); int bestScore = GameStateEvaluator2.evaluate(playerId, root.getGame());
combat = root.combat; if (bestScore > currentScore) {
actions = new LinkedList<Ability>(root.abilities);
combat = root.combat;
}
} }
} }
} }
@ -240,7 +247,7 @@ public class ComputerPlayer5 extends ComputerPlayer4 implements Player {
logger.fine("step finished"); logger.fine("step finished");
int testScore = GameStateEvaluator2.evaluate(playerId, game); int testScore = GameStateEvaluator2.evaluate(playerId, game);
if (game.getActivePlayerId().equals(playerId)) { if (game.getActivePlayerId().equals(playerId)) {
if (testScore < currentScore) { if (testScore <= currentScore) {
// if score at end of step is worse than original score don't check further // if score at end of step is worse than original score don't check further
logger.fine("simulating -- abandoning check, no immediate benefit"); logger.fine("simulating -- abandoning check, no immediate benefit");
val = testScore; val = testScore;

View file

@ -64,6 +64,7 @@ import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.TrampleAbility;
import mage.abilities.mana.ManaAbility; import mage.abilities.mana.ManaAbility;
import mage.abilities.mana.ManaOptions; import mage.abilities.mana.ManaOptions;
import mage.filter.common.*;
import mage.game.draft.Draft; import mage.game.draft.Draft;
import mage.player.ai.simulators.CombatGroupSimulator; import mage.player.ai.simulators.CombatGroupSimulator;
import mage.player.ai.simulators.CombatSimulator; import mage.player.ai.simulators.CombatSimulator;
@ -73,10 +74,6 @@ import mage.cards.Cards;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.choices.Choice; import mage.choices.Choice;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreatureForCombat;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterLandCard;
import mage.filter.common.FilterNonlandCard;
import mage.game.Game; import mage.game.Game;
import mage.game.Table; import mage.game.Table;
import mage.game.combat.CombatGroup; import mage.game.combat.CombatGroup;
@ -90,6 +87,7 @@ import mage.target.TargetAmount;
import mage.target.TargetCard; import mage.target.TargetCard;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import mage.target.common.TargetCreatureOrPlayer;
import mage.target.common.TargetDiscard; import mage.target.common.TargetDiscard;
import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetCreatureOrPlayerAmount; import mage.target.common.TargetCreatureOrPlayerAmount;
@ -271,6 +269,34 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
} }
} }
} }
if (target instanceof TargetCreatureOrPlayer) {
List<Permanent> targets;
TargetCreatureOrPlayer t = ((TargetCreatureOrPlayer)target);
if (outcome.isGood()) {
targets = threats(playerId, ((FilterCreatureOrPlayer)t.getFilter()).getCreatureFilter(), game);
}
else {
targets = threats(opponentId, ((FilterCreatureOrPlayer)t.getFilter()).getCreatureFilter(), game);
}
for (Permanent permanent: targets) {
if (((TargetPermanent)target).canTarget(playerId, permanent.getId(), source, game)) {
target.addTarget(permanent.getId(), source, game);
return true;
}
}
if (outcome.isGood()) {
if (target.canTarget(playerId, source, game)) {
target.addTarget(playerId, source, game);
return true;
}
}
else {
if (target.canTarget(playerId, source, game)) {
target.addTarget(opponentId, source, game);
return true;
}
}
}
return false; return false;
} }

View file

@ -4,7 +4,7 @@
<server serverAddress="localhost" serverName="mage-server" port="17171" maxGameThreads="10" maxSecondsIdle="600"/> <server serverAddress="localhost" serverName="mage-server" port="17171" maxGameThreads="10" maxSecondsIdle="600"/>
<playerTypes> <playerTypes>
<playerType name="Computer - minimax hybrid" jar="mage-player-aiminimax.jar" className="mage.player.ai.ComputerPlayer3"/> <playerType name="Computer - minimax hybrid" jar="mage-player-aiminimax.jar" className="mage.player.ai.ComputerPlayer3"/>
<playerType name="Computer - mad" jar="mage-player-ai-ma.jar" className="mage.player.ai.ComputerPlayer5"/> <playerType name="Computer - mad" jar="mage-player-ai-ma.jar" className="mage.player.ai.ComputerPlayer4"/>
</playerTypes> </playerTypes>
<gameTypes> <gameTypes>
<gameType name="Two Player Duel" jar="mage-game-twoplayerduel.jar" className="mage.game.TwoPlayerMatch" typeName="mage.game.TwoPlayerDuelType"/> <gameType name="Two Player Duel" jar="mage-game-twoplayerduel.jar" className="mage.game.TwoPlayerMatch" typeName="mage.game.TwoPlayerDuelType"/>