fixed and refactored balance effect (#6595)

* fixed and refactored balance effect

* inversed logic in balance effect - now players choose cards to keep instead to sacrifice/discard
This commit is contained in:
18ths 2020-06-11 23:19:45 +02:00 committed by GitHub
parent 642cdea2f8
commit e68a20c5fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 116 additions and 91 deletions

View file

@ -0,0 +1,41 @@
package org.mage.test.cards.single;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class BalanceTest extends CardTestPlayerBase {
@Test
public void testBalance() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerA, "Runeclaw Bear", 3);
addCard(Zone.HAND, playerA, "Plains", 1);
addCard(Zone.HAND, playerA, "Balance");
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 3);
addCard(Zone.BATTLEFIELD, playerB, "Runeclaw Bear", 2);
addCard(Zone.HAND, playerB, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balance");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Plains", 2);
assertPermanentCount(playerA, "Runeclaw Bear", 2);
assertHandCount(playerA, "Plains", 1);
assertHandCount(playerA, "Balance", 0);
assertGraveyardCount(playerA, "Runeclaw Bear", 1);
assertGraveyardCount(playerA, "Balance", 1);
assertPermanentCount(playerB, "Swamp", 2);
assertPermanentCount(playerB, "Runeclaw Bear", 2);
assertHandCount(playerB, "Swamp", 1);
assertGraveyardCount(playerB, "Swamp", 2); //1 from hand, 1 from battlefield
}
}

View file

@ -17,19 +17,14 @@ import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetControlledPermanent;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author emerald000
*/
public class BalanceEffect extends OneShotEffect {
private static final FilterControlledPermanent filter = new FilterControlledLandPermanent("lands to keep");
private static final FilterControlledPermanent filter2 = new FilterControlledCreaturePermanent("creatures to keep");
private static final FilterCard filter3 = new FilterCard("cards to keep");
public BalanceEffect() {
super(Outcome.Sacrifice);
staticText = "each player chooses a number of lands they control "
@ -53,108 +48,45 @@ public class BalanceEffect extends OneShotEffect {
if (controller == null) {
return false;
}
//Lands
int minLand = Integer.MAX_VALUE;
Cards landsToSacrifice = new CardsImpl();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player == null) {
continue;
}
int count = game.getBattlefield().countAll(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, player.getId(), game);
if (count < minLand) {
minLand = count;
}
}
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player == null) {
continue;
}
TargetControlledPermanent target = new TargetControlledPermanent(minLand, minLand, filter, true);
if (!target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) {
continue;
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, player.getId(), source.getSourceId(), game)) {
if (permanent != null && !target.getTargets().contains(permanent.getId())) {
landsToSacrifice.add(permanent);
}
}
}
for (UUID cardId : landsToSacrifice) {
Permanent permanent = game.getPermanent(cardId);
if (permanent != null) {
permanent.sacrifice(source.getSourceId(), game);
}
}
//Creatures
int minCreature = Integer.MAX_VALUE;
Cards creaturesToSacrifice = new CardsImpl();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player == null) {
}
int count = game.getBattlefield().countAll(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, player.getId(), game);
if (count < minCreature) {
minCreature = count;
}
}
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player == null) {
continue;
}
TargetControlledPermanent target = new TargetControlledPermanent(minCreature, minCreature, filter2, true);
if (!target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) {
continue;
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_CREATURE, player.getId(), source.getSourceId(), game)) {
if (permanent != null && !target.getTargets().contains(permanent.getId())) {
creaturesToSacrifice.add(permanent);
}
}
}
for (UUID cardId : creaturesToSacrifice) {
Permanent permanent = game.getPermanent(cardId);
if (permanent != null) {
permanent.sacrifice(source.getSourceId(), game);
}
}
choosePermanentsToKeep(game, source, controller, StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, new FilterControlledLandPermanent("lands to keep"));
choosePermanentsToKeep(game, source, controller, StaticFilters.FILTER_CONTROLLED_CREATURE, new FilterControlledCreaturePermanent("creatures to keep"));
//Cards in hand
int minCard = Integer.MAX_VALUE;
Map<UUID, Cards> cardsToDiscard = new HashMap<>(2);
int lowestHandSize = Integer.MAX_VALUE;
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player == null) {
continue;
}
int count = player.getHand().size();
if (count < minCard) {
minCard = count;
}
lowestHandSize = Math.min(lowestHandSize, player.getHand().size());
}
Map<UUID, Cards> cardsToDiscard = new HashMap<>();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player == null) {
continue;
}
Cards cards = new CardsImpl();
TargetCardInHand target = new TargetCardInHand(minCard, filter3);
if (!target.choose(Outcome.Discard, player.getId(), source.getSourceId(), game)) {
TargetCardInHand target = new TargetCardInHand(lowestHandSize, new FilterCard("cards to keep"));
if (!target.choose(Outcome.Protect, player.getId(), source.getSourceId(), game)) {
continue;
}
for (Card card : player.getHand().getCards(game)) {
if (card != null && !target.getTargets().contains(card.getId())) {
cards.add(card);
Set<Card> allCardsInHand = player.getHand().getCards(game);
Set<Card> cardsToKeep = new LinkedHashSet<>();
for (Card card : allCardsInHand) {
if (card != null && target.getTargets().contains(card.getId())) {
cardsToKeep.add(card);
}
}
cardsToDiscard.put(playerId, cards);
cardsToDiscard.put(playerId, allCardsInHand.stream()
.filter(e -> !cardsToKeep.contains(e))
.collect(CardsImpl::new, CardsImpl::add, CardsImpl::addAll));
}
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
@ -163,6 +95,58 @@ public class BalanceEffect extends OneShotEffect {
player.discard(cardsToDiscard.get(playerId), source, game);
}
}
return true;
}
private void choosePermanentsToKeep(Game game, Ability source, Player controller,
FilterControlledPermanent filterPermanent, FilterControlledPermanent filterPermanentDialog) {
int lowestPermanentsCount = Integer.MAX_VALUE;
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player == null) {
continue;
}
lowestPermanentsCount = Math.min(lowestPermanentsCount,
game.getBattlefield().countAll(filterPermanent, player.getId(), game));
}
List<Permanent> permanentsToSacrifice = new ArrayList<>();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player == null) {
continue;
}
TargetControlledPermanent target = new TargetControlledPermanent(lowestPermanentsCount, lowestPermanentsCount, filterPermanentDialog, true);
if (!target.choose(Outcome.Protect, player.getId(), source.getSourceId(), game)) {
continue;
}
List<Permanent> allPermanentsOfType = game.getBattlefield().getActivePermanents(filterPermanent, player.getId(), source.getSourceId(), game);
List<Permanent> permanentsToKeep = new ArrayList<>();
for (Permanent permanent : allPermanentsOfType) {
if (permanent != null && target.getTargets().contains(permanent.getId())) {
permanentsToKeep.add(permanent);
}
}
List<Permanent> playerPermanentsToSacrifice = allPermanentsOfType.stream().filter(e -> !permanentsToKeep.contains(e)).collect(Collectors.toList());
permanentsToSacrifice.addAll(playerPermanentsToSacrifice);
if (playerPermanentsToSacrifice.isEmpty()) {
game.informPlayers(player.getLogName() + " chose permanents to be sacrificed: "
+ playerPermanentsToSacrifice.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
}
}
for (Permanent permanent : permanentsToSacrifice) {
if (permanent != null) {
permanent.sacrifice(source.getSourceId(), game);
}
}
}
}