* Fixed that attacker has not always to assign all damage to multiple blockers. Improved AI behaviour of assigning damage to multiple blockers. Tries to kill blocker if possible now.

This commit is contained in:
LevelX2 2014-08-18 00:46:45 +02:00
parent 06caf2179d
commit d02f272bca
7 changed files with 82 additions and 13 deletions

View file

@ -1388,5 +1388,55 @@ public class ComputerPlayer6 extends ComputerPlayer implements Player {
super.cleanUpOnMatchEnd(); super.cleanUpOnMatchEnd();
} }
@Override
public UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup, List<UUID> blockerOrder, Game game) {
if (combatGroup.getAttackers().size() == 1) {
Permanent attacker = game.getPermanent(combatGroup.getAttackers().get(0));
boolean attackerDeathtouch = attacker.getAbilities().containsKey(DeathtouchAbility.getInstance().getId());
// boolean attackerFirstStrike = attacker.getAbilities().containsKey(FirstStrikeAbility.getInstance().getId());
List<Permanent> blockerAlreadySet = getAlreadyBlockingPermanents(blockerOrder, game);
int powerAlreadyNeeded = getPowerAlreadyNeeded(blockerAlreadySet, attackerDeathtouch);
int powerLeftToKill = attacker.getPower().getValue() - powerAlreadyNeeded;
// no possible damage left, order doesn't matter
if (powerLeftToKill <= 0) {
return blockers.iterator().next().getId();
}
for (Permanent blocker: blockers) {
if (attackerDeathtouch || powerLeftToKill >= blocker.getToughness().getValue()) {
if (!blocker.getAbilities().containsKey(IndestructibleAbility.getInstance().getId())) {
return blocker.getId();
}
}
}
// Can't kill a blocker so it doesn't matter
return blockers.iterator().next().getId();
} else { // multiple attackers (like banding)
//TODO: improve this
return blockers.iterator().next().getId();
}
}
private List<Permanent> getAlreadyBlockingPermanents(List<UUID> blockerOrder, Game game) {
List<Permanent> blockerAlreadySet = new ArrayList<>();
for (UUID uuid :blockerOrder) {
Permanent permanent = game.getPermanent(uuid);
if (permanent != null) {
blockerAlreadySet.add(permanent);
}
}
return blockerAlreadySet;
}
private int getPowerAlreadyNeeded(List<Permanent> blockerAlreadySet, boolean attackerDeathtouch) {
int toughnessAlreadyNeeded = 0;
if (attackerDeathtouch) {
return blockerAlreadySet.size();
}
for (Permanent creature : blockerAlreadySet) {
toughnessAlreadyNeeded += creature.getToughness().getValue();
}
return toughnessAlreadyNeeded;
}
} }

View file

@ -82,6 +82,7 @@ import java.util.*;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map.Entry; import java.util.Map.Entry;
import mage.abilities.costs.VariableCost; import mage.abilities.costs.VariableCost;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.FlashAbility;
import mage.cards.repository.ExpansionInfo; import mage.cards.repository.ExpansionInfo;
import mage.cards.repository.ExpansionRepository; import mage.cards.repository.ExpansionRepository;
@ -1388,7 +1389,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
@Override @Override
public UUID chooseBlockerOrder(List<Permanent> blockers, Game game) { public UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup, List<UUID> blockerOrder, Game game) {
//TODO: improve this //TODO: improve this
return blockers.iterator().next().getId(); return blockers.iterator().next().getId();
} }

View file

@ -353,8 +353,9 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
@Override @Override
public boolean choosePile(Outcome outcome, String message, List<? extends Card> pile1, List<? extends Card> pile2, Game game) { public boolean choosePile(Outcome outcome, String message, List<? extends Card> pile1, List<? extends Card> pile2, Game game) {
if (this.isHuman()) if (this.isHuman()) {
return rnd.nextBoolean(); return rnd.nextBoolean();
}
return super.choosePile(outcome, message, pile1, pile2, game); return super.choosePile(outcome, message, pile1, pile2, game);
} }
@ -408,16 +409,18 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
@Override @Override
public UUID chooseAttackerOrder(List<Permanent> attackers, Game game) { public UUID chooseAttackerOrder(List<Permanent> attackers, Game game) {
if (this.isHuman()) if (this.isHuman()) {
return attackers.get(rnd.nextInt(attackers.size())).getId(); return attackers.get(rnd.nextInt(attackers.size())).getId();
}
return super.chooseAttackerOrder(attackers, game); return super.chooseAttackerOrder(attackers, game);
} }
@Override @Override
public UUID chooseBlockerOrder(List<Permanent> blockers, Game game) { public UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup, List<UUID> blockerOrder, Game game) {
if (this.isHuman()) if (this.isHuman()) {
return blockers.get(rnd.nextInt(blockers.size())).getId(); return blockers.get(rnd.nextInt(blockers.size())).getId();
return super.chooseBlockerOrder(blockers, game); }
return super.chooseBlockerOrder(blockers, combatGroup, blockerOrder, game);
} }
@Override @Override
@ -450,14 +453,16 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
targets.remove(targetId); targets.remove(targetId);
} }
} }
else else {
super.assignDamage(damage, targets, singleTargetName, sourceId, game); super.assignDamage(damage, targets, singleTargetName, sourceId, game);
}
} }
@Override @Override
public int getAmount(int min, int max, String message, Game game) { public int getAmount(int min, int max, String message, Game game) {
if (this.isHuman()) if (this.isHuman()) {
return rnd.nextInt(max - min) + min; return rnd.nextInt(max - min) + min;
}
return super.getAmount(min, max, message, game); return super.getAmount(min, max, message, game);
} }

View file

@ -764,7 +764,7 @@ public class HumanPlayer extends PlayerImpl {
@Override @Override
public UUID chooseBlockerOrder(List<Permanent> blockers, Game game) { public UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup, List<UUID> blockerOrder, Game game) {
updateGameStatePriority("chooseBlockerOrder", game); updateGameStatePriority("chooseBlockerOrder", game);
while (!abort) { while (!abort) {
game.fireSelectTargetEvent(playerId, "Pick blocker", blockers, true); game.fireSelectTargetEvent(playerId, "Pick blocker", blockers, true);

View file

@ -384,7 +384,7 @@ public class RandomPlayer extends ComputerPlayer {
} }
@Override @Override
public UUID chooseBlockerOrder(List<Permanent> blockers, Game game) { public UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup, List<UUID> blockerOrder, Game game) {
return blockers.get(rnd.nextInt(blockers.size())).getId(); return blockers.get(rnd.nextInt(blockers.size())).getId();
} }

View file

@ -304,12 +304,16 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
} }
if (damage > 0 && hasTrample(attacker)) { if (damage > 0 && hasTrample(attacker)) {
defenderDamage(attacker, damage, game); defenderDamage(attacker, damage, game);
} else {
// Assign the damge left to first blocker
int alreadyAssigned = assigned.get(blockerOrder.get(0));
assigned.replace(blockerOrder.get(0), damage + alreadyAssigned);
} }
} }
for (UUID blockerId: blockerOrder) { for (UUID blockerId: blockerOrder) {
Integer power = blockerPower.get(blockerId); Integer power = blockerPower.get(blockerId);
if (power != null) { if (power != null) {
attacker.markDamage(power.intValue(), blockerId, game, true, true); attacker.markDamage(power, blockerId, game, true, true);
} }
} }
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) { for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
@ -448,7 +452,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
for (UUID blockerId: blockerList) { for (UUID blockerId: blockerList) {
blockerPerms.add(game.getPermanent(blockerId)); blockerPerms.add(game.getPermanent(blockerId));
} }
UUID blockerId = player.chooseBlockerOrder(blockerPerms, game); UUID blockerId = player.chooseBlockerOrder(blockerPerms, this, blockerOrder, game);
blockerOrder.add(blockerId); blockerOrder.add(blockerId);
blockerList.remove(blockerId); blockerList.remove(blockerId);
} }

View file

@ -59,6 +59,7 @@ import mage.util.Copyable;
import java.io.Serializable; import java.io.Serializable;
import java.util.*; import java.util.*;
import mage.game.combat.CombatGroup;
/** /**
* *
@ -312,7 +313,15 @@ public interface Player extends MageItem, Copyable<Player> {
void selectAttackers(Game game, UUID attackingPlayerId); void selectAttackers(Game game, UUID attackingPlayerId);
void selectBlockers(Game game, UUID defendingPlayerId); void selectBlockers(Game game, UUID defendingPlayerId);
UUID chooseAttackerOrder(List<Permanent> attacker, Game game); UUID chooseAttackerOrder(List<Permanent> attacker, Game game);
UUID chooseBlockerOrder(List<Permanent> blockers, Game game); /**
* Choose the order in which blockers get damage assigned to
* @param blockers list of blockers where to choose the next one from
* @param combatGroup the concerning combat group
* @param blockerOrder the already set order of blockers
* @param game
* @return blocker next to add to the blocker order
*/
UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup, List<UUID> blockerOrder, Game game);
void assignDamage(int damage, List<UUID> targets, String singleTargetName, UUID sourceId, Game game); void assignDamage(int damage, List<UUID> targets, String singleTargetName, UUID sourceId, Game game);
int getAmount(int min, int max, String message, Game game); int getAmount(int min, int max, String message, Game game);
void sideboard(Match match, Deck deck); void sideboard(Match match, Deck deck);