[mad ai] emulating block declaration. safe block. (in progress)

This commit is contained in:
magenoxx 2012-03-26 22:04:31 +04:00
parent 563687566c
commit deb6533bd8
12 changed files with 188 additions and 34 deletions

View file

@ -54,6 +54,7 @@ import mage.game.turn.*;
import mage.player.ai.ma.optimizers.TreeOptimizer;
import mage.player.ai.ma.optimizers.impl.EquipOptimizer;
import mage.player.ai.ma.optimizers.impl.LevelUpOptimizer;
import mage.player.ai.util.CombatInfo;
import mage.player.ai.util.CombatUtil;
import mage.players.Player;
import mage.target.Target;
@ -150,7 +151,6 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
if (game.getActivePlayerId().equals(playerId)) {
declareAttackers(game, playerId);
pass();
return true;
} else {
pass();
}
@ -159,7 +159,6 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
if (!game.getActivePlayerId().equals(playerId)) {
declareBlockers(game, playerId);
pass();
return true;
} else {
pass();
}
@ -770,22 +769,24 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
CombatUtil.sortByPower(attackers, false);
//TODO:
CombatInfo combatInfo = CombatUtil.blockWithGoodTrade(game, attackers, possibleBlockers);
Player player = game.getPlayer(this.playerId);
Map<Permanent, List<Permanent>> map = new HashMap<Permanent, List<Permanent>>();
for (Map.Entry<Permanent, List<Permanent>> entry : map.entrySet()) {
boolean blocked = false;
for (Map.Entry<Permanent, List<Permanent>> entry : combatInfo.getCombat().entrySet()) {
UUID attackerId = entry.getKey().getId();
List<Permanent> blockers = entry.getValue();
if (blockers != null) {
for (Permanent blocker : blockers) {
player.declareAttacker(attackerId, blocker.getId(), game);
player.declareBlocker(blocker.getId(), attackerId, game);
blocked = true;
}
}
}
if (blocked) {
game.getPlayers().resetPassed();
}
}
}
@ -887,7 +888,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
CombatUtil.handleExalted();
int aggressionRate = 5;
int aggressionRate = 0;
for (Permanent attacker : attackersList) {
if (aggressionRate == 5) {
attackingPlayer.declareAttacker(attacker.getId(), defenderId, game);

View file

@ -28,17 +28,23 @@
package mage.player.ai;
import mage.Constants;
import mage.Constants.AbilityType;
import mage.Constants.RangeOfInfluence;
import mage.Constants.Zone;
import mage.abilities.Ability;
import mage.filter.FilterAbility;
import mage.game.Game;
import mage.game.combat.Combat;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.turn.*;
import mage.players.Player;
import org.apache.log4j.Logger;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
/**
*
@ -275,14 +281,14 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
}
/*protected int simulateCombat(Game game, SimulationNode2 node, int depth, int alpha, int beta, boolean counter) {
protected int simulateCombat(Game game, SimulationNode2 node, int depth, int alpha, int beta, boolean counter) {
Integer val = null;
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
return GameStateEvaluator2.evaluate(playerId, game);
}
if (game.getTurn().getStepType() != PhaseStep.DECLARE_BLOCKERS) {
if (game.getTurn().getStepType() != Constants.PhaseStep.DECLARE_BLOCKERS) {
game.getTurn().setPhase(new CombatPhase());
if (game.getPhase().beginPhase(game, game.getActivePlayerId())) {
simulateStep(game, new BeginCombatStep());
@ -317,10 +323,10 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
if (logger.isDebugEnabled())
logger.debug("returning -- combat score: " + val + " depth:" + depth + " for player:" + game.getPlayer(node.getPlayerId()).getName());
return val;
}*/
}
/*protected int simulateAttackers(Game game, SimulationNode2 node, UUID attackerId, int depth, int alpha, int beta, boolean counter) {
protected int simulateAttackers(Game game, SimulationNode2 node, UUID attackerId, int depth, int alpha, int beta, boolean counter) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
@ -392,9 +398,9 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
if (logger.isDebugEnabled())
logger.debug("returning -- combat attacker score: " + val + " depth:" + depth + " for player:" + game.getPlayer(node.getPlayerId()).getName());
return val;
}*/
}
/*protected int simulateBlockers(Game game, SimulationNode2 node, UUID defenderId, int depth, int alpha, int beta, boolean counter) {
protected int simulateBlockers(Game game, SimulationNode2 node, UUID defenderId, int depth, int alpha, int beta, boolean counter) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
@ -471,7 +477,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
if (logger.isDebugEnabled())
logger.debug("returning -- combat blocker score: " + val + " depth:" + depth + " for player:" + game.getPlayer(node.getPlayerId()).getName());
return val;
}*/
}
/*protected int simulateCounterAttack(Game game, SimulationNode2 node, int depth, int alpha, int beta) {
if (Thread.interrupted()) {
@ -520,7 +526,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
}
}
/*protected void finishCombat(Game game) {
protected void finishCombat(Game game) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
logger.debug("interrupted");
@ -529,7 +535,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
simulateStep(game, new FirstCombatDamageStep());
simulateStep(game, new CombatDamageStep());
simulateStep(game, new EndOfCombatStep());
}*/
}
protected int simulatePostCombatMain(Game game, SimulationNode2 node, int depth, int alpha, int beta) {
if (Thread.interrupted()) {

View file

@ -1,7 +0,0 @@
package mage.player.ai.util;
/**
* @author noxx
*/
public class Combat {
}

View file

@ -0,0 +1,29 @@
package mage.player.ai.util;
import mage.game.permanent.Permanent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author noxx
*/
public class CombatInfo {
private Map<Permanent, List<Permanent>> combat = new HashMap<Permanent, List<Permanent>>();
public void addPair(Permanent attacker, Permanent blocker) {
List<Permanent> blockers = combat.get(attacker);
if (blockers == null) {
blockers = new ArrayList<Permanent>();
combat.put(attacker, blockers);
}
blockers.add(blocker);
}
public Map<Permanent, List<Permanent>> getCombat() {
return combat;
}
}

View file

@ -4,13 +4,16 @@ import mage.abilities.keyword.DoubleStrikeAbility;
import mage.abilities.keyword.InfectAbility;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.combat.Combat;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.turn.CombatDamageStep;
import mage.game.turn.EndOfCombatStep;
import mage.game.turn.FirstCombatDamageStep;
import mage.game.turn.Step;
import mage.players.Player;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.*;
/**
* Base helper methods for combat.
@ -21,6 +24,8 @@ public class CombatUtil {
private static final List<Permanent> emptyList = new ArrayList<Permanent>();
private static final transient org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(CombatUtil.class);
private CombatUtil() {
}
@ -90,6 +95,19 @@ public class CombatUtil {
});
}
public static Permanent getWorstCreature(List<Permanent> creatures) {
if (creatures.isEmpty()) {
return null;
}
Collections.sort(creatures, new Comparator<Permanent>() {
@Override
public int compare(Permanent o1, Permanent o2) {
return o2.getPower().getValue() - o1.getPower().getValue();
}
});
return creatures.get(0);
}
private static int sumDamage(List<Permanent> attackersThatWontBeBlocked, Player defender) {
int damage = 0;
for (Permanent attacker : attackersThatWontBeBlocked) {
@ -137,11 +155,84 @@ public class CombatUtil {
return canBlock;
}
public void blockWithGoodTrade(Game game, List<Permanent> attackers, List<Permanent> possibleBlockers) {
public static CombatInfo blockWithGoodTrade(Game game, List<Permanent> attackers, List<Permanent> blockers) {
UUID attackerId = game.getCombat().getAttackerId();
UUID defenderId = game.getCombat().getDefenders().iterator().next();
if (attackerId == null || defenderId == null) {
log.warn("Couldn't find attacker or defender: " + attackerId + " " + defenderId);
return new CombatInfo();
}
CombatInfo combatInfo = new CombatInfo();
for (Permanent attacker : attackers) {
//TODO: handle attackers with "can't be blocked except"
List<Permanent> blockers = getPossibleBlockers(game, attacker, possibleBlockers);
List<Permanent> possibleBlockers = getPossibleBlockers(game, attacker, blockers);
List<Permanent> survivedBlockers = getBlockersThatWillSurvive(game, attackerId, defenderId, attacker, possibleBlockers);
if (!survivedBlockers.isEmpty()) {
Permanent blocker = getWorstCreature(survivedBlockers);
combatInfo.addPair(attacker, blocker);
blockers.remove(blocker);
}
if (blockers.isEmpty()) {
break;
}
}
return combatInfo;
}
private static List<Permanent> getBlockersThatWillSurvive(Game game, UUID attackerId, UUID defenderId, Permanent attacker, List<Permanent> possibleBlockers) {
List<Permanent> blockers = new ArrayList<Permanent>();
for (Permanent blocker : possibleBlockers) {
SurviveInfo info = willItSurvive(game, attackerId, defenderId, attacker, blocker);
if (info.isAttackerDied() && !info.isBlockerDied()) {
blockers.add(blocker);
}
}
return blockers;
}
private static SurviveInfo willItSurvive(Game game, UUID attackingPlayerId, UUID defendingPlayerId, Permanent attacker, Permanent blocker) {
Game sim = game.copy();
Combat combat = sim.getCombat();
combat.setAttacker(attackingPlayerId);
combat.setDefenders(sim);
sim.getPlayer(defendingPlayerId).declareBlocker(blocker.getId(), attacker.getId(), sim);
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, defendingPlayerId, defendingPlayerId));
sim.checkStateAndTriggered();
while (!sim.getStack().isEmpty()) {
sim.getStack().resolve(sim);
sim.applyEffects();
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId()));
simulateStep(sim, new FirstCombatDamageStep());
simulateStep(sim, new CombatDamageStep());
simulateStep(sim, new EndOfCombatStep());
sim.checkStateAndTriggered();
while (!sim.getStack().isEmpty()) {
sim.getStack().resolve(sim);
sim.applyEffects();
}
return new SurviveInfo(!sim.getBattlefield().containsPermanent(attacker.getId()), !sim.getBattlefield().containsPermanent(blocker.getId()));
}
protected static void simulateStep(Game game, Step step) {
game.getPhase().setStep(step);
if (!step.skipStep(game, game.getActivePlayerId())) {
step.beginStep(game, game.getActivePlayerId());
game.checkStateAndTriggered();
while (!game.getStack().isEmpty()) {
game.getStack().resolve(game);
game.applyEffects();
}
step.endStep(game, game.getActivePlayerId());
}
}
}

View file

@ -0,0 +1,30 @@
package mage.player.ai.util;
/**
* @author noxx
*/
public class SurviveInfo {
private boolean attackerDied;
private boolean blockerDied;
public SurviveInfo(boolean attackerDied, boolean blockerDied) {
this.attackerDied = attackerDied;
this.blockerDied = blockerDied;
}
public boolean isAttackerDied() {
return attackerDied;
}
public void setAttackerDied(boolean attackerDied) {
this.attackerDied = attackerDied;
}
public boolean isBlockerDied() {
return blockerDied;
}
public void setBlockerDied(boolean blockerDied) {
this.blockerDied = blockerDied;
}
}

View file

@ -438,8 +438,12 @@ public class Combat implements Serializable, Copyable<Combat> {
if (creature != null)
creature.setBlocking(0);
}
@Override
public UUID getAttackerId() {
return attackerId;
}
@Override
public Combat copy() {
return new Combat(this);
}