diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index 65dad77162..8fecec7c63 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -1,3 +1,4 @@ + package mage.game.combat; import java.io.Serializable; @@ -694,7 +695,7 @@ public class Combat implements Serializable, Copyable { Set opponents = game.getOpponents(attackingPlayerId); //20101001 - 509.1c // map with attackers (UUID) that must be blocked by at least one blocker and a set of all creatures that can block it and don't block yet - Map> mustBeBlockedByAtLeastOne = new HashMap<>(); + Map> mustBeBlockedByAtLeastX = new HashMap<>(); Map minNumberOfBlockersMap = new HashMap<>(); // check mustBlock requirements of creatures from opponents of attacking player @@ -707,19 +708,22 @@ public class Combat implements Serializable, Copyable { // get all requirement effects that apply to the creature (e.g. is able to block attacker) for (Map.Entry> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, false, game).entrySet()) { RequirementEffect effect = entry.getKey(); - // get possible mustBeBlockedByAtLeastOne blocker + // get possible mustBeBlockedByAtLeastX blocker for (Ability ability : entry.getValue()) { UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game); if (toBeBlockedCreature != null) { - minNumberOfBlockersMap.put(toBeBlockedCreature, effect.getMinNumberOfBlockers()); - Set potentialBlockers; - if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) { - potentialBlockers = mustBeBlockedByAtLeastOne.get(toBeBlockedCreature); - } else { - potentialBlockers = new HashSet<>(); - mustBeBlockedByAtLeastOne.put(toBeBlockedCreature, potentialBlockers); + CombatGroup toBeBlockedGroup = findGroup(toBeBlockedCreature); + if (toBeBlockedGroup != null && toBeBlockedGroup.getDefendingPlayerId().equals(creature.getControllerId())) { + minNumberOfBlockersMap.put(toBeBlockedCreature, effect.getMinNumberOfBlockers()); + Set potentialBlockers; + if (mustBeBlockedByAtLeastX.containsKey(toBeBlockedCreature)) { + potentialBlockers = mustBeBlockedByAtLeastX.get(toBeBlockedCreature); + } else { + potentialBlockers = new HashSet<>(); + mustBeBlockedByAtLeastX.put(toBeBlockedCreature, potentialBlockers); + } + potentialBlockers.add(creature.getId()); } - potentialBlockers.add(creature.getId()); } } // check the mustBlockAllAttackers requirement for creatures already blocking (Blaze of Glory) ------------------------------- @@ -802,19 +806,22 @@ public class Combat implements Serializable, Copyable { // get all requirement effects that apply to the creature for (Map.Entry> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, false, game).entrySet()) { RequirementEffect effect = entry.getKey(); - // get possible mustBeBlockedByAtLeastOne blocker + // get possible mustBeBlockedByAtLeastX blocker for (Ability ability : entry.getValue()) { UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game); if (toBeBlockedCreature != null) { - minNumberOfBlockersMap.put(toBeBlockedCreature, effect.getMinNumberOfBlockers()); - Set potentialBlockers; - if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) { - potentialBlockers = mustBeBlockedByAtLeastOne.get(toBeBlockedCreature); - } else { - potentialBlockers = new HashSet<>(); - mustBeBlockedByAtLeastOne.put(toBeBlockedCreature, potentialBlockers); + CombatGroup toBeBlockedGroup = findGroup(toBeBlockedCreature); + if (toBeBlockedGroup != null && toBeBlockedGroup.getDefendingPlayerId().equals(creature.getControllerId())) { + minNumberOfBlockersMap.put(toBeBlockedCreature, effect.getMinNumberOfBlockers()); + Set potentialBlockers; + if (mustBeBlockedByAtLeastX.containsKey(toBeBlockedCreature)) { + potentialBlockers = mustBeBlockedByAtLeastX.get(toBeBlockedCreature); + } else { + potentialBlockers = new HashSet<>(); + mustBeBlockedByAtLeastX.put(toBeBlockedCreature, potentialBlockers); + } + potentialBlockers.add(creature.getId()); } - potentialBlockers.add(creature.getId()); } } @@ -889,19 +896,19 @@ public class Combat implements Serializable, Copyable { } - // check if for attacking creatures with mustBeBlockedByAtLeastOne requirements are fulfilled - for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastOne.keySet()) { + // check if for attacking creatures with mustBeBlockedByAtLeastX requirements are fulfilled + for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastX.keySet()) { for (CombatGroup combatGroup : game.getCombat().getGroups()) { if (combatGroup.getAttackers().contains(toBeBlockedCreatureId)) { boolean requirementFulfilled = false; // Check whether an applicable creature is blocking. for (UUID blockerId : combatGroup.getBlockers()) { - if (mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId).contains(blockerId)) { + if (mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId).contains(blockerId)) { requirementFulfilled = true; break; } } - requirementFulfilled &= (combatGroup.getBlockers().size() >= Math.min(minNumberOfBlockersMap.get(toBeBlockedCreatureId), mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId).size())); + requirementFulfilled &= (combatGroup.getBlockers().size() >= Math.min(minNumberOfBlockersMap.get(toBeBlockedCreatureId), mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId).size())); if (!requirementFulfilled) { // creature is not blocked but has possible blockers if (controller.isHuman()) { @@ -909,12 +916,12 @@ public class Combat implements Serializable, Copyable { if (toBeBlockedCreature != null) { // check if all possible blocker block other creatures they are forced to block // read through all possible blockers - for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) { + for (UUID possibleBlockerId : mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId)) { if (combatGroup.getBlockers().contains(possibleBlockerId)) { continue; } String blockRequiredMessage = isCreatureDoingARequiredBlock( - possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastOne, game); + possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastX, game); if (blockRequiredMessage != null) { // message means not required removeBlocker(possibleBlockerId, game); game.informPlayer(controller, blockRequiredMessage + " Existing block removed. It's a requirement to block " + toBeBlockedCreature.getIdName() + '.'); @@ -925,9 +932,9 @@ public class Combat implements Serializable, Copyable { } else { // take the first potential blocker from the set to block for the AI - for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) { + for (UUID possibleBlockerId : mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId)) { String blockRequiredMessage = isCreatureDoingARequiredBlock( - possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastOne, game); + possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastX, game); if (blockRequiredMessage != null) { // set the block Permanent possibleBlocker = game.getPermanent(possibleBlockerId); @@ -1008,8 +1015,8 @@ public class Combat implements Serializable, Copyable { } else // check if the blocker blocks a attacker that must be blocked at least by one and is the only blocker, this block is also valid { if (combatGroup.getBlockers().size() == 1) { - if (mustBeBlockedByAtLeastOne.containsKey(forcingAttackerId)) { - if (mustBeBlockedByAtLeastOne.get(forcingAttackerId).contains(creatureForcedToBlock.getId())) { + if (mustBeBlockedByAtLeastX.containsKey(forcingAttackerId)) { + if (mustBeBlockedByAtLeastX.get(forcingAttackerId).contains(creatureForcedToBlock.getId())) { blockIsValid = true; break CombatGroups; } @@ -1042,11 +1049,11 @@ public class Combat implements Serializable, Copyable { * * @param possibleBlockerId * @param toBeBlockedCreatureId - * @param mustBeBlockedByAtLeastOne + * @param mustBeBlockedByAtLeastX * @param game * @return null block is required otherwise message with reason why not */ - protected String isCreatureDoingARequiredBlock(UUID possibleBlockerId, UUID toBeBlockedCreatureId, Map> mustBeBlockedByAtLeastOne, Game game) { + protected String isCreatureDoingARequiredBlock(UUID possibleBlockerId, UUID toBeBlockedCreatureId, Map> mustBeBlockedByAtLeastX, Game game) { Permanent possibleBlocker = game.getPermanent(possibleBlockerId); if (possibleBlocker != null) { if (possibleBlocker.getBlocking() == 0) { @@ -1055,16 +1062,16 @@ public class Combat implements Serializable, Copyable { Set forcingAttackers = creatureMustBlockAttackers.get(possibleBlockerId); if (forcingAttackers == null) { // no other creature forces the blocker to block -> it's available - // check now, if it already blocks a creature that mustBeBlockedByAtLeastOne + // check now, if it already blocks a creature that mustBeBlockedByAtLeastX if (possibleBlocker.getBlocking() > 0) { CombatGroup combatGroupOfPossibleBlocker = findGroupOfBlocker(possibleBlockerId); if (combatGroupOfPossibleBlocker != null) { for (UUID blockedAttackerId : combatGroupOfPossibleBlocker.getAttackers()) { - if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) { + if (mustBeBlockedByAtLeastX.containsKey(blockedAttackerId)) { // blocks a creature that has to be blocked by at least one if (combatGroupOfPossibleBlocker.getBlockers().size() == 1) { - Set blockedSet = mustBeBlockedByAtLeastOne.get(blockedAttackerId); - Set toBlockSet = mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId); + Set blockedSet = mustBeBlockedByAtLeastX.get(blockedAttackerId); + Set toBlockSet = mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId); if (toBlockSet == null) { // This should never happen.
 return null;