diff --git a/forge-core/src/main/java/forge/MulliganDefs.java b/forge-core/src/main/java/forge/MulliganDefs.java new file mode 100644 index 00000000000..ee0731ffd8c --- /dev/null +++ b/forge-core/src/main/java/forge/MulliganDefs.java @@ -0,0 +1,42 @@ +package forge; + +import com.google.common.collect.Lists; + +import java.util.List; + +/* + * A class that contains definitions of available Mulligan rule variants and helper methods to access them + */ +public class MulliganDefs { + public enum MulliganRule { + Original, + Paris, + Vancouver, + London + } + private static MulliganRule defaultRule = MulliganRule.Vancouver; + + public static MulliganRule getDefaultRule() { + return defaultRule; + } + + public static String[] getMulliganRuleNames() { + List names = Lists.newArrayList(); + for (MulliganRule mr : MulliganRule.values()) { + names.add(mr.name()); + } + return names.toArray(new String[0]); + } + + public static MulliganRule GetRuleByName(String rule) { + MulliganRule r; + try { + r = MulliganRule.valueOf(rule); + } catch (IllegalArgumentException ex) { + System.err.println("Warning: illegal Mulligan rule specified: " + rule + ", defaulting to " + getDefaultRule().name()); + r = getDefaultRule(); + } + + return r; + } +} diff --git a/forge-core/src/main/java/forge/StaticData.java b/forge-core/src/main/java/forge/StaticData.java index 9e8629baf20..99f05389bca 100644 --- a/forge-core/src/main/java/forge/StaticData.java +++ b/forge-core/src/main/java/forge/StaticData.java @@ -39,6 +39,8 @@ public class StaticData { private boolean filteredHandsEnabled = false; + private MulliganDefs.MulliganRule mulliganRule = MulliganDefs.getDefaultRule(); + // Loaded lazily: private IStorage boosters; private IStorage specialBoosters; @@ -215,10 +217,6 @@ public class StaticData { this.filteredHandsEnabled = filteredHandsEnabled; } - public boolean getFilteredHandsEnabled(){ - return filteredHandsEnabled; - } - public PaperCard getCardByEditionDate(PaperCard card, Date editionDate) { PaperCard c = this.getCommonCards().getCardFromEdition(card.getName(), editionDate, CardDb.SetPreference.LatestCoreExp, card.getArtIndex()); @@ -242,4 +240,17 @@ public class StaticData { // I give up! return card; } + + public boolean getFilteredHandsEnabled(){ + return filteredHandsEnabled; + } + + public void setMulliganRule(MulliganDefs.MulliganRule rule) { + mulliganRule = rule; + } + + public MulliganDefs.MulliganRule getMulliganRule() { + return mulliganRule; + } + } diff --git a/forge-game/src/main/java/forge/game/mulligan/MulliganService.java b/forge-game/src/main/java/forge/game/mulligan/MulliganService.java index 0c576f97327..2fed6777cc5 100644 --- a/forge-game/src/main/java/forge/game/mulligan/MulliganService.java +++ b/forge-game/src/main/java/forge/game/mulligan/MulliganService.java @@ -4,6 +4,8 @@ import java.util.List; import com.google.common.collect.Lists; +import forge.MulliganDefs; +import forge.StaticData; import forge.game.Game; import forge.game.GameType; import forge.game.player.Player; @@ -35,8 +37,25 @@ public class MulliganService { boolean firstMullFree = game.getPlayers().size() > 2 || game.getRules().hasAppliedVariant(GameType.Brawl); for (int i = 0; i < whoCanMulligan.size(); i++) { - // hook in the UI for different mulligans here - mulligans.add(new VancouverMulligan(whoCanMulligan.get(i), firstMullFree)); + MulliganDefs.MulliganRule rule = StaticData.instance().getMulliganRule(); + switch (rule) { + case Original: + mulligans.add(new OriginalMulligan(whoCanMulligan.get(i), firstMullFree)); + break; + case Paris: + mulligans.add(new ParisMulligan(whoCanMulligan.get(i), firstMullFree)); + break; + case Vancouver: + mulligans.add(new VancouverMulligan(whoCanMulligan.get(i), firstMullFree)); + break; + case London: + mulligans.add(new LondonMulligan(whoCanMulligan.get(i), firstMullFree)); + break; + default: + // Default to Vancouver mulligan for now. Should ideally never get here. + mulligans.add(new VancouverMulligan(whoCanMulligan.get(i), firstMullFree)); + break; + } } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java index 62c0be34a84..4d766f4e6cf 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java @@ -1,8 +1,6 @@ package forge.screens.home.settings; -import forge.GuiBase; -import forge.Singletons; -import forge.UiCommand; +import forge.*; import forge.ai.AiProfileUtil; import forge.control.FControl.CloseAction; import forge.game.GameLogEntryType; @@ -227,6 +225,7 @@ public enum CSubmenuPreferences implements ICDoc { initializeGameLogVerbosityComboBox(); initializeCloseActionComboBox(); initializeDefaultFontSizeComboBox(); + initializeMulliganRuleComboBox(); initializeAiProfilesComboBox(); initializeColorIdentityCombobox(); initializeAutoYieldModeComboBox(); @@ -355,8 +354,7 @@ public enum CSubmenuPreferences implements ICDoc { panel.setComboBox(comboBox, Singletons.getControl().getCloseAction()); } - private void initializeDefaultLanguageComboBox() { - + private void initializeDefaultLanguageComboBox() { final String [] choices = {"en-US", "es-ES", "de-DE"}; final FPref userSetting = FPref.UI_LANGUAGE; final FComboBoxPanel panel = this.view.getCbpDefaultLanguageComboBoxPanel(); @@ -364,6 +362,21 @@ public enum CSubmenuPreferences implements ICDoc { final String selectedItem = this.prefs.getPref(userSetting); panel.setComboBox(comboBox, selectedItem); } + + private void initializeMulliganRuleComboBox() { + final String [] choices = MulliganDefs.getMulliganRuleNames(); + final FPref userSetting = FPref.MULLIGAN_RULE; + final FComboBoxPanel panel = this.view.getCbpMulliganRule(); + final FComboBox comboBox = createComboBox(choices, userSetting); + final String selectedItem = this.prefs.getPref(userSetting); + comboBox.addItemListener(new ItemListener() { + @Override public void itemStateChanged(final ItemEvent e) { + StaticData.instance().setMulliganRule(MulliganDefs.GetRuleByName(prefs.getPref(FPref.MULLIGAN_RULE))); + } + }); + panel.setComboBox(comboBox, selectedItem); + } + private void initializeDefaultFontSizeComboBox() { final String [] choices = {"10", "11", "12", "13", "14", "15", "16", "17", "18"}; final FPref userSetting = FPref.UI_DEFAULT_FONT_SIZE; diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java index 11499dd475e..b821d1ec7fb 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java @@ -114,6 +114,7 @@ public enum VSubmenuPreferences implements IVSubmenu { private final FComboBoxPanel cbpGameLogEntryType = new FComboBoxPanel<>(localizer.getMessage("cbpGameLogEntryType")+":"); private final FComboBoxPanel cbpCloseAction = new FComboBoxPanel<>(localizer.getMessage("cbpCloseAction")+":"); private final FComboBoxPanel cbpDefaultFontSize = new FComboBoxPanel<>(localizer.getMessage("cbpDefaultFontSize")+":"); + private final FComboBoxPanel cbpMulliganRule = new FComboBoxPanel<>(localizer.getMessage("cbpMulliganRule")+":"); private final FComboBoxPanel cbpAiProfiles = new FComboBoxPanel<>(localizer.getMessage("cbpAiProfiles")+":"); private final FComboBoxPanel cbpDisplayCurrentCardColors = new FComboBoxPanel<>(localizer.getMessage("cbpDisplayCurrentCardColors")+":"); private final FComboBoxPanel cbpAutoYieldMode = new FComboBoxPanel<>(localizer.getMessage("cbpAutoYieldMode")+":"); @@ -172,6 +173,9 @@ public enum VSubmenuPreferences implements IVSubmenu { // Gameplay Options pnlPrefs.add(new SectionLabel(localizer.getMessage("GamePlay")), sectionConstraints); + pnlPrefs.add(cbpMulliganRule, comboBoxConstraints); + pnlPrefs.add(new NoteLabel(localizer.getMessage("nlpMulliganRule")), descriptionConstraints); + pnlPrefs.add(cbpAiProfiles, comboBoxConstraints); pnlPrefs.add(new NoteLabel(localizer.getMessage("nlpAiProfiles")), descriptionConstraints); @@ -637,6 +641,10 @@ public enum VSubmenuPreferences implements IVSubmenu { return cbWorkshopSyntax; } + public FComboBoxPanel getCbpMulliganRule() { + return cbpMulliganRule; + } + public FComboBoxPanel getAiProfilesComboBoxPanel() { return cbpAiProfiles; } diff --git a/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java b/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java index a880ff379fa..f13dafbc3b2 100644 --- a/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java +++ b/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java @@ -3,6 +3,8 @@ package forge.screens.settings; import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; import forge.Forge; import forge.Graphics; +import forge.MulliganDefs; +import forge.StaticData; import forge.ai.AiProfileUtil; import forge.assets.FSkin; import forge.assets.FSkinColor; @@ -84,6 +86,15 @@ public class SettingsPage extends TabPage { 0); //Gameplay Options + lstSettings.addItem(new CustomSelectSetting(FPref.MULLIGAN_RULE, "Mulligan Rule", + "Choose the version of the Mulligan rule.", + MulliganDefs.getMulliganRuleNames()) { + @Override + public void valueChanged(String newValue) { + super.valueChanged(newValue); + StaticData.instance().setMulliganRule(MulliganDefs.GetRuleByName(FModel.getPreferences().getPref(FPref.MULLIGAN_RULE))); + } + }, 1); lstSettings.addItem(new CustomSelectSetting(FPref.UI_CURRENT_AI_PROFILE, "AI Personality", "Choose your AI opponent.", diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index e6ec835f4ce..a6a1d758077 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -70,6 +70,7 @@ cbUseSentry=Sende automatisch Fehlerberichte cbpGameLogEntryType=Spielberichtsumfang cbpCloseAction=Beenden cbpDefaultFontSize=Standard Schriftgröße +cbpMulliganRule = Mulligan Rule cbpAiProfiles=KI Persönlichkeit cbpDisplayCurrentCardColors=Zeige detailierte Kartenfarben cbpAutoYieldMode=Automatische Bestätigung @@ -82,6 +83,7 @@ nlPlayerName=Name unter welchem du beim Spielen geführt wirst. nlCompactMainMenu=Aktiviere, um im Seitenmenü platzsparend immer nur eine Menügruppe anzeigen zu lassen. (Erfordert Neustart) nlUseSentry=Aktiviere, um automatische Fehlerberichte an die Entwickler zu senden. GamePlay=Spiel +nlpMulliganRule=Choose the version of the Mulligan rule nlpAiProfiles=Wähle die Spielweise deines KI-Gegners. nlAnte=Entscheidet, ob um einen Einsatz (Ante) gespielt wird. nlAnteMatchRarity=Versucht den Spieleinsatz für alle Spieler ungefähr gleich zu halten. diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 998450e51c9..82a6fc7b49a 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -70,6 +70,7 @@ cbUseSentry = Automatically submit bug reports. cbpGameLogEntryType = Game Log Verbosity cbpCloseAction = Close Action cbpDefaultFontSize = Default Font Size +cbpMulliganRule = Mulligan Rule cbpAiProfiles = AI Personality cbpDisplayCurrentCardColors = Show Detailed Card Color cbpAutoYieldMode = Auto-Yield @@ -82,6 +83,7 @@ nlPlayerName = Sets the name that you will be referred to by Forge during gamepl nlCompactMainMenu = Enable for a space efficient sidebar that displays only one menu group at a time (RESTART REQUIRED). nlUseSentry = When enabled, automatically submits bug reports to developers. GamePlay = Gameplay +nlpMulliganRule = Choose the version of the Mulligan rule nlpAiProfiles = Choose your AI opponent nlAnte = Determines whether or not the game is played for ante. nlAnteMatchRarity = Attempts to make antes the same rarity for all players. diff --git a/forge-gui/res/languages/es-es.properties b/forge-gui/res/languages/es-es.properties index 0ed4c5a9ea0..fe4df8b0485 100644 --- a/forge-gui/res/languages/es-es.properties +++ b/forge-gui/res/languages/es-es.properties @@ -70,6 +70,7 @@ cbUseSentry=Enviar automáticamente informes de errores. cbpGameLogEntryType=Verbosidad del registro del juego cbpCloseAction=Acción al cerrar cbpDefaultFontSize=Tamaño de fuente predeterminado +cbpMulliganRule = Mulligan Rule cbpAiProfiles=Personalidad de la IA cbpDisplayCurrentCardColors=Mostrar color detallado de la carta cbpAutoYieldMode=Auto-Ceder @@ -82,6 +83,7 @@ nlPlayerName=Establece el nombre al que te referirá Forge durante el juego. nlCompactMainMenu=Habilitar para una barra lateral eficiente en espacio que muestre solo un grupo de menús a la vez (REQUIERE REINICIAR). nlUseSentry=Cuando está habilitado, envía automáticamente informes de errores a los desarrolladores. GamePlay=Juego +nlpMulliganRule=Choose the version of the Mulligan rule nlpAiProfiles=Elige tu oponente de la IA nlAnte=Determina si el juego se juega con apuesta o no. nlAnteMatchRarity=Intenta crear apuesta de la misma rareza para todos los jugadores. diff --git a/forge-gui/src/main/java/forge/model/FModel.java b/forge-gui/src/main/java/forge/model/FModel.java index 3528ed4d14e..549c7ca966e 100644 --- a/forge-gui/src/main/java/forge/model/FModel.java +++ b/forge-gui/src/main/java/forge/model/FModel.java @@ -17,11 +17,10 @@ */ package forge.model; -import forge.CardStorageReader; +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import forge.*; import forge.CardStorageReader.ProgressObserver; -import forge.FThreads; -import forge.ImageKeys; -import forge.StaticData; import forge.achievement.*; import forge.ai.AiProfileUtil; import forge.card.CardPreferences; @@ -58,9 +57,6 @@ import java.io.File; import java.util.List; import java.util.Map; -import com.google.common.base.Function; -import com.google.common.collect.Maps; - /** * The default Model implementation for Forge. * @@ -174,6 +170,7 @@ public final class FModel { magicDb.setModernPredicate(formats.getModern().getFilterRules()); magicDb.setFilteredHandsEnabled(preferences.getPrefBoolean(FPref.FILTERED_HANDS)); + magicDb.setMulliganRule(MulliganDefs.MulliganRule.valueOf(preferences.getPref(FPref.MULLIGAN_RULE))); blocks = new StorageBase<>("Block definitions", new CardBlock.Reader(ForgeConstants.BLOCK_DATA_DIR + "blocks.txt", magicDb.getEditions())); questPreferences = new QuestPreferences(); diff --git a/forge-gui/src/main/java/forge/properties/ForgePreferences.java b/forge-gui/src/main/java/forge/properties/ForgePreferences.java index 747392138d7..51f4b2f3900 100644 --- a/forge-gui/src/main/java/forge/properties/ForgePreferences.java +++ b/forge-gui/src/main/java/forge/properties/ForgePreferences.java @@ -160,6 +160,7 @@ public class ForgePreferences extends PreferencesStore { ENFORCE_DECK_LEGALITY ("true"), PERFORMANCE_MODE ("false"), FILTERED_HANDS ("false"), + MULLIGAN_RULE("Vancouver"), DEV_MODE_ENABLED ("false"), DEV_WORKSHOP_SYNTAX ("false"),