Fixed undoing individual blocker declarations for multi-blockers

One more #4172 fix
This commit is contained in:
Zzooouhh 2018-01-10 19:44:48 +00:00 committed by GitHub
parent 56c615a66f
commit 8f9356533d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -678,6 +678,82 @@ public class Combat implements Serializable, Copyable<Combat> {
potentialBlockers.add(creature.getId());
}
}
// check the mustBlockAllAttackers requirement (Blaze of Glory) -------------------------------
if (effect.mustBlockAllAttackers(game)) {
Set<UUID> attackersToBlock = new HashSet<>();
// check that it can block at least one of the attackers
// and no restictions prevent this
boolean mayBlock = false;
for (UUID attackingCreatureId : getAttackers()) {
if (creature.canBlock(attackingCreatureId, game)) {
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
if (attackingCreature != null) {
// check if the attacker is already blocked by a max of blockers, so blocker can't block it also
if (attackingCreature.getMaxBlockedBy() != 0) { // 0 = no restriction about the number of possible blockers
int alreadyBlockingCreatures = 0;
for (CombatGroup group : getGroups()) {
if (group.getAttackers().contains(attackingCreatureId)) {
alreadyBlockingCreatures = group.getBlockers().size();
break;
}
}
if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) {
// Attacker can't be blocked by more blockers so check next attacker
continue;
}
}
// check restrictions of the creature to block that prevent it can be blocked
if (attackingCreature.getMinBlockedBy() > 1) {
// TODO: check if enough possible blockers are available, if true, mayBlock can be set to true
} else {
attackersToBlock.add(attackingCreatureId);
}
}
}
}
//~ // remove creatures already blocked by affected creature
//~ for (CombatGroup group : getBlockingGroups()) {
//~ if (group.getAttackers().contains(attackingCreatureId)) {
//~ for (UUID attackingCreatureId : group.getAttackers()) {
//~ CombatGroup attackersGroup = findGroup(attackingCreatureId);
//~ if (attackersGroup != null) {
//~ if (attackersGroup.getBlockers().contains(creature.getId())) {
//~ attackersToBlock.remove(attackingCreatureId);
//~ }
//~ }
//~ }
//~ }
//~ }
if (!attackersToBlock.isEmpty()) {
if (attackersToBlock.size() > creature.getBlocking()) {
mayBlock = true;
}
}
// if so inform human player or set block for AI player
if (mayBlock) {
if (controller.isHuman()) {
if (!game.isSimulation()) {
game.informPlayer(controller, "Creature should block all attackers it's able to this turn: " + creature.getIdName());
}
} else {
Player defender = game.getPlayer(creature.getControllerId());
if (defender != null) {
for (UUID attackingCreatureId : getAttackers()) {
if (creature.canBlock(attackingCreatureId, game)) {
// ???
if (attackersToBlock.contains(attackingCreatureId)) {
//~ defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
addBlockingGroup(creature.getId(), creature.getId(), defender.getId(), game);
}
}
}
}
}
return false;
}
}
}
}
@ -701,8 +777,8 @@ public class Combat implements Serializable, Copyable<Combat> {
}
}
// check the mustBlockAny requirement ----------------------------------------
if (effect.mustBlockAny(game)) {
// check the mustBlockAny requirement ---------------------------------------- (and mustBlockAllAttackers for AI)
if (effect.mustBlockAny(game) || effect.mustBlockAllAttackers(game)) {
// check that it can block at least one of the attackers
// and no restictions prevent this
boolean mayBlock = false;
@ -740,15 +816,28 @@ public class Combat implements Serializable, Copyable<Combat> {
if (mayBlock) {
if (controller.isHuman()) {
if (!game.isSimulation()) {
game.informPlayer(controller, "Creature should block this turn: " + creature.getIdName());
if (!effect.mustBlockAllAttackers(game)) {
game.informPlayer(controller, "Creature should block this turn: " + creature.getIdName());
} else {
game.informPlayer(controller, "Creature should block all attackers it's able to this turn: " + 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;
if (!effect.mustBlockAllAttackers(game)) {
defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
break;
} else {
// this might be buggy with additional restriction effects
if (creature.getBlocking() == 0) {
defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
} else {
addBlockingGroup(creature.getId(), creature.getId(), defender.getId(), game);
}
}
}
}
}
@ -756,6 +845,82 @@ public class Combat implements Serializable, Copyable<Combat> {
return false;
}
}
/*
// check the mustBlockAllAttackers requirement -------------------------------
if (effect.mustBlockAllAttackers(game)) {
Set<UUID> attackersToBlock = new HashSet<>();
// check that it can block at least one of the attackers
// and no restictions prevent this
boolean mayBlock = false;
for (UUID attackingCreatureId : getAttackers()) {
if (creature.canBlock(attackingCreatureId, game)) {
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
if (attackingCreature != null) {
// check if the attacker is already blocked by a max of blockers, so blocker can't block it also
if (attackingCreature.getMaxBlockedBy() != 0) { // 0 = no restriction about the number of possible blockers
int alreadyBlockingCreatures = 0;
for (CombatGroup group : getGroups()) {
if (group.getAttackers().contains(attackingCreatureId)) {
alreadyBlockingCreatures = group.getBlockers().size();
break;
}
}
if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) {
// Attacker can't be blocked by more blockers so check next attacker
continue;
}
}
// check restrictions of the creature to block that prevent it can be blocked
if (attackingCreature.getMinBlockedBy() > 1) {
// TODO: check if enough possible blockers are available, if true, mayBlock can be set to true
} else {
attackersToBlock.add(attackingCreatureId);
}
}
}
}
if (!attackersToBlock.isEmpty()) {
//~ CombatGroup group = findGroupOfBlocker(creature.getId());
//~ if (group == null) {
//~ mayBlock = true;
//~ } else {
//~ for (UUID attackingCreatureId : attackersToBlock) {
//~ if (!group.getAttackers().contains(attackingCreatureId)) {
//~ mayBlock = true;
//~ break;
//~ }
//~ }
game.informPlayers(attackersToBlock.size() + " and " + creature.getBlocking());
if (attackersToBlock.size() > creature.getBlocking()) {
mayBlock = true;
}
//~ }
}
// if so inform human player or set block for AI player
if (mayBlock) {
if (controller.isHuman()) {
if (!game.isSimulation()) {
game.informPlayer(controller, "Creature should block all attackers if able this turn: " + creature.getIdName());
}
} else {
Player defender = game.getPlayer(creature.getControllerId());
if (defender != null) {
for (UUID attackingCreatureId : getAttackers()) {
if (creature.canBlock(attackingCreatureId, game)) {
// ???
if (attackersToBlock.contains(attackingCreatureId)) {
defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
}
}
}
}
}
return false;
}
}
*/
}
}
@ -1180,6 +1345,7 @@ public class Combat implements Serializable, Copyable<Combat> {
//TODO: handle banding
blockingGroups.get(blockerId).attackers.add(attackerId);
}
// "blocker.setBlocking(blocker.getBlocking() + 1)" is handled by the attacking combat group
}
}
@ -1392,6 +1558,7 @@ public class Combat implements Serializable, Copyable<Combat> {
}
public void removeBlockerGromGroup(UUID blockerId, CombatGroup groupToUnblock, Game game) {
// Manual player action for undoing one declared blocker (used for multi-blocker creatures)
Permanent creature = game.getPermanent(blockerId);
if (creature != null) {
for (CombatGroup group : groups) {
@ -1404,7 +1571,26 @@ public class Combat implements Serializable, Copyable<Combat> {
if (creature.getBlocking() > 0) {
creature.setBlocking(creature.getBlocking() - 1);
} else {
throw new UnsupportedOperationException("Tryinging creature to unblock, but blocking number value of creature < 1");
throw new UnsupportedOperationException("Trying to unblock creature, but blocking number value of creature < 1");
}
boolean canRemove = false;
for (CombatGroup blockGroup : getBlockingGroups()) {
if (blockGroup.blockers.contains(blockerId)) {
for (UUID attackerId : group.getAttackers()) {
blockGroup.attackers.remove(attackerId);
blockGroup.attackerOrder.remove(attackerId);
}
if (creature.getBlocking() == 0) {
blockGroup.blockers.remove(blockerId);
blockGroup.attackerOrder.clear();
}
}
if (blockGroup.blockers.isEmpty()) {
canRemove = true;
}
}
if (canRemove) {
blockingGroups.remove(blockerId);
}
}
}
@ -1412,6 +1598,7 @@ public class Combat implements Serializable, Copyable<Combat> {
}
public void removeBlocker(UUID blockerId, Game game) {
// Manual player action for undoing all declared blockers (used for single-blocker creatures and multi-blockers exceeding blocking limit)
for (CombatGroup group : groups) {
if (group.blockers.contains(blockerId)) {
group.blockers.remove(blockerId);