use of mage.abilities.common.PassAbility in project mage by magefree.
the class ComputerPlayerMCTS method priority.
@Override
public boolean priority(Game game) {
if (game.getStep().getType() == PhaseStep.UPKEEP) {
if (!lastPhase.equals(game.getTurn().getValue(game.getTurnNum()))) {
logList(game.getTurn().getValue(game.getTurnNum()) + name + " hand: ", new ArrayList(hand.getCards(game)));
lastPhase = game.getTurn().getValue(game.getTurnNum());
if (MCTSNode.USE_ACTION_CACHE) {
int count = MCTSNode.cleanupCache(game.getTurnNum());
if (count > 0)
logger.info("Removed " + count + " cache entries");
}
}
}
game.getState().setPriorityPlayerId(playerId);
game.firePriorityEvent(playerId);
getNextAction(game, NextAction.PRIORITY);
Ability ability = root.getAction();
if (ability == null)
logger.fatal("null ability");
activateAbility((ActivatedAbility) ability, game);
if (ability instanceof PassAbility)
return false;
logLife(game);
logger.info("choose action:" + root.getAction() + " success ratio: " + root.getWinRatio());
return true;
}
use of mage.abilities.common.PassAbility in project mage by magefree.
the class SimulatedPlayerMCTS method priority.
@Override
public boolean priority(Game game) {
// logger.info("priority");
boolean didSomething = false;
Ability ability = getAction(game);
// logger.info("simulate " + ability.toString());
if (!(ability instanceof PassAbility)) {
didSomething = true;
}
activateAbility((ActivatedAbility) ability, game);
actionCount++;
return didSomething;
}
use of mage.abilities.common.PassAbility in project mage by magefree.
the class ComputerPlayer2 method checkForUselessAction.
/**
* resolve current ability on the stack if there is one, then
* check if current game state is the same as the previous, if so then
* action has no effect and is not useful
*
* @param sim
* @param node
* @param action
* @param playerId
* @return
*/
private boolean checkForUselessAction(Game sim, SimulationNode node, Ability action, UUID playerId) {
int currentVal = 0;
int prevVal = 0;
if (action instanceof PassAbility)
return false;
SimulationNode test = node.getParent();
if (test == null)
return false;
if (action.isUsesStack()) {
Game testSim = sim.copy();
StackObject ability = testSim.getStack().pop();
ability.resolve(testSim);
testSim.applyEffects();
currentVal = GameStateEvaluator.evaluate(playerId, testSim, true);
} else {
currentVal = GameStateEvaluator.evaluate(playerId, sim, true);
}
prevVal = GameStateEvaluator.evaluate(playerId, test.getGame(), true);
return currentVal == prevVal;
}
use of mage.abilities.common.PassAbility in project mage by magefree.
the class ComputerPlayer6 method simulatePriority.
protected int simulatePriority(SimulationNode2 node, Game game, int depth, int alpha, int beta) {
if (!COMPUTER_DISABLE_TIMEOUT_IN_GAME_SIMULATIONS && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.info("interrupted");
return GameStateEvaluator2.evaluate(playerId, game).getTotalScore();
}
node.setGameValue(game.getState().getValue(true).hashCode());
SimulatedPlayer2 currentPlayer = (SimulatedPlayer2) game.getPlayer(game.getPlayerList().get());
SimulationNode2 bestNode = null;
List<Ability> allActions = currentPlayer.simulatePriority(game);
optimize(game, allActions);
int startedScore = GameStateEvaluator2.evaluate(this.getId(), node.getGame()).getTotalScore();
if (logger.isInfoEnabled() && !allActions.isEmpty() && depth == maxDepth) {
logger.info(String.format("POSSIBLE ACTIONS for %s (%d, started score: %d)%s", getName(), allActions.size(), startedScore, (actions.isEmpty() ? "" : ":")));
for (int i = 0; i < allActions.size(); i++) {
logger.info(String.format("-> #%d (%s)", i + 1, allActions.get(i)));
}
}
int actionNumber = 0;
int bestValSubNodes = Integer.MIN_VALUE;
for (Ability action : allActions) {
actionNumber++;
if (!COMPUTER_DISABLE_TIMEOUT_IN_GAME_SIMULATIONS && Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.info("Sim Prio [" + depth + "] -- interrupted");
break;
}
Game sim = game.copy();
sim.setSimulation(true);
if (// for MorphAbility, etc
!(action instanceof StaticAbility) && sim.getPlayer(currentPlayer.getId()).activateAbility((ActivatedAbility) action.copy(), sim)) {
sim.applyEffects();
if (checkForRepeatedAction(sim, node, action, currentPlayer.getId())) {
logger.debug("Sim Prio [" + depth + "] -- repeated action: " + action);
continue;
}
if (!sim.checkIfGameIsOver() && (action.isUsesStack() || action instanceof PassAbility)) {
// skip priority for opponents before stack resolve
UUID nextPlayerId = sim.getPlayerList().get();
do {
sim.getPlayer(nextPlayerId).pass(game);
nextPlayerId = sim.getPlayerList().getNext();
} while (!Objects.equals(nextPlayerId, this.getId()));
}
SimulationNode2 newNode = new SimulationNode2(node, sim, action, depth, currentPlayer.getId());
sim.checkStateAndTriggered();
int actionScore;
if (action instanceof PassAbility && sim.getStack().isEmpty()) {
// no more next actions, it's a final score
actionScore = GameStateEvaluator2.evaluate(this.getId(), sim).getTotalScore();
} else {
// resolve current action and calc all next actions to find best score (return max possible score)
actionScore = addActions(newNode, depth - 1, alpha, beta);
}
logger.debug("Sim Prio " + BLANKS.substring(0, 2 + (maxDepth - depth) * 3) + '[' + depth + "]#" + actionNumber + " <" + actionScore + "> - (" + action + ") ");
// * node.score - rewrites to store max score (e.g. contains only final data)
if (logger.isInfoEnabled() && depth >= maxDepth) {
// show calculated actions and score
// example: Sim Prio [6] #1 <605> (Play Swamp)
int currentActionScore = GameStateEvaluator2.evaluate(this.getId(), newNode.getGame()).getTotalScore();
int diffCurrentAction = currentActionScore - startedScore;
int diffNextActions = actionScore - startedScore - diffCurrentAction;
logger.info(String.format("Sim Prio [%d] #%d <diff %s, %s> (%s)", depth, actionNumber, printDiffScore(diffCurrentAction), printDiffScore(diffNextActions), action + (action.isModal() ? " Mode = " + action.getModes().getMode().toString() : "") + listTargets(game, action.getTargets(), " (targeting %s)", "") + (logger.isTraceEnabled() ? " #" + newNode.hashCode() : "")));
// collect childs info (next actions chain)
SimulationNode2 logNode = newNode;
while (logNode.getChildren() != null && !logNode.getChildren().isEmpty()) {
logNode = logNode.getChildren().get(0);
if (logNode.getAbilities() != null && !logNode.getAbilities().isEmpty()) {
int logCurrentScore = GameStateEvaluator2.evaluate(this.getId(), logNode.getGame()).getTotalScore();
int logPrevScore = GameStateEvaluator2.evaluate(this.getId(), logNode.getParent().getGame()).getTotalScore();
logger.info(String.format("Sim Prio [%d] -> next action: [%d]%s <diff %s, %s>", depth, logNode.getDepth(), logNode.getAbilities().toString(), printDiffScore(logCurrentScore - logPrevScore), printDiffScore(actionScore - logCurrentScore)));
}
}
}
if (currentPlayer.getId().equals(playerId)) {
if (actionScore > bestValSubNodes) {
bestValSubNodes = actionScore;
}
if (depth == maxDepth && action instanceof PassAbility) {
// passivity penalty
actionScore = actionScore - PASSIVITY_PENALTY;
}
if (actionScore > alpha || (depth == maxDepth && actionScore == alpha && RandomUtil.nextBoolean())) {
// Adding random for equal value to get change sometimes
alpha = actionScore;
bestNode = newNode;
bestNode.setScore(actionScore);
if (!newNode.getChildren().isEmpty()) {
bestNode.setCombat(newNode.getChildren().get(0).getCombat());
}
if (depth == maxDepth) {
GameStateEvaluator2.PlayerEvaluateScore score = GameStateEvaluator2.evaluate(this.getId(), bestNode.game);
String scoreInfo = " [" + score.getPlayerInfoShort() + "-" + score.getOpponentInfoShort() + "]";
String abilitiesInfo = bestNode.getAbilities().stream().map(a -> a.toString() + listTargets(game, a.getTargets(), " (targeting %s)", "")).collect(Collectors.joining("; "));
logger.info("Sim Prio [" + depth + "] >> BEST action chain found <" + bestNode.getScore() + scoreInfo + "> " + abilitiesInfo);
node.children.clear();
node.children.add(bestNode);
node.setScore(bestNode.getScore());
}
}
// no need to check other actions
if (actionScore == GameStateEvaluator2.WIN_GAME_SCORE) {
logger.debug("Sim Prio -- win - break");
break;
}
} else {
if (actionScore < beta) {
beta = actionScore;
bestNode = newNode;
bestNode.setScore(actionScore);
if (!newNode.getChildren().isEmpty()) {
bestNode.setCombat(newNode.getChildren().get(0).getCombat());
}
}
// no need to check other actions
if (actionScore == GameStateEvaluator2.LOSE_GAME_SCORE) {
logger.debug("Sim Prio -- lose - break");
break;
}
}
if (alpha >= beta) {
break;
}
if (SimulationNode2.nodeCount > maxNodes) {
logger.debug("Sim Prio -- reached end-state");
break;
}
}
}
if (depth == maxDepth) {
logger.info("Sim Prio [" + depth + "] -- End for Max Depth -- Nodes calculated: " + SimulationNode2.nodeCount);
}
if (bestNode != null) {
node.children.clear();
node.children.add(bestNode);
node.setScore(bestNode.getScore());
if (logger.isTraceEnabled() && !bestNode.getAbilities().toString().equals("[Pass]")) {
logger.trace(new StringBuilder("Sim Prio [").append(depth).append("] -- Set after (depth=").append(depth).append(") <").append(bestNode.getScore()).append("> ").append(bestNode.getAbilities().toString()).toString());
}
}
if (currentPlayer.getId().equals(playerId)) {
return bestValSubNodes;
} else {
return beta;
}
}
Aggregations