use of mage.abilities.ActivatedAbility in project mage by magefree.
the class MCTSNode method expand.
public void expand() {
MCTSPlayer player = (MCTSPlayer) game.getPlayer(playerId);
if (player.getNextAction() == null) {
logger.fatal("next action is null");
}
switch(player.getNextAction()) {
case PRIORITY:
// logger.info("Priority for player:" + player.getName() + " turn: " + game.getTurnNum() + " phase: " + game.getPhase().getType() + " step: " + game.getStep().getType());
List<Ability> abilities;
if (!USE_ACTION_CACHE)
abilities = player.getPlayableOptions(game);
else
abilities = getPlayables(player, fullStateValue, game);
for (Ability ability : abilities) {
Game sim = game.copy();
// logger.info("expand " + ability.toString());
MCTSPlayer simPlayer = (MCTSPlayer) sim.getPlayer(player.getId());
simPlayer.activateAbility((ActivatedAbility) ability, sim);
sim.resume();
children.add(new MCTSNode(this, sim, ability));
}
break;
case SELECT_ATTACKERS:
// logger.info("Select attackers:" + player.getName());
List<List<UUID>> attacks;
if (!USE_ACTION_CACHE)
attacks = player.getAttacks(game);
else
attacks = getAttacks(player, fullStateValue, game);
UUID defenderId = game.getOpponents(player.getId()).iterator().next();
for (List<UUID> attack : attacks) {
Game sim = game.copy();
MCTSPlayer simPlayer = (MCTSPlayer) sim.getPlayer(player.getId());
for (UUID attackerId : attack) {
simPlayer.declareAttacker(attackerId, defenderId, sim, false);
}
sim.resume();
children.add(new MCTSNode(this, sim, sim.getCombat()));
}
break;
case SELECT_BLOCKERS:
// logger.info("Select blockers:" + player.getName());
List<List<List<UUID>>> blocks;
if (!USE_ACTION_CACHE)
blocks = player.getBlocks(game);
else
blocks = getBlocks(player, fullStateValue, game);
for (List<List<UUID>> block : blocks) {
Game sim = game.copy();
MCTSPlayer simPlayer = (MCTSPlayer) sim.getPlayer(player.getId());
List<CombatGroup> groups = sim.getCombat().getGroups();
for (int i = 0; i < groups.size(); i++) {
if (i < block.size()) {
for (UUID blockerId : block.get(i)) {
simPlayer.declareBlocker(simPlayer.getId(), blockerId, groups.get(i).getAttackers().get(0), sim);
}
}
}
sim.resume();
children.add(new MCTSNode(this, sim, sim.getCombat()));
}
break;
}
game = null;
}
use of mage.abilities.ActivatedAbility in project mage by magefree.
the class SimulatedPlayer2 method filterAbilities.
// protected void simulateAction(Game game, SimulatedAction previousActions, Ability action) {
// List<Ability> actions = new ArrayList<Ability>(previousActions.getAbilities());
// actions.add(action);
// Game sim = game.copy();
// if (sim.getPlayer(playerId).activateAbility((ActivatedAbility) action.copy(), sim)) {
// sim.applyEffects();
// sim.getPlayers().resetPassed();
// allActions.add(new SimulatedAction(sim, actions));
// }
// }
/**
* if suggested abilities exist, return only those from playables
*
* @param game
* @param playables
* @param suggested
* @return
*/
protected List<ActivatedAbility> filterAbilities(Game game, List<ActivatedAbility> playables, List<String> suggested) {
if (playables.isEmpty()) {
return playables;
}
if (suggested == null || suggested.isEmpty()) {
return playables;
}
List<ActivatedAbility> filtered = new ArrayList<>();
for (ActivatedAbility ability : playables) {
Card card = game.getCard(ability.getSourceId());
if (card != null) {
for (String s : suggested) {
if (s.equals(card.getName())) {
logger.debug("matched: " + s);
forced = true;
filtered.add(ability);
}
}
}
}
if (!filtered.isEmpty()) {
return filtered;
}
return playables;
}
use of mage.abilities.ActivatedAbility in project mage by magefree.
the class SimulatedPlayer2 method filterOptions.
protected List<Ability> filterOptions(Game game, List<Ability> options, ActivatedAbility ability, List<String> suggested) {
if (options.isEmpty()) {
return options;
}
if (suggested == null || suggested.isEmpty()) {
return options;
}
List<Ability> filtered = new ArrayList<>();
for (Ability option : options) {
if (!option.getTargets().isEmpty() && option.getTargets().get(0).getMaxNumberOfTargets() == 1) {
Card card = game.getCard(ability.getSourceId());
if (card != null) {
for (String s : suggested) {
String[] groups = s.split(";");
logger.trace("s=" + s + ";groups=" + groups.length);
if (groups.length == 2) {
if (groups[0].equals(card.getName()) && groups[1].startsWith("name=")) {
// extract target and compare to suggested
String targetName = groups[1].split("=")[1];
Player player = game.getPlayer(option.getFirstTarget());
if (player != null && targetName.equals(player.getName())) {
System.out.println("matched(option): " + s);
filtered.add(option);
return filtered;
} else {
Card target = game.getCard(option.getFirstTarget());
if (target != null && target.getName().equals(targetName)) {
System.out.println("matched(option): " + s);
filtered.add(option);
return filtered;
}
System.out.println("not equal UUID for target, player=" + player);
}
}
}
}
}
}
}
// no option was found
return options;
}
use of mage.abilities.ActivatedAbility in project mage by magefree.
the class SimulatedPlayer method simulateVariableCosts.
// protected void simulateAction(Game game, SimulatedAction previousActions, Ability action) {
// List<Ability> actions = new ArrayList<Ability>(previousActions.getAbilities());
// actions.add(action);
// Game sim = game.copy();
// if (sim.getPlayer(playerId).activateAbility((ActivatedAbility) action.copy(), sim)) {
// sim.applyEffects();
// sim.getPlayers().resetPassed();
// allActions.add(new SimulatedAction(sim, actions));
// }
// }
// add a generic mana cost for each amount possible
protected void simulateVariableCosts(Ability ability, Game game) {
int numAvailable = getAvailableManaProducers(game).size() - ability.getManaCosts().manaValue();
int start = 0;
if (!(ability instanceof SpellAbility)) {
// only use x=0 on spell abilities
if (numAvailable == 0)
return;
else
start = 1;
}
for (int i = start; i < numAvailable; i++) {
Ability newAbility = ability.copy();
newAbility.getManaCostsToPay().add(new GenericManaCost(i));
allActions.add(newAbility);
}
}
use of mage.abilities.ActivatedAbility 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