Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bugfix] Break deadlock for one must/can't be blocked pair. #13182

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Mage/src/main/java/mage/game/combat/Combat.java
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,7 @@ public boolean checkBlockRequirementsAfter(Player player, Player controller, Gam
// 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>> mustBeBlockedByAtLeastX = new HashMap<>();
Map<UUID, Integer> minNumberOfBlockersMap = new HashMap<>();
Map<UUID, Integer> minPossibleBlockersMap = new HashMap<>();

// check mustBlock requirements of creatures from opponents of attacking player
for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED, player.getId(), game)) {
Expand All @@ -876,6 +877,12 @@ public boolean checkBlockRequirementsAfter(Player player, Player controller, Gam
CombatGroup toBeBlockedGroup = findGroup(toBeBlockedCreature);
if (toBeBlockedGroup != null && toBeBlockedGroup.getDefendingPlayerId().equals(creature.getControllerId())) {
minNumberOfBlockersMap.put(toBeBlockedCreature, effect.getMinNumberOfBlockers());
Permanent toBeBlockedCreaturePermanent = game.getPermanent(toBeBlockedCreature);
if (toBeBlockedCreaturePermanent != null) {
minPossibleBlockersMap.put(toBeBlockedCreature, toBeBlockedCreaturePermanent.getMinBlockedBy());
} else {
minPossibleBlockersMap.put(toBeBlockedCreature, 1);
}
Set<UUID> potentialBlockers;
if (mustBeBlockedByAtLeastX.containsKey(toBeBlockedCreature)) {
potentialBlockers = mustBeBlockedByAtLeastX.get(toBeBlockedCreature);
Expand Down Expand Up @@ -973,6 +980,12 @@ public boolean checkBlockRequirementsAfter(Player player, Player controller, Gam
CombatGroup toBeBlockedGroup = findGroup(toBeBlockedCreature);
if (toBeBlockedGroup != null && toBeBlockedGroup.getDefendingPlayerId().equals(creature.getControllerId())) {
minNumberOfBlockersMap.put(toBeBlockedCreature, effect.getMinNumberOfBlockers());
Permanent toBeBlockedCreaturePermanent = game.getPermanent(toBeBlockedCreature);
if (toBeBlockedCreaturePermanent != null) {
minPossibleBlockersMap.put(toBeBlockedCreature, toBeBlockedCreaturePermanent.getMinBlockedBy());
} else {
minPossibleBlockersMap.put(toBeBlockedCreature, 1);
}
Set<UUID> potentialBlockers;
if (mustBeBlockedByAtLeastX.containsKey(toBeBlockedCreature)) {
potentialBlockers = mustBeBlockedByAtLeastX.get(toBeBlockedCreature);
Expand Down Expand Up @@ -1059,6 +1072,13 @@ public boolean checkBlockRequirementsAfter(Player player, Player controller, Gam
for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastX.keySet()) {
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
if (combatGroup.getAttackers().contains(toBeBlockedCreatureId)) {
// Neyith of the Dire Hunt: If the target creature has menace, two creatures must block it if able.
// (2020-06-23)
// This is a basic check to avoid deadlocking on one blocker plus 'must be blocked if able' with menace;
// a full solution is more complicated but this prevents the most common case.
if (mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId).size() < minPossibleBlockersMap.get(toBeBlockedCreatureId)) {
continue;
}
boolean requirementFulfilled = false;
// Check whether an applicable creature is blocking.
for (UUID blockerId : combatGroup.getBlockers()) {
Expand Down
Loading