mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
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:
parent
6f576f74f5
commit
e189543699
5 changed files with 88 additions and 30 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"/>
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue