forked from External/mage
Attackers sorting, Blocking groups - rule 509.3. Fixed Issue 195.
This commit is contained in:
parent
4627c92d41
commit
d33bf20bf0
11 changed files with 209 additions and 43 deletions
|
|
@ -892,6 +892,12 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
|
|||
return min;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID chooseAttackerOrder(List<Permanent> attackers, Game game) {
|
||||
//TODO: improve this
|
||||
return attackers.iterator().next().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID chooseBlockerOrder(List<Permanent> blockers, Game game) {
|
||||
//TODO: improve this
|
||||
|
|
|
|||
|
|
@ -469,6 +469,22 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID chooseAttackerOrder(List<Permanent> attackers, Game game) {
|
||||
while (!abort) {
|
||||
game.fireSelectTargetEvent(playerId, "Pick attacker", attackers, true);
|
||||
waitForResponse();
|
||||
if (response.getUUID() != null) {
|
||||
for (Permanent perm: attackers) {
|
||||
if (perm.getId().equals(response.getUUID()))
|
||||
return perm.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UUID chooseBlockerOrder(List<Permanent> blockers, Game game) {
|
||||
while (!abort) {
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -28,12 +28,6 @@
|
|||
|
||||
package mage.game.combat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.Constants.Outcome;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
|
|
@ -48,9 +42,11 @@ import mage.players.PlayerList;
|
|||
import mage.target.common.TargetDefender;
|
||||
import mage.util.Copyable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class Combat implements Serializable, Copyable<Combat> {
|
||||
|
|
@ -60,32 +56,41 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
private static FilterCreatureForCombat filterBlockers = new FilterCreatureForCombat();
|
||||
|
||||
protected List<CombatGroup> groups = new ArrayList<CombatGroup>();
|
||||
protected Map<UUID, CombatGroup> blockingGroups = new HashMap<UUID, CombatGroup>();
|
||||
protected Set<UUID> defenders = new HashSet<UUID>();
|
||||
protected UUID attackerId; //the player that is attacking
|
||||
|
||||
public Combat() {}
|
||||
public Combat() {
|
||||
}
|
||||
|
||||
public Combat(final Combat combat) {
|
||||
this.attackerId = combat.attackerId;
|
||||
for (CombatGroup group: combat.groups) {
|
||||
for (CombatGroup group : combat.groups) {
|
||||
groups.add(group.copy());
|
||||
}
|
||||
for (UUID defenderId: combat.defenders) {
|
||||
for (UUID defenderId : combat.defenders) {
|
||||
defenders.add(defenderId);
|
||||
}
|
||||
for (Map.Entry<UUID, CombatGroup> group : combat.blockingGroups.entrySet()) {
|
||||
blockingGroups.put(group.getKey(), group.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public List<CombatGroup> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
public Collection<CombatGroup> getBlockingGroups() {
|
||||
return blockingGroups.values();
|
||||
}
|
||||
|
||||
public Set<UUID> getDefenders() {
|
||||
return defenders;
|
||||
}
|
||||
|
||||
public List<UUID> getAttackers() {
|
||||
List<UUID> attackers = new ArrayList<UUID>();
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
attackers.addAll(group.attackers);
|
||||
}
|
||||
return attackers;
|
||||
|
|
@ -93,7 +98,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
public List<UUID> getBlockers() {
|
||||
List<UUID> blockers = new ArrayList<UUID>();
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
blockers.addAll(group.blockers);
|
||||
}
|
||||
return blockers;
|
||||
|
|
@ -101,6 +106,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
public void clear() {
|
||||
groups.clear();
|
||||
blockingGroups.clear();
|
||||
defenders.clear();
|
||||
attackerId = null;
|
||||
}
|
||||
|
|
@ -108,7 +114,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
public int getValue(Game game) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(attackerId).append(defenders);
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
sb.append(group.getValue(game));
|
||||
}
|
||||
return sb.toString().hashCode();
|
||||
|
|
@ -131,23 +137,21 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
protected void checkAttackRequirements(Player player, Game game) {
|
||||
//20101001 - 508.1d
|
||||
for (Permanent creature: game.getBattlefield().getAllActivePermanents(filterAttackers, player.getId())) {
|
||||
for (RequirementEffect effect: game.getContinuousEffects().getApplicableRequirementEffects(creature, game)) {
|
||||
for (Permanent creature : game.getBattlefield().getAllActivePermanents(filterAttackers, player.getId())) {
|
||||
for (RequirementEffect effect : game.getContinuousEffects().getApplicableRequirementEffects(creature, game)) {
|
||||
if (effect.mustAttack(game)) {
|
||||
UUID defenderId = effect.mustAttackDefender(game.getContinuousEffects().getAbility(effect.getId()), game);
|
||||
if (defenderId == null) {
|
||||
if (defenders.size() == 1) {
|
||||
player.declareAttacker(creature.getId(), defenders.iterator().next(), game);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TargetDefender target = new TargetDefender(defenders, creature.getId());
|
||||
target.setRequired(true);
|
||||
if (player.chooseTarget(Outcome.Damage, target, null, game)) {
|
||||
player.declareAttacker(creature.getId(), target.getFirstTarget(), game);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
player.declareAttacker(creature.getId(), defenderId, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -160,7 +164,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
Player player = game.getPlayer(attackerId);
|
||||
//20101001 - 509.1c
|
||||
checkBlockRequirements(player, game);
|
||||
for (UUID defenderId: getPlayerDefenders(game)) {
|
||||
for (UUID defenderId : getPlayerDefenders(game)) {
|
||||
game.getPlayer(defenderId).selectBlockers(game);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, defenderId, defenderId));
|
||||
}
|
||||
|
|
@ -170,9 +174,9 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
protected void checkBlockRequirements(Player player, Game game) {
|
||||
//20101001 - 509.1c
|
||||
//TODO: handle case where more than one attacker must be blocked
|
||||
for (Permanent creature: game.getBattlefield().getActivePermanents(filterBlockers, player.getId(), game)) {
|
||||
for (Permanent creature : game.getBattlefield().getActivePermanents(filterBlockers, player.getId(), game)) {
|
||||
if (game.getOpponents(attackerId).contains(creature.getControllerId())) {
|
||||
for (RequirementEffect effect: game.getContinuousEffects().getApplicableRequirementEffects(creature, game)) {
|
||||
for (RequirementEffect effect : game.getContinuousEffects().getApplicableRequirementEffects(creature, game)) {
|
||||
if (effect.mustBlock(game)) {
|
||||
UUID attackId = effect.mustBlockAttacker(game.getContinuousEffects().getAbility(effect.getId()), game);
|
||||
Player defender = game.getPlayer(creature.getControllerId());
|
||||
|
|
@ -210,7 +214,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
break;
|
||||
case MULITPLE:
|
||||
for (UUID opponentId: game.getOpponents(attackerId)) {
|
||||
for (UUID opponentId : game.getOpponents(attackerId)) {
|
||||
addDefender(opponentId, game);
|
||||
}
|
||||
break;
|
||||
|
|
@ -219,7 +223,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
private void addDefender(UUID defenderId, Game game) {
|
||||
defenders.add(defenderId);
|
||||
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filterPlaneswalker, defenderId)) {
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterPlaneswalker, defenderId)) {
|
||||
defenders.add(permanent.getId());
|
||||
}
|
||||
}
|
||||
|
|
@ -238,12 +242,36 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
groups.add(newGroup);
|
||||
}
|
||||
|
||||
// add blocking group for creatures that block more than one creature
|
||||
public void addBlockingGroup(UUID blockerId, UUID attackerId, UUID playerId, Game game) {
|
||||
Permanent blocker = game.getPermanent(blockerId);
|
||||
if (blockerId != null && blocker != null && blocker.getBlocking() > 1) {
|
||||
if (!blockingGroups.containsKey(blockerId)) {
|
||||
CombatGroup newGroup = new CombatGroup(playerId, playerId != null);
|
||||
newGroup.blockers.add(blockerId);
|
||||
// add all blocked attackers
|
||||
for (CombatGroup group : groups) {
|
||||
if (group.getBlockers().contains(blockerId)) {
|
||||
// take into account banding
|
||||
for (UUID attacker : group.attackers) {
|
||||
newGroup.attackers.add(attacker);
|
||||
}
|
||||
}
|
||||
}
|
||||
blockingGroups.put(blockerId, newGroup);
|
||||
} else {
|
||||
//TODO: handle banding
|
||||
blockingGroups.get(blockerId).attackers.add(attackerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeFromCombat(UUID creatureId, Game game) {
|
||||
Permanent creature = game.getPermanent(creatureId);
|
||||
if (creature != null) {
|
||||
creature.setAttacking(false);
|
||||
creature.setBlocking(0);
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
group.remove(creatureId);
|
||||
}
|
||||
}
|
||||
|
|
@ -251,15 +279,15 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
public void endCombat(Game game) {
|
||||
Permanent creature;
|
||||
for (CombatGroup group: groups) {
|
||||
for (UUID attacker: group.attackers) {
|
||||
for (CombatGroup group : groups) {
|
||||
for (UUID attacker : group.attackers) {
|
||||
creature = game.getPermanent(attacker);
|
||||
if (creature != null) {
|
||||
creature.setAttacking(false);
|
||||
creature.setBlocking(0);
|
||||
}
|
||||
}
|
||||
for (UUID blocker: group.blockers) {
|
||||
for (UUID blocker : group.blockers) {
|
||||
creature = game.getPermanent(blocker);
|
||||
if (creature != null) {
|
||||
creature.setAttacking(false);
|
||||
|
|
@ -271,7 +299,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
|
||||
public boolean hasFirstOrDoubleStrike(Game game) {
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
if (group.hasFirstOrDoubleStrike(game))
|
||||
return true;
|
||||
}
|
||||
|
|
@ -279,7 +307,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
|
||||
public CombatGroup findGroup(UUID attackerId) {
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
if (group.getAttackers().contains(attackerId))
|
||||
return group;
|
||||
}
|
||||
|
|
@ -288,7 +316,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
public int totalUnblockedDamage(Game game) {
|
||||
int total = 0;
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
if (group.getBlockers().isEmpty()) {
|
||||
total += group.totalAttackerDamage(game);
|
||||
}
|
||||
|
|
@ -307,7 +335,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
|
||||
public boolean isAttacked(UUID defenderId, Game game) {
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
if (group.getDefenderId().equals(defenderId))
|
||||
return true;
|
||||
if (group.defenderIsPlaneswalker) {
|
||||
|
|
@ -321,7 +349,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
public UUID getDefendingPlayer(UUID attackerId) {
|
||||
UUID defenderId = null;
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
if (group.getAttackers().contains(attackerId)) {
|
||||
defenderId = group.getDefenderId();
|
||||
break;
|
||||
|
|
@ -332,13 +360,12 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
private Set<UUID> getPlayerDefenders(Game game) {
|
||||
Set<UUID> playerDefenders = new HashSet<UUID>();
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
if (group.defenderIsPlaneswalker) {
|
||||
Permanent permanent = game.getPermanent(group.getDefenderId());
|
||||
if (permanent != null)
|
||||
playerDefenders.add(permanent.getControllerId());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
playerDefenders.add(group.getDefenderId());
|
||||
}
|
||||
}
|
||||
|
|
@ -346,9 +373,15 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
|
||||
public void damageAssignmentOrder(Game game) {
|
||||
for (CombatGroup group: groups) {
|
||||
for (CombatGroup group : groups) {
|
||||
group.pickBlockerOrder(attackerId, game);
|
||||
}
|
||||
for (Map.Entry<UUID, CombatGroup> blockingGroup : blockingGroups.entrySet()) {
|
||||
Permanent blocker = game.getPermanent(blockingGroup.getKey());
|
||||
if (blocker != null) {
|
||||
blockingGroup.getValue().pickAttackerOrder(blocker.getControllerId(), game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
protected List<UUID> attackers = new ArrayList<UUID>();
|
||||
protected List<UUID> blockers = new ArrayList<UUID>();
|
||||
protected List<UUID> blockerOrder = new ArrayList<UUID>();
|
||||
protected List<UUID> attackerOrder = new ArrayList<UUID>();
|
||||
protected boolean blocked;
|
||||
protected UUID defenderId;
|
||||
protected boolean defenderIsPlaneswalker;
|
||||
|
|
@ -74,6 +75,9 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
for (UUID orderId: group.blockerOrder) {
|
||||
this.blockerOrder.add(orderId);
|
||||
}
|
||||
for (UUID orderId: group.attackerOrder) {
|
||||
this.attackerOrder.add(orderId);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getValue(Game game) {
|
||||
|
|
@ -148,6 +152,17 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
}
|
||||
}
|
||||
|
||||
public void assignDamageToAttackers(boolean first, Game game) {
|
||||
if (blockers.size() > 0 && (!first || hasFirstOrDoubleStrike(game))) {
|
||||
if (attackers.size() == 1) {
|
||||
singleAttackerDamage(first, game);
|
||||
}
|
||||
else {
|
||||
multiAttackerDamage(first, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canDamage(Permanent perm, boolean first) {
|
||||
return (first && hasFirstOrDoubleStrike(perm)) || (!first && !hasFirstStrike(perm));
|
||||
}
|
||||
|
|
@ -168,7 +183,6 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
Permanent blocker = game.getPermanent(blockers.get(0));
|
||||
Permanent attacker = game.getPermanent(attackers.get(0));
|
||||
if (blocker != null && attacker != null) {
|
||||
int blockerDamage = blocker.getPower().getValue();
|
||||
if (canDamage(attacker, first)) {
|
||||
int damage = attacker.getPower().getValue();
|
||||
if (hasTrample(attacker)) {
|
||||
|
|
@ -190,7 +204,10 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
}
|
||||
}
|
||||
if (canDamage(blocker, first)) {
|
||||
attacker.damage(blockerDamage, blocker.getId(), game, true, true);
|
||||
if (blocker.getBlocking() == 1) { // blocking several creatures handled separately
|
||||
int blockerDamage = blocker.getPower().getValue();
|
||||
attacker.damage(blockerDamage, blocker.getId(), game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -198,10 +215,11 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
private void multiBlockerDamage(boolean first, Game game) {
|
||||
//TODO: handle banding
|
||||
Permanent attacker = game.getPermanent(attackers.get(0));
|
||||
if (attacker == null) {
|
||||
return;
|
||||
}
|
||||
Player player = game.getPlayer(attacker.getControllerId());
|
||||
int damage = attacker.getPower().getValue();
|
||||
if (attacker == null)
|
||||
return;
|
||||
if (canDamage(attacker, first)) {
|
||||
Map<UUID, Integer> assigned = new HashMap<UUID, Integer>();
|
||||
for (UUID blockerId: blockerOrder) {
|
||||
|
|
@ -230,7 +248,9 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
for (UUID blockerId: blockerOrder) {
|
||||
Permanent blocker = game.getPermanent(blockerId);
|
||||
if (canDamage(blocker, first)) {
|
||||
attacker.damage(blocker.getPower().getValue(), blocker.getId(), game, true, true);
|
||||
if (blocker.getBlocking() == 1) { // blocking several creatures handled separately
|
||||
attacker.damage(blocker.getPower().getValue(), blocker.getId(), game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Issue#73
|
||||
|
|
@ -249,6 +269,69 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Damages attacking creatures by a creature that blocked several ones
|
||||
* Damages only attackers as blocker was damage in {@link #singleBlockerDamage}.
|
||||
*
|
||||
* Handles abilities like "{this} an block any number of creatures.".
|
||||
*
|
||||
* @param first
|
||||
* @param game
|
||||
*/
|
||||
private void singleAttackerDamage(boolean first, Game game) {
|
||||
Permanent blocker = game.getPermanent(blockers.get(0));
|
||||
Permanent attacker = game.getPermanent(attackers.get(0));
|
||||
if (blocker != null && attacker != null) {
|
||||
if (canDamage(blocker, first)) {
|
||||
int damage = blocker.getPower().getValue();
|
||||
attacker.damage(damage, blocker.getId(), game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Damages attacking creatures by a creature that blocked several ones
|
||||
* Damages only attackers as blocker was damage in either {@link #singleBlockerDamage} or {@link #multiBlockerDamage}.
|
||||
*
|
||||
* Handles abilities like "{this} an block any number of creatures.".
|
||||
*
|
||||
* @param first
|
||||
* @param game
|
||||
*/
|
||||
private void multiAttackerDamage(boolean first, Game game) {
|
||||
Permanent blocker = game.getPermanent(blockers.get(0));
|
||||
Player player = game.getPlayer(blocker.getControllerId());
|
||||
if (blocker == null) {
|
||||
return;
|
||||
}
|
||||
int damage = blocker.getPower().getValue();
|
||||
|
||||
if (canDamage(blocker, first)) {
|
||||
Map<UUID, Integer> assigned = new HashMap<UUID, Integer>();
|
||||
for (UUID attackerId: attackerOrder) {
|
||||
Permanent attacker = game.getPermanent(attackerId);
|
||||
int lethalDamage;
|
||||
if (blocker.getAbilities().containsKey(DeathtouchAbility.getInstance().getId()))
|
||||
lethalDamage = 1;
|
||||
else
|
||||
lethalDamage = attacker.getToughness().getValue() - attacker.getDamage();
|
||||
if (lethalDamage >= damage) {
|
||||
assigned.put(attackerId, damage);
|
||||
damage = 0;
|
||||
break;
|
||||
}
|
||||
int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + attacker.getName(), game);
|
||||
assigned.put(attackerId, damageAssigned);
|
||||
damage -= damageAssigned;
|
||||
}
|
||||
|
||||
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
|
||||
Permanent attacker = game.getPermanent(entry.getKey());
|
||||
attacker.damage(entry.getValue(), blocker.getId(), game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void defenderDamage(Permanent attacker, int amount, Game game) {
|
||||
if (this.defenderIsPlaneswalker) {
|
||||
Permanent defender = game.getPermanent(defenderId);
|
||||
|
|
@ -277,7 +360,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
}
|
||||
}
|
||||
Permanent blocker = game.getPermanent(blockerId);
|
||||
if (blockerId != null) {
|
||||
if (blockerId != null && blocker != null) {
|
||||
blocker.setBlocking(blocker.getBlocking() + 1);
|
||||
blockers.add(blockerId);
|
||||
blockerOrder.add(blockerId);
|
||||
|
|
@ -310,6 +393,29 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void pickAttackerOrder(UUID playerId, Game game) {
|
||||
if (attackers.isEmpty())
|
||||
return;
|
||||
Player player = game.getPlayer(playerId);
|
||||
List<UUID> attackerList = new ArrayList<UUID>(attackers);
|
||||
attackerOrder.clear();
|
||||
while (true) {
|
||||
if (attackerList.size() == 1) {
|
||||
attackerOrder.add(attackerList.get(0));
|
||||
break;
|
||||
}
|
||||
else {
|
||||
List<Permanent> attackerPerms = new ArrayList<Permanent>();
|
||||
for (UUID attackerId: attackerList) {
|
||||
attackerPerms.add(game.getPermanent(attackerId));
|
||||
}
|
||||
UUID attackerId = player.chooseAttackerOrder(attackerPerms, game);
|
||||
attackerOrder.add(attackerId);
|
||||
attackerList.remove(attackerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int totalAttackerDamage(Game game) {
|
||||
int total = 0;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ public class CombatDamageStep extends Step<CombatDamageStep> {
|
|||
for (CombatGroup group: game.getCombat().getGroups()) {
|
||||
group.assignDamage(first, game);
|
||||
}
|
||||
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
|
||||
group.assignDamageToAttackers(first, game);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getFirst() {
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
public abstract Mode chooseMode(Modes modes, Ability source, Game game);
|
||||
public abstract void selectAttackers(Game game);
|
||||
public abstract void selectBlockers(Game game);
|
||||
public abstract UUID chooseAttackerOrder(List<Permanent> attacker, Game game);
|
||||
public abstract UUID chooseBlockerOrder(List<Permanent> blockers, Game game);
|
||||
public abstract void assignDamage(int damage, List<UUID> targets, String singleTargetName, UUID sourceId, Game game);
|
||||
public abstract int getAmount(int min, int max, String message, Game game);
|
||||
|
|
|
|||
|
|
@ -849,6 +849,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
|
|||
CombatGroup group = game.getCombat().findGroup(attackerId);
|
||||
if (blocker != null && group != null && group.canBlock(blocker, game)) {
|
||||
group.addBlocker(blockerId, playerId, game);
|
||||
game.getCombat().addBlockingGroup(blockerId, attackerId, playerId, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue