Fixed Gorm requiring a blocker from another player (fixes #5025)

This commit is contained in:
L_J 2018-06-10 12:40:51 +00:00 committed by GitHub
parent cf97a82c33
commit 45243378cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,3 +1,4 @@
package mage.game.combat;
import java.io.Serializable;
@ -694,7 +695,7 @@ public class Combat implements Serializable, Copyable<Combat> {
Set<UUID> 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<UUID, Set<UUID>> mustBeBlockedByAtLeastOne = new HashMap<>();
Map<UUID, Set<UUID>> mustBeBlockedByAtLeastX = new HashMap<>();
Map<UUID, Integer> minNumberOfBlockersMap = new HashMap<>();
// check mustBlock requirements of creatures from opponents of attacking player
@ -707,19 +708,22 @@ public class Combat implements Serializable, Copyable<Combat> {
// get all requirement effects that apply to the creature (e.g. is able to block attacker)
for (Map.Entry<RequirementEffect, Set<Ability>> 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<UUID> 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<UUID> 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<Combat> {
// get all requirement effects that apply to the creature
for (Map.Entry<RequirementEffect, Set<Ability>> 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<UUID> 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<UUID> 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<Combat> {
}
// 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<Combat> {
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<Combat> {
} 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<Combat> {
} 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<Combat> {
*
* @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<UUID, Set<UUID>> mustBeBlockedByAtLeastOne, Game game) {
protected String isCreatureDoingARequiredBlock(UUID possibleBlockerId, UUID toBeBlockedCreatureId, Map<UUID, Set<UUID>> 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<Combat> {
Set<UUID> 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<UUID> blockedSet = mustBeBlockedByAtLeastOne.get(blockedAttackerId);
Set<UUID> toBlockSet = mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId);
Set<UUID> blockedSet = mustBeBlockedByAtLeastX.get(blockedAttackerId);
Set<UUID> toBlockSet = mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId);
if (toBlockSet == null) {
// This should never happen.
return null;