mirror of
https://github.com/correl/mage.git
synced 2024-12-24 03:00:14 +00:00
[mad ai] emulating block declaration. safe block. (in progress)
This commit is contained in:
parent
563687566c
commit
deb6533bd8
12 changed files with 188 additions and 34 deletions
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
package mage.player.ai.util;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
*/
|
||||
public class Combat {
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue