mirror of
https://github.com/correl/mage.git
synced 2024-11-16 03:00:12 +00:00
Merge pull request #2325 from Dilnu/master
Fix the combat code to support Slayer's Cleaver
This commit is contained in:
commit
ea38924b5a
3 changed files with 58 additions and 38 deletions
|
@ -56,7 +56,6 @@ public class SlayersCleaver extends CardImpl {
|
||||||
|
|
||||||
// Equipped creature gets +3/+1 and must be blocked by an Eldrazi if able.
|
// Equipped creature gets +3/+1 and must be blocked by an Eldrazi if able.
|
||||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 1));
|
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 1));
|
||||||
// TODO: The effect does not work correctly yet, we need to do some chnanges to combat handling to fix this
|
|
||||||
ability.addEffect(new SlayersCleaverEffect());
|
ability.addEffect(new SlayersCleaverEffect());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
// Equip {4}
|
// Equip {4}
|
||||||
|
|
|
@ -231,12 +231,12 @@ public class BlockRequirementTest extends CardTestPlayerBase {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite"); // {1} 1/1
|
addCard(Zone.BATTLEFIELD, playerA, "Memnite"); // {1} 1/1
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Wretched Gryff"); // {7} Flying 3/4 - Eldrazi Hippogriff
|
addCard(Zone.BATTLEFIELD, playerB, "Dimensional Infiltrator"); // 2/1 - Eldrazi
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Hill Giant"); // {3}{R} 3/3
|
addCard(Zone.BATTLEFIELD, playerB, "Llanowar Elves"); // 1/1
|
||||||
|
|
||||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Memnite"); // pumps to 4/2
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Memnite"); // pumps to 4/2
|
||||||
attack(1, playerA, "Memnite"); // must be blocked by Wretched Gryff
|
attack(1, playerA, "Memnite"); // must be blocked by Dimensional Infiltrator
|
||||||
block(1, playerB, "Hill Giant", "Memnite"); // should not be allowed as only blocker
|
block(1, playerB, "Llanowar Elves", "Memnite"); // should not be allowed as only blocker
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.END_COMBAT);
|
setStopAt(1, PhaseStep.END_COMBAT);
|
||||||
execute();
|
execute();
|
||||||
|
@ -244,7 +244,7 @@ public class BlockRequirementTest extends CardTestPlayerBase {
|
||||||
assertPermanentCount(playerA, "Slayer's Cleaver", 1);
|
assertPermanentCount(playerA, "Slayer's Cleaver", 1);
|
||||||
assertLife(playerB, 20);
|
assertLife(playerB, 20);
|
||||||
assertGraveyardCount(playerA, "Memnite", 1);
|
assertGraveyardCount(playerA, "Memnite", 1);
|
||||||
assertGraveyardCount(playerB, "Wretched Gryff", 1);
|
assertGraveyardCount(playerB, "Dimensional Infiltrator", 1);
|
||||||
assertPermanentCount(playerB, "Hill Giant", 1);
|
assertGraveyardCount(playerB, "Llanowar Elves", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -749,7 +749,16 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
// check if for attacking creatures with mustBeBlockedByAtLeastOne requirements are fulfilled
|
// check if for attacking creatures with mustBeBlockedByAtLeastOne requirements are fulfilled
|
||||||
for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastOne.keySet()) {
|
for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastOne.keySet()) {
|
||||||
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
||||||
if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(toBeBlockedCreatureId)) {
|
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)) {
|
||||||
|
requirementFulfilled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!requirementFulfilled) {
|
||||||
// creature is not blocked but has possible blockers
|
// creature is not blocked but has possible blockers
|
||||||
if (controller.isHuman()) {
|
if (controller.isHuman()) {
|
||||||
Permanent toBeBlockedCreature = game.getPermanent(toBeBlockedCreatureId);
|
Permanent toBeBlockedCreature = game.getPermanent(toBeBlockedCreatureId);
|
||||||
|
@ -757,7 +766,8 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
// check if all possible blocker block other creatures they are forced to block
|
// check if all possible blocker block other creatures they are forced to block
|
||||||
// read through all possible blockers
|
// read through all possible blockers
|
||||||
for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
|
for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
|
||||||
String blockRequiredMessage = isCreatureDoingARequiredBlock(possibleBlockerId, mustBeBlockedByAtLeastOne, game);
|
String blockRequiredMessage = isCreatureDoingARequiredBlock(
|
||||||
|
possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastOne, game);
|
||||||
if (blockRequiredMessage != null) { // message means not required
|
if (blockRequiredMessage != null) { // message means not required
|
||||||
removeBlocker(possibleBlockerId, game);
|
removeBlocker(possibleBlockerId, game);
|
||||||
game.informPlayer(controller, blockRequiredMessage + " Existing block removed. It's a requirement to block " + toBeBlockedCreature.getIdName() + ".");
|
game.informPlayer(controller, blockRequiredMessage + " Existing block removed. It's a requirement to block " + toBeBlockedCreature.getIdName() + ".");
|
||||||
|
@ -769,7 +779,8 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
} else {
|
} else {
|
||||||
// take the first potential blocker from the set to block for the AI
|
// take the first potential blocker from the set to block for the AI
|
||||||
for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
|
for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) {
|
||||||
String blockRequiredMessage = isCreatureDoingARequiredBlock(possibleBlockerId, mustBeBlockedByAtLeastOne, game);
|
String blockRequiredMessage = isCreatureDoingARequiredBlock(
|
||||||
|
possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastOne, game);
|
||||||
if (blockRequiredMessage != null) {
|
if (blockRequiredMessage != null) {
|
||||||
// set the block
|
// set the block
|
||||||
Permanent possibleBlocker = game.getPermanent(possibleBlockerId);
|
Permanent possibleBlocker = game.getPermanent(possibleBlockerId);
|
||||||
|
@ -786,6 +797,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// check if creatures are forced to block but do not block at all or block creatures they are not forced to block
|
// check if creatures are forced to block but do not block at all or block creatures they are not forced to block
|
||||||
|
@ -887,11 +899,12 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
* required block
|
* required block
|
||||||
*
|
*
|
||||||
* @param possibleBlockerId
|
* @param possibleBlockerId
|
||||||
|
* @param toBeBlockedCreatureId
|
||||||
* @param mustBeBlockedByAtLeastOne
|
* @param mustBeBlockedByAtLeastOne
|
||||||
* @param game
|
* @param game
|
||||||
* @return null block is required otherwise message with reason why not
|
* @return null block is required otherwise message with reason why not
|
||||||
*/
|
*/
|
||||||
protected String isCreatureDoingARequiredBlock(UUID possibleBlockerId, Map<UUID, Set<UUID>> mustBeBlockedByAtLeastOne, Game game) {
|
protected String isCreatureDoingARequiredBlock(UUID possibleBlockerId, UUID toBeBlockedCreatureId, Map<UUID, Set<UUID>> mustBeBlockedByAtLeastOne, Game game) {
|
||||||
Permanent possibleBlocker = game.getPermanent(possibleBlockerId);
|
Permanent possibleBlocker = game.getPermanent(possibleBlockerId);
|
||||||
if (possibleBlocker != null) {
|
if (possibleBlocker != null) {
|
||||||
if (possibleBlocker.getBlocking() == 0) {
|
if (possibleBlocker.getBlocking() == 0) {
|
||||||
|
@ -908,9 +921,17 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) {
|
if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) {
|
||||||
// blocks a creature that has to be blocked by at least one
|
// blocks a creature that has to be blocked by at least one
|
||||||
if (combatGroupOfPossibleBlocker.getBlockers().size() == 1) {
|
if (combatGroupOfPossibleBlocker.getBlockers().size() == 1) {
|
||||||
// the creature blocks alone already a creature that has to be blocked by at least one,
|
Set <UUID> blockedSet = mustBeBlockedByAtLeastOne.get(blockedAttackerId);
|
||||||
// so this is ok
|
Set <UUID> toBlockSet = mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId);
|
||||||
|
if (toBlockSet == null) {
|
||||||
|
// This should never happen.
|
||||||
return null;
|
return null;
|
||||||
|
} else if (toBlockSet.containsAll(blockedSet)) {
|
||||||
|
// the creature already blocks alone a creature that has to be blocked by at least one
|
||||||
|
// and has more possible blockers, so this is ok
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// TODO: Check if the attacker is already blocked by another creature
|
// TODO: Check if the attacker is already blocked by another creature
|
||||||
// and despite there is need that this attacker blocks this attacker also
|
// and despite there is need that this attacker blocks this attacker also
|
||||||
|
|
Loading…
Reference in a new issue