Skip to content

Commit 75942bc

Browse files
Add option to include basic lands in ante selection (#10293)
Adds UI_ANTE_INCLUDE_BASIC_LANDS preference that, when enabled, allows basic lands to be randomly selected for ante (matching original paper Magic rules). When disabled (default), basic lands continue to be excluded from ante selection, preserving the current Microprose Shandalar behavior. The option applies to both random and rarity-matched ante modes. In Adventure mode settings, the sub-options are disabled (checkmarks hidden) when ante is disabled.
1 parent 82f66c1 commit 75942bc

File tree

12 files changed

+68
-14
lines changed

12 files changed

+68
-14
lines changed

forge-game/src/main/java/forge/game/Game.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@ public int nextHiddenCardId() {
10121012
return ++hiddenCardIdCounter;
10131013
}
10141014

1015-
public Multimap<Player, Card> chooseCardsForAnte(final boolean matchRarity) {
1015+
public Multimap<Player, Card> chooseCardsForAnte(final boolean matchRarity, final boolean includeBasicLands) {
10161016
Multimap<Player, Card> anteed = ArrayListMultimap.create();
10171017

10181018
if (matchRarity) {
@@ -1029,14 +1029,21 @@ public Multimap<Player, Card> chooseCardsForAnte(final boolean matchRarity) {
10291029

10301030
if (validRarities.size() == 0) { //If no possible rarity matches were found, use the original method to choose antes
10311031
for (Player player : getPlayers()) {
1032-
chooseRandomCardsForAnte(player, anteed);
1032+
chooseRandomCardsForAnte(player, anteed, includeBasicLands);
10331033
}
10341034
return anteed;
10351035
}
10361036

1037-
//If possible, don't ante basic lands
1038-
if (validRarities.size() > 1) {
1039-
validRarities.remove(CardRarity.BasicLand);
1037+
//If possible, don't ante basic lands (unless the option to include them is enabled)
1038+
if (!includeBasicLands) {
1039+
if (validRarities.size() > 1) {
1040+
validRarities.remove(CardRarity.BasicLand);
1041+
} else if (validRarities.size() == 1 && validRarities.get(0) == CardRarity.BasicLand) {
1042+
for (Player player : getPlayers()) {
1043+
chooseRandomCardsForAnte(player, anteed, includeBasicLands);
1044+
}
1045+
return anteed;
1046+
}
10401047
}
10411048

10421049
if (validRarities.contains(CardRarity.Special)) {
@@ -1076,20 +1083,27 @@ public Multimap<Player, Card> chooseCardsForAnte(final boolean matchRarity) {
10761083
Card ante = library.get(MyRandom.getRandom().nextInt(library.size()));
10771084
anteed.put(player, ante);
10781085
} else {
1079-
chooseRandomCardsForAnte(player, anteed);
1086+
chooseRandomCardsForAnte(player, anteed, includeBasicLands);
10801087
}
10811088
}
10821089
}
10831090
else {
10841091
for (Player player : getPlayers()) {
1085-
chooseRandomCardsForAnte(player, anteed);
1092+
chooseRandomCardsForAnte(player, anteed, includeBasicLands);
10861093
}
10871094
}
10881095
return anteed;
10891096
}
10901097

1091-
private void chooseRandomCardsForAnte(final Player player, final Multimap<Player, Card> anteed) {
1098+
private void chooseRandomCardsForAnte(final Player player, final Multimap<Player, Card> anteed, final boolean includeBasicLands) {
10921099
final CardCollectionView lib = player.getCardsIn(ZoneType.Library);
1100+
if (includeBasicLands) {
1101+
Card ante = Aggregates.random(lib);
1102+
if (ante != null) {
1103+
anteed.put(player, ante);
1104+
}
1105+
return;
1106+
}
10931107
Predicate<Card> goodForAnte = CardPredicates.BASIC_LANDS.negate();
10941108
Card ante = Aggregates.random(IterableUtil.filter(lib, goodForAnte));
10951109
if (ante == null) {

forge-game/src/main/java/forge/game/GameRules.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class GameRules {
1212
private int gamesToWinMatch = 2;
1313
private boolean playForAnte = false;
1414
private boolean matchAnteRarity = false;
15+
private boolean anteIncludeBasicLands = false;
1516
private boolean AISideboardingEnabled = false;
1617
private boolean sideboardForAI = false;
1718
private boolean allowCheatShuffle = false;
@@ -75,6 +76,13 @@ public void setMatchAnteRarity(final boolean matchRarity) {
7576
matchAnteRarity = matchRarity;
7677
}
7778

79+
public boolean getAnteIncludeBasicLands() {
80+
return anteIncludeBasicLands;
81+
}
82+
public void setAnteIncludeBasicLands(final boolean includeBasicLands) {
83+
anteIncludeBasicLands = includeBasicLands;
84+
}
85+
7886
public boolean getSideboardForAI() {
7987
return sideboardForAI;
8088
}

forge-game/src/main/java/forge/game/Match.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public void startGame(final Game game) {
8080
public void startGame(final Game game, Runnable startGameHook) {
8181
prepareAllZones(game);
8282
if (rules.useAnte()) { // Deciding which cards go to ante
83-
Multimap<Player, Card> list = game.chooseCardsForAnte(rules.getMatchAnteRarity());
83+
Multimap<Player, Card> list = game.chooseCardsForAnte(rules.getMatchAnteRarity(), rules.getAnteIncludeBasicLands());
8484
for (Entry<Player, Card> kv : list.entries()) {
8585
Player p = kv.getKey();
8686
game.getAction().moveTo(ZoneType.Ante, kv.getValue(), null, AbilityKey.newMap());

forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ public void initialize() {
112112
lstControls.clear(); // just in case
113113
lstControls.add(Pair.of(view.getCbAnte(), FPref.UI_ANTE));
114114
lstControls.add(Pair.of(view.getCbAnteMatchRarity(), FPref.UI_ANTE_MATCH_RARITY));
115+
lstControls.add(Pair.of(view.getCbAnteIncludeBasicLands(), FPref.UI_ANTE_INCLUDE_BASIC_LANDS));
115116
lstControls.add(Pair.of(view.getCbManaBurn(), FPref.UI_MANABURN));
116117
lstControls.add(Pair.of(view.getCbOrderCombatants(), FPref.LEGACY_ORDER_COMBATANTS));
117118
lstControls.add(Pair.of(view.getCbScaleLarger(), FPref.UI_SCALE_LARGER));

forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
7070
private final JCheckBox cbRemoveArtifacts = new OptionsCheckBox(localizer.getMessage("cbRemoveArtifacts"));
7171
private final JCheckBox cbAnte = new OptionsCheckBox(localizer.getMessage("cbAnte"));
7272
private final JCheckBox cbAnteMatchRarity = new OptionsCheckBox(localizer.getMessage("cbAnteMatchRarity"));
73+
private final JCheckBox cbAnteIncludeBasicLands = new OptionsCheckBox(localizer.getMessage("cbAnteIncludeBasicLands"));
7374
private final JCheckBox cbEnableAICheats = new OptionsCheckBox(localizer.getMessage("cbEnableAICheats"));
7475
private final JCheckBox cbManaBurn = new OptionsCheckBox(localizer.getMessage("cbManaBurn"));
7576
private final JCheckBox cbOrderCombatants = new OptionsCheckBox(localizer.getMessage("cbOrderCombatants"));
@@ -228,6 +229,9 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
228229
pnlPrefs.add(cbAnteMatchRarity, titleConstraints);
229230
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlAnteMatchRarity")), descriptionConstraints);
230231

232+
pnlPrefs.add(cbAnteIncludeBasicLands, titleConstraints);
233+
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlAnteIncludeBasicLands")), descriptionConstraints);
234+
231235
pnlPrefs.add(cbEnableAICheats, titleConstraints);
232236
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlEnableAICheats")), descriptionConstraints);
233237

@@ -764,6 +768,11 @@ public JCheckBox getCbAnteMatchRarity() {
764768
return cbAnteMatchRarity;
765769
}
766770

771+
/** @return {@link javax.swing.JCheckBox} */
772+
public JCheckBox getCbAnteIncludeBasicLands() {
773+
return cbAnteIncludeBasicLands;
774+
}
775+
767776
/** @return {@link javax.swing.JCheckBox} */
768777
public JCheckBox getCbManaBurn() {
769778
return cbManaBurn;

forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/GameWrapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public void runGame() {
6969
GameRules rules = new GameRules(GameType.Constructed);
7070
rules.setPlayForAnte(FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE));
7171
rules.setMatchAnteRarity(FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE_MATCH_RARITY));
72+
rules.setAnteIncludeBasicLands(FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE_INCLUDE_BASIC_LANDS));
7273
rules.setManaBurn(FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN));
7374
rules.setOrderCombatants(FModel.getPreferences().getPrefBoolean(FPref.LEGACY_ORDER_COMBATANTS));
7475
rules.setUseGrayText(FModel.getPreferences().getPrefBoolean(FPref.UI_GRAY_INACTIVE_TEXT));

forge-gui-mobile/src/forge/adventure/scene/DuelScene.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ public void enter() {
507507
}
508508
rules.setPlayForAnte(FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ANTE));
509509
rules.setMatchAnteRarity(FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ANTE_MATCH_RARITY));
510+
rules.setAnteIncludeBasicLands(FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ANTE_INCLUDE_BASIC_LANDS));
510511
rules.setManaBurn(false);
511512
rules.setWarnAboutAICards(false);
512513

forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,20 @@ public void changed(ChangeEvent event, Actor actor) {
267267
Config.instance().saveSettings();
268268
}
269269
});
270-
addCheckBox(Forge.getLocalizer().getMessage("cbAnte"), ForgePreferences.FPref.UI_ANTE);
271-
addCheckBox(Forge.getLocalizer().getMessage("cbAnteMatchRarity"), ForgePreferences.FPref.UI_ANTE_MATCH_RARITY);
270+
CheckBox cbAnte = addCheckBox(Forge.getLocalizer().getMessage("cbAnte"), ForgePreferences.FPref.UI_ANTE);
271+
CheckBox cbAnteMatchRarity = addCheckBox(Forge.getLocalizer().getMessage("cbAnteMatchRarity"), ForgePreferences.FPref.UI_ANTE_MATCH_RARITY);
272+
CheckBox cbAnteIncludeBasicLands = addCheckBox(Forge.getLocalizer().getMessage("cbAnteIncludeBasicLands"), ForgePreferences.FPref.UI_ANTE_INCLUDE_BASIC_LANDS);
273+
boolean anteEnabled = FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ANTE);
274+
cbAnteMatchRarity.setDisabled(!anteEnabled);
275+
cbAnteIncludeBasicLands.setDisabled(!anteEnabled);
276+
cbAnte.addListener(new ChangeListener() {
277+
@Override
278+
public void changed(ChangeEvent event, Actor actor) {
279+
boolean enabled = ((CheckBox) actor).isChecked();
280+
cbAnteMatchRarity.setDisabled(!enabled);
281+
cbAnteIncludeBasicLands.setDisabled(!enabled);
282+
}
283+
});
272284
addCheckBox(Forge.getLocalizer().getMessage("lblPromptAutoSell"), ForgePreferences.FPref.PROMPT_FOR_AUTOSELL);
273285
addCheckBox(Forge.getLocalizer().getMessage("lblCardName"), ForgePreferences.FPref.UI_OVERLAY_CARD_NAME);
274286
addSettingSlider(Forge.getLocalizer().getMessage("cbAdjustMusicVolume"), ForgePreferences.FPref.UI_VOL_MUSIC, 0, 100);
@@ -363,11 +375,11 @@ public void changed(ChangeEvent event, Actor actor) {
363375
settingGroup.add(box).align(Align.right);
364376
}
365377

366-
private void addCheckBox(String name, ForgePreferences.FPref pref) {
367-
addCheckBox(name, pref, null);
378+
private CheckBox addCheckBox(String name, ForgePreferences.FPref pref) {
379+
return addCheckBox(name, pref, null);
368380
}
369381

370-
private void addCheckBox(String name, ForgePreferences.FPref pref, Runnable runnable) {
382+
private CheckBox addCheckBox(String name, ForgePreferences.FPref pref, Runnable runnable) {
371383
CheckBox box = Controls.newCheckBox("");
372384
box.setChecked(FModel.getPreferences().getPrefBoolean(pref));
373385
box.addListener(new ChangeListener() {
@@ -382,6 +394,7 @@ public void changed(ChangeEvent event, Actor actor) {
382394

383395
addLabel(name);
384396
settingGroup.add(box).align(Align.right);
397+
return box;
385398
}
386399

387400
private void addSettingSlider(String name, ForgePreferences.FPref pref, int min, int max) {

forge-gui-mobile/src/forge/screens/settings/SettingsPage.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ public void valueChanged(String newValue) {
193193
lstSettings.addItem(new BooleanSetting(FPref.UI_ANTE_MATCH_RARITY,
194194
Forge.getLocalizer().getMessage("cbAnteMatchRarity"),
195195
Forge.getLocalizer().getMessage("nlAnteMatchRarity")), 1);
196+
lstSettings.addItem(new BooleanSetting(FPref.UI_ANTE_INCLUDE_BASIC_LANDS,
197+
Forge.getLocalizer().getMessage("cbAnteIncludeBasicLands"),
198+
Forge.getLocalizer().getMessage("nlAnteIncludeBasicLands")), 1);
196199
lstSettings.addItem(new BooleanSetting(FPref.MATCH_HOT_SEAT_MODE,
197200
Forge.getLocalizer().getMessage("lblHotSeatMode"),
198201
Forge.getLocalizer().getMessage("nlHotSeatMode")), 1);

forge-gui/res/languages/en-US.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ cbSingletons=Singleton Mode
9191
cbRemoveArtifacts=Remove Artifacts
9292
cbAnte=Play for Ante
9393
cbAnteMatchRarity=Match Ante Rarity
94+
cbAnteIncludeBasicLands=Ante Can Include Basic Lands
9495
cbEnableAICheats=Allow AI Cheating
9596
cbManaBurn=Mana Burn
9697
cbOrderCombatants=Order Combatants
@@ -189,6 +190,7 @@ nlpAiProfiles=Choose your AI opponent
189190
nlpStackAdditions=Choose when you want to get visual notifications for an effect added to the stack: Never, always, or only for the effects cast/activated by a AI player or triggered by any player
190191
nlAnte=Determines whether or not the game is played for ante.
191192
nlAnteMatchRarity=Attempts to make antes the same rarity for all players.
193+
nlAnteIncludeBasicLands=Allows basic lands to be selected for ante, matching original paper Magic rules.
192194
nlEnableAICheats=Allow the AI to cheat to gain advantage (for personalities that have cheat shuffling options set).
193195
nlManaBurn=Play with mana burn (from pre-Magic 2010 rules).
194196
nlOrderCombatants=Play with legacy ordering combatants (rule from Magic 2010 to pre-Foundations).

0 commit comments

Comments
 (0)