From cb13682737da6fba0c3b66479e8350ccd5aa3d10 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 4 Sep 2025 06:50:04 +0800 Subject: [PATCH] remove unsupported cards on game matches - closes #8616 --- .../java/forge/ai/PlayerControllerAi.java | 5 +++++ forge-core/src/main/java/forge/deck/Deck.java | 14 ++++++++++++++ .../src/main/java/forge/game/GameAction.java | 7 +++++++ .../src/main/java/forge/game/Match.java | 19 +++++++++++++------ .../forge/game/player/PlayerController.java | 2 ++ .../util/PlayerControllerForTests.java | 5 +++++ .../forge/player/PlayerControllerHuman.java | 10 ++++++++++ 7 files changed, 56 insertions(+), 6 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index 6cd6815c86f..1b94140f717 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -1347,6 +1347,11 @@ public class PlayerControllerAi extends PlayerController { // Ai won't understand that anyway } + @Override + public void revealUnsupported(Map> unsupported) { + // Ai won't understand that anyway + } + @Override public Map> complainCardsCantPlayWell(Deck myDeck) { // TODO check if profile detection set to Auto diff --git a/forge-core/src/main/java/forge/deck/Deck.java b/forge-core/src/main/java/forge/deck/Deck.java index 4d6b34e22a7..22f11d22c8f 100644 --- a/forge-core/src/main/java/forge/deck/Deck.java +++ b/forge-core/src/main/java/forge/deck/Deck.java @@ -115,6 +115,20 @@ public class Deck extends DeckBase implements Iterable> getValid() { + List unsupported = new ArrayList<>(); + for (Entry kv : parts.entrySet()) { + CardPool pool = kv.getValue(); + for (Entry pc : pool) { + if (pc.getKey().getRules() != null && pc.getKey().getRules().isUnsupported()) { + unsupported.add(pc.getKey()); + pool.remove(pc.getKey()); + } + } + } + return Pair.of(this, unsupported); + } + public List getCommanders() { List result = Lists.newArrayList(); final CardPool cp = get(DeckSection.Commander); diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index c44ea5b1288..c2d2425a501 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -2222,6 +2222,13 @@ public class GameAction { } } + public void revealUnsupported(Map> unsupported) { + // Notify players + for (Player p : game.getPlayers()) { + p.getController().revealUnsupported(unsupported); + } + } + /** Delivers a message to all players. (use reveal to show Cards) */ public void notifyOfValue(SpellAbility saSource, GameObject relatedTarget, String value, Player playerExcept) { if (saSource != null) { diff --git a/forge-game/src/main/java/forge/game/Match.java b/forge-game/src/main/java/forge/game/Match.java index 2c5b7e3605e..f340a777cb9 100644 --- a/forge-game/src/main/java/forge/game/Match.java +++ b/forge-game/src/main/java/forge/game/Match.java @@ -23,6 +23,7 @@ import forge.item.PaperCard; import forge.util.Localizer; import forge.util.MyRandom; import forge.util.collect.FCollectionView; +import org.apache.commons.lang3.tuple.Pair; import java.util.*; import java.util.Map.Entry; @@ -224,6 +225,7 @@ public class Match { // friendliness Map>> rAICards = new HashMap<>(); Multimap removedAnteCards = ArrayListMultimap.create(); + Map> unsupported = new HashMap<>(); final FCollectionView players = game.getPlayers(); final List playersConditions = game.getMatch().getPlayers(); @@ -293,17 +295,17 @@ public class Match { Set myRemovedAnteCards = null; if (!rules.useAnte()) { - myRemovedAnteCards = getRemovedAnteCards(myDeck); + myRemovedAnteCards = getRemovedAnteCards(myDeck.getLeft()); for (PaperCard cp: myRemovedAnteCards) { - for (Entry ds : myDeck) { + for (Entry ds : myDeck.getLeft()) { ds.getValue().removeAll(cp); } } } - preparePlayerZone(player, ZoneType.Library, myDeck.getMain(), psc.useRandomFoil()); - if (myDeck.has(DeckSection.Sideboard)) { - preparePlayerZone(player, ZoneType.Sideboard, myDeck.get(DeckSection.Sideboard), psc.useRandomFoil()); + preparePlayerZone(player, ZoneType.Library, myDeck.getLeft().getMain(), psc.useRandomFoil()); + if (myDeck.getLeft().has(DeckSection.Sideboard)) { + preparePlayerZone(player, ZoneType.Sideboard, myDeck.getLeft().get(DeckSection.Sideboard), psc.useRandomFoil()); // Assign Companion Card companion = player.assignCompanion(game, person); @@ -322,7 +324,7 @@ public class Match { player.shuffle(null); if (isFirstGame) { - Map> cardsComplained = player.getController().complainCardsCantPlayWell(myDeck); + Map> cardsComplained = player.getController().complainCardsCantPlayWell(myDeck.getLeft()); if (cardsComplained != null && !cardsComplained.isEmpty()) { rAICards.put(player, cardsComplained); } @@ -337,6 +339,7 @@ public class Match { if (myRemovedAnteCards != null && !myRemovedAnteCards.isEmpty()) { removedAnteCards.putAll(player, myRemovedAnteCards); } + unsupported.put(player, myDeck.getRight()); } final Localizer localizer = Localizer.getInstance(); @@ -347,6 +350,10 @@ public class Match { if (!removedAnteCards.isEmpty()) { game.getAction().revealAnte(localizer.getMessage("lblAnteCardsRemoved"), removedAnteCards); } + + if (!unsupported.isEmpty()) { + game.getAction().revealUnsupported(unsupported); + } } private void executeAnte(Game lastGame) { diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index c44f84e8470..b6eff922da9 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -287,6 +287,8 @@ public abstract class PlayerController { public abstract void revealAnte(String message, Multimap removedAnteCards); public abstract void revealAISkipCards(String message, Map>> deckCards); + public abstract void revealUnsupported(Map> unsupported); + // These 2 are for AI public CardCollectionView cheatShuffle(CardCollectionView list) { return list; } public Map> complainCardsCantPlayWell(Deck myDeck) { return null; } diff --git a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java index c46ffc6deb6..958d18eb986 100644 --- a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java +++ b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java @@ -664,6 +664,11 @@ public class PlayerControllerForTests extends PlayerController { // TODO test this! } + @Override + public void revealUnsupported(Map> unsupported) { + // test this! + } + @Override public List chooseCardsYouWonToAddToDeck(List losses) { // TODO Auto-generated method stub diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 445f62ee7de..224927bd9ba 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -2306,6 +2306,16 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } } + @Override + public void revealUnsupported(final Map> unsupported) { + for (final Player p : unsupported.keySet()) { + List removed = unsupported.get(p); + if (removed == null || removed.isEmpty()) + continue; + getGui().getChoices(localizer.getMessage("lblActionFromPlayerDeck", localizer.getMessage("lblRemoved"), Lang.getInstance().getPossessedObject(MessageUtil.mayBeYou(player, p), "")), -1, -1, ImmutableList.copyOf(removed)); + } + } + @Override public List chooseCardsYouWonToAddToDeck(final List losses) { return getGui().many(localizer.getMessage("lblSelectCardstoAddtoYourDeck"), localizer.getMessage("lblAddTheseToMyDeck"), 0, losses.size(), losses, null);