Program: 158553
Project: 158553
Buggy source:
/** 
 * 509.1c The defending player checks each creature he or she controls to see whether it's affected by any requirements (effects that say a creature must block, or that it must block if some condition is met). If the number of requirements that are being obeyed is fewer than the maximum possible number of requirements that could be obeyed without disobeying any restrictions, the declaration of blockers is illegal. If a creature can't block unless a player pays a cost, that player is not required to pay that cost, even if blocking with that creature would increase the number of requirements being obeyed. Example: A player controls one creature that "blocks if able" and another creature with no abilities. An effect states "Creatures can't be blocked except by two or more creatures." Having only the first creature block violates the restriction. Having neither creature block fulfills the restriction but not the requirement. Having both creatures block the same attacking creature fulfills both the restriction and the requirement, so that's the only option.
 * @param player
 * @param controller
 * @param game
 * @return
 */
public boolean checkBlockRequirementsAfter(Player player,Player controller,Game game){
  Set<UUID> opponents=game.getOpponents(attackerId);
  Map<UUID,Set<UUID>> mustBeBlockedByAtLeastOne=new HashMap<>();
  for (  Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(),player.getId(),game)) {
    if (opponents.contains(creature.getControllerId())) {
      if (creature.getBlocking() > 0) {
        for (        Map.Entry<RequirementEffect,HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature,game).entrySet()) {
          RequirementEffect effect=entry.getKey();
          for (          Ability ability : entry.getValue()) {
            UUID toBeBlockedCreature=effect.mustBlockAttackerIfElseUnblocked(ability,game);
            if (toBeBlockedCreature != null) {
              Set<UUID> potentialBlockers;
              if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) {
                potentialBlockers=mustBeBlockedByAtLeastOne.get(toBeBlockedCreature);
              }
 else {
                potentialBlockers=new HashSet<>();
                mustBeBlockedByAtLeastOne.put(toBeBlockedCreature,potentialBlockers);
              }
              potentialBlockers.add(creature.getId());
            }
          }
        }
      }
      if (creature.getBlocking() == 0) {
        for (        Map.Entry<RequirementEffect,HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature,game).entrySet()) {
          RequirementEffect effect=entry.getKey();
          for (          Ability ability : entry.getValue()) {
            UUID toBeBlockedCreature=effect.mustBlockAttackerIfElseUnblocked(ability,game);
            if (toBeBlockedCreature != null) {
              Set<UUID> potentialBlockers;
              if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) {
                potentialBlockers=mustBeBlockedByAtLeastOne.get(toBeBlockedCreature);
              }
 else {
                potentialBlockers=new HashSet<>();
                mustBeBlockedByAtLeastOne.put(toBeBlockedCreature,potentialBlockers);
              }
              potentialBlockers.add(creature.getId());
            }
          }
          if (effect.mustBlockAny(game)) {
            boolean mayBlock=false;
            for (            UUID attackingCreatureId : getAttackers()) {
              if (creature.canBlock(attackingCreatureId,game)) {
                Permanent attackingCreature=game.getPermanent(attackingCreatureId);
                if (attackingCreature != null) {
                  if (attackingCreature.getMaxBlockedBy() != 0) {
                    int alreadyBlockingCreatures=0;
                    for (                    CombatGroup group : getGroups()) {
                      if (group.getAttackers().contains(attackingCreatureId)) {
                        alreadyBlockingCreatures=group.getBlockers().size();
                        break;
                      }
                    }
                    if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) {
                      continue;
                    }
                  }
                  if (attackingCreature.getMinBlockedBy() > 1) {
                  }
 else {
                    mayBlock=true;
                    break;
                  }
                }
              }
            }
            if (mayBlock) {
              if (controller.isHuman()) {
                if (!game.isSimulation()) {
                  game.informPlayer(controller,"String_Node_Str" + creature.getIdName());
                }
              }
 else {
                Player defender=game.getPlayer(creature.getControllerId());
                if (defender != null) {
                  for (                  UUID attackingCreatureId : getAttackers()) {
                    if (creature.canBlock(attackingCreatureId,game)) {
                      defender.declareBlocker(defender.getId(),creature.getId(),attackingCreatureId,game);
                      break;
                    }
                  }
                }
              }
              return false;
            }
          }
        }
      }
    }
  }
  for (  UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastOne.keySet()) {
    for (    CombatGroup combatGroup : game.getCombat().getGroups()) {
      if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(toBeBlockedCreatureId)) {
        if (controller.isHuman()) {
          Permanent toBeBlockedCreature=game.getPermanent(toBeBlockedCreatureId);
          if (toBeBlockedCreature != null) {
            for (            UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
              String blockRequiredMessage=isCreatureDoingARequiredBlock(possibleBlockerId,mustBeBlockedByAtLeastOne,game);
              if (blockRequiredMessage != null) {
                removeBlocker(possibleBlockerId,game);
                game.informPlayer(controller,blockRequiredMessage + "String_Node_Str" + toBeBlockedCreature.getIdName()+ "String_Node_Str");
                return false;
              }
            }
          }
        }
 else {
          for (          UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
            String blockRequiredMessage=isCreatureDoingARequiredBlock(possibleBlockerId,mustBeBlockedByAtLeastOne,game);
            if (blockRequiredMessage != null) {
              Permanent possibleBlocker=game.getPermanent(possibleBlockerId);
              Player defender=game.getPlayer(possibleBlocker.getControllerId());
              if (defender != null) {
                if (possibleBlocker.getBlocking() > 0) {
                  removeBlocker(possibleBlockerId,game);
                }
                defender.declareBlocker(defender.getId(),possibleBlockerId,toBeBlockedCreatureId,game);
              }
              break;
            }
          }
        }
      }
    }
  }
  StringBuilder sb=new StringBuilder();
  for (  Map.Entry<UUID,Set<UUID>> entry : creatureMustBlockAttackers.entrySet()) {
    boolean blockIsValid;
    Permanent creatureForcedToBlock=game.getPermanent(entry.getKey());
    if (creatureForcedToBlock == null) {
      break;
    }
    if (!creatureForcedToBlock.getControllerId().equals(player.getId())) {
      continue;
    }
    if (creatureForcedToBlock.getBlocking() == 0) {
      blockIsValid=false;
    }
 else {
      blockIsValid=false;
      CombatGroups:       for (      CombatGroup combatGroup : game.getCombat().getGroups()) {
        if (combatGroup.getBlockers().contains(creatureForcedToBlock.getId())) {
          for (          UUID forcingAttackerId : combatGroup.getAttackers()) {
            if (entry.getValue().contains(forcingAttackerId)) {
              blockIsValid=true;
              break CombatGroups;
            }
 else             if (combatGroup.getBlockers().size() == 1) {
              if (mustBeBlockedByAtLeastOne.containsKey(forcingAttackerId)) {
                if (mustBeBlockedByAtLeastOne.get(forcingAttackerId).contains(creatureForcedToBlock.getId())) {
                  blockIsValid=true;
                  break CombatGroups;
                }
              }
            }
          }
        }
      }
    }
    if (!blockIsValid) {
      sb.append("String_Node_Str").append(creatureForcedToBlock.getIdName());
    }
  }
  if (sb.length() > 0) {
    if (!game.isSimulation()) {
      sb.insert(0,"String_Node_Str");
      sb.append("String_Node_Str");
      game.informPlayer(controller,sb.toString());
    }
    return false;
  }
  return true;
}

Fixed version (ground truth):
/** 
 * 509.1c The defending player checks each creature he or she controls to see whether it's affected by any requirements (effects that say a creature must block, or that it must block if some condition is met). If the number of requirements that are being obeyed is fewer than the maximum possible number of requirements that could be obeyed without disobeying any restrictions, the declaration of blockers is illegal. If a creature can't block unless a player pays a cost, that player is not required to pay that cost, even if blocking with that creature would increase the number of requirements being obeyed. Example: A player controls one creature that "blocks if able" and another creature with no abilities. An effect states "Creatures can't be blocked except by two or more creatures." Having only the first creature block violates the restriction. Having neither creature block fulfills the restriction but not the requirement. Having both creatures block the same attacking creature fulfills both the restriction and the requirement, so that's the only option.
 * @param player
 * @param controller
 * @param game
 * @return
 */
public boolean checkBlockRequirementsAfter(Player player,Player controller,Game game){
  Set<UUID> opponents=game.getOpponents(attackerId);
  Map<UUID,Set<UUID>> mustBeBlockedByAtLeastOne=new HashMap<>();
  for (  Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(),player.getId(),game)) {
    if (opponents.contains(creature.getControllerId())) {
      if (creature.getBlocking() > 0) {
        for (        Map.Entry<RequirementEffect,HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature,game).entrySet()) {
          RequirementEffect effect=entry.getKey();
          for (          Ability ability : entry.getValue()) {
            UUID toBeBlockedCreature=effect.mustBlockAttackerIfElseUnblocked(ability,game);
            if (toBeBlockedCreature != null) {
              Set<UUID> potentialBlockers;
              if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) {
                potentialBlockers=mustBeBlockedByAtLeastOne.get(toBeBlockedCreature);
              }
 else {
                potentialBlockers=new HashSet<>();
                mustBeBlockedByAtLeastOne.put(toBeBlockedCreature,potentialBlockers);
              }
              potentialBlockers.add(creature.getId());
            }
          }
        }
      }
      if (creature.getBlocking() == 0) {
        for (        Map.Entry<RequirementEffect,HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature,game).entrySet()) {
          RequirementEffect effect=entry.getKey();
          for (          Ability ability : entry.getValue()) {
            UUID toBeBlockedCreature=effect.mustBlockAttackerIfElseUnblocked(ability,game);
            if (toBeBlockedCreature != null) {
              Set<UUID> potentialBlockers;
              if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) {
                potentialBlockers=mustBeBlockedByAtLeastOne.get(toBeBlockedCreature);
              }
 else {
                potentialBlockers=new HashSet<>();
                mustBeBlockedByAtLeastOne.put(toBeBlockedCreature,potentialBlockers);
              }
              potentialBlockers.add(creature.getId());
            }
          }
          if (effect.mustBlockAny(game)) {
            boolean mayBlock=false;
            for (            UUID attackingCreatureId : getAttackers()) {
              if (creature.canBlock(attackingCreatureId,game)) {
                Permanent attackingCreature=game.getPermanent(attackingCreatureId);
                if (attackingCreature != null) {
                  if (attackingCreature.getMaxBlockedBy() != 0) {
                    int alreadyBlockingCreatures=0;
                    for (                    CombatGroup group : getGroups()) {
                      if (group.getAttackers().contains(attackingCreatureId)) {
                        alreadyBlockingCreatures=group.getBlockers().size();
                        break;
                      }
                    }
                    if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) {
                      continue;
                    }
                  }
                  if (attackingCreature.getMinBlockedBy() > 1) {
                  }
 else {
                    mayBlock=true;
                    break;
                  }
                }
              }
            }
            if (mayBlock) {
              if (controller.isHuman()) {
                if (!game.isSimulation()) {
                  game.informPlayer(controller,"String_Node_Str" + creature.getIdName());
                }
              }
 else {
                Player defender=game.getPlayer(creature.getControllerId());
                if (defender != null) {
                  for (                  UUID attackingCreatureId : getAttackers()) {
                    if (creature.canBlock(attackingCreatureId,game)) {
                      defender.declareBlocker(defender.getId(),creature.getId(),attackingCreatureId,game);
                      break;
                    }
                  }
                }
              }
              return false;
            }
          }
        }
      }
    }
  }
  for (  UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastOne.keySet()) {
    for (    CombatGroup combatGroup : game.getCombat().getGroups()) {
      if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(toBeBlockedCreatureId)) {
        if (controller.isHuman()) {
          Permanent toBeBlockedCreature=game.getPermanent(toBeBlockedCreatureId);
          if (toBeBlockedCreature != null) {
            for (            UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
              String blockRequiredMessage=isCreatureDoingARequiredBlock(possibleBlockerId,mustBeBlockedByAtLeastOne,game);
              if (blockRequiredMessage != null) {
                removeBlocker(possibleBlockerId,game);
                game.informPlayer(controller,blockRequiredMessage + "String_Node_Str" + toBeBlockedCreature.getIdName()+ "String_Node_Str");
                return false;
              }
            }
          }
        }
 else {
          for (          UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
            String blockRequiredMessage=isCreatureDoingARequiredBlock(possibleBlockerId,mustBeBlockedByAtLeastOne,game);
            if (blockRequiredMessage != null) {
              Permanent possibleBlocker=game.getPermanent(possibleBlockerId);
              Player defender=game.getPlayer(possibleBlocker.getControllerId());
              if (defender != null) {
                if (possibleBlocker.getBlocking() > 0) {
                  removeBlocker(possibleBlockerId,game);
                }
                defender.declareBlocker(defender.getId(),possibleBlockerId,toBeBlockedCreatureId,game);
              }
              break;
            }
          }
        }
      }
    }
  }
  StringBuilder sb=new StringBuilder();
  for (  Map.Entry<UUID,Set<UUID>> entry : creatureMustBlockAttackers.entrySet()) {
    boolean blockIsValid;
    Permanent creatureForcedToBlock=game.getPermanent(entry.getKey());
    if (creatureForcedToBlock == null) {
      break;
    }
    if (!creatureForcedToBlock.getControllerId().equals(player.getId())) {
      continue;
    }
    if (creatureForcedToBlock.getBlocking() == 0) {
      boolean validBlockPossible=false;
      for (      UUID possibleAttackerId : entry.getValue()) {
        CombatGroup attackersGroup=findGroup(possibleAttackerId);
        if (attackersGroup.getBlockers().contains(creatureForcedToBlock.getId())) {
          validBlockPossible=true;
          break;
        }
        Permanent attackingCreature=game.getPermanent(possibleAttackerId);
        if (attackingCreature.getMinBlockedBy() > 1) {
          if (attackersGroup.getBlockers().size() + 1 >= attackingCreature.getMinBlockedBy()) {
            validBlockPossible=true;
          }
        }
      }
      if (!validBlockPossible) {
        continue;
      }
    }
    if (creatureForcedToBlock.getBlocking() == 0) {
      blockIsValid=false;
    }
 else {
      blockIsValid=false;
      CombatGroups:       for (      CombatGroup combatGroup : game.getCombat().getGroups()) {
        if (combatGroup.getBlockers().contains(creatureForcedToBlock.getId())) {
          for (          UUID forcingAttackerId : combatGroup.getAttackers()) {
            if (entry.getValue().contains(forcingAttackerId)) {
              blockIsValid=true;
              break CombatGroups;
            }
 else             if (combatGroup.getBlockers().size() == 1) {
              if (mustBeBlockedByAtLeastOne.containsKey(forcingAttackerId)) {
                if (mustBeBlockedByAtLeastOne.get(forcingAttackerId).contains(creatureForcedToBlock.getId())) {
                  blockIsValid=true;
                  break CombatGroups;
                }
              }
            }
          }
        }
      }
    }
    if (!blockIsValid) {
      sb.append("String_Node_Str").append(creatureForcedToBlock.getIdName());
    }
  }
  if (sb.length() > 0) {
    if (!game.isSimulation()) {
      sb.insert(0,"String_Node_Str");
      sb.append("String_Node_Str");
      game.informPlayer(controller,sb.toString());
    }
    return false;
  }
  return true;
}