From ac2881cc6c96ff57e4a0c43ea315ac160f09c1cd Mon Sep 17 00:00:00 2001 From: Agetian Date: Sun, 1 Jan 2017 16:06:28 +0000 Subject: [PATCH] - Added a new quest preference "Do Not Play AI Matches" which allows the player to decide the outcome of AI vs. AI matches randomly instead of playing them out and thus simulating them. This is disabled by default, set to "1" to enable. - Currently determines the outcome of all AI vs. AI matches in a 50-50 fashion. Might be upgraded later to bias the outcome towards a stronger deck judging by the total card draft rating value. --- .../home/quest/CSubmenuQuestPrefs.java | 5 +++ .../home/quest/VSubmenuQuestPrefs.java | 36 +++++++++++++++- .../forge/screens/quest/QuestPrefsScreen.java | 18 +++++--- .../java/forge/quest/QuestDraftUtils.java | 41 +++++++++++++++++++ .../quest/QuestTournamentController.java | 7 ++++ .../forge/quest/data/QuestPreferences.java | 4 +- 6 files changed, 104 insertions(+), 7 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java index fd844c0ef4d..1f96810630b 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java @@ -84,6 +84,10 @@ public enum CSubmenuQuestPrefs implements ICDoc { view.getLblErrShop().setVisible(true); view.getLblErrShop().setText(s); break; + case DRAFT_TOURNAMENTS: + view.getLblErrDraftTournaments().setVisible(true); + view.getLblErrDraftTournaments().setText(s); + break; default: break; } @@ -99,6 +103,7 @@ public enum CSubmenuQuestPrefs implements ICDoc { view.getLblErrDifficulty().setVisible(false); view.getLblErrRewards().setVisible(false); view.getLblErrShop().setVisible(false); + view.getLblErrDraftTournaments().setVisible(false); } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java index fe988881dff..15b1edca337 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java @@ -52,11 +52,13 @@ public enum VSubmenuQuestPrefs implements IVSubmenu { private final JPanel pnlDifficulty = new JPanel(); private final JPanel pnlBooster = new JPanel(); private final JPanel pnlShop = new JPanel(); + private final JPanel pnlDraftTournaments = new JPanel(); private final FLabel lblErrRewards = new FLabel.Builder().text("Rewards Error").fontStyle(Font.BOLD).build(); private final FLabel lblErrDifficulty = new FLabel.Builder().text("Difficulty Error").fontStyle(Font.BOLD).build(); private final FLabel lblErrBooster = new FLabel.Builder().text("Booster Error").fontStyle(Font.BOLD).build(); private final FLabel lblErrShop = new FLabel.Builder().text("Shop Error").fontStyle(Font.BOLD).build(); + private final FLabel lblErrDraftTournaments = new FLabel.Builder().text("Draft Tournaments Error").fontStyle(Font.BOLD).build(); private final QuestPreferences prefs = FModel.getQuestPreferences(); private PrefInput focusTarget; @@ -66,7 +68,8 @@ public enum VSubmenuQuestPrefs implements IVSubmenu { REWARDS, /** */ DIFFICULTY, /** */ BOOSTER, /** */ - SHOP + SHOP, /***/ + DRAFT_TOURNAMENTS; } /** @@ -82,6 +85,7 @@ public enum VSubmenuQuestPrefs implements IVSubmenu { lblErrDifficulty.setForeground(Color.red); lblErrBooster.setForeground(Color.red); lblErrShop.setForeground(Color.red); + lblErrDraftTournaments.setForeground(Color.red); // Rewards panel final FPanel pnlTitleRewards = new FPanel(); @@ -127,6 +131,17 @@ public enum VSubmenuQuestPrefs implements IVSubmenu { pnlContent.add(pnlTitleShop, "w 96%!, h 36px!, gap 2% 0 10px 10px"); pnlContent.add(pnlShop, "w 96%!, gap 2% 0 10px 20px"); populateShop(); + + // Draft tournaments panel + final FPanel pnlTitleDraftTournaments = new FPanel(); + pnlTitleDraftTournaments.setLayout(new MigLayout("insets 0, align center")); + pnlTitleDraftTournaments.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); + pnlTitleDraftTournaments.add(new FLabel.Builder().text("Draft Tournaments") + .icon(FSkin.getIcon(FSkinProp.ICO_QUEST_COIN)) + .fontSize(16).build(), "h 95%!, gap 0 0 2.5% 0"); + pnlContent.add(pnlTitleDraftTournaments, "w 96%!, h 36px!, gap 2% 0 10px 10px"); + pnlContent.add(pnlDraftTournaments, "w 96%!, gap 2% 0 10px 20px"); + populateDraftTournaments(); } /* (non-Javadoc) @@ -190,6 +205,11 @@ public enum VSubmenuQuestPrefs implements IVSubmenu { return lblErrBooster; } + /** @return {@link javax.swing.JLabel} */ + public JLabel getLblErrDraftTournaments() { + return lblErrDraftTournaments; + } + public void focusFirstTextbox() { focusTarget.requestFocusInWindow(); } @@ -414,6 +434,20 @@ public enum VSubmenuQuestPrefs implements IVSubmenu { } + private void populateDraftTournaments() { + + pnlDraftTournaments.setOpaque(false); + pnlDraftTournaments.setLayout(new MigLayout("insets 0, gap 0, wrap 2, hidemode 3")); + pnlDraftTournaments.removeAll(); + pnlDraftTournaments.add(lblErrDraftTournaments, "w 100%!, h 30px!, span 2 1"); + + FLabel randomAIMatches = new FLabel.Builder().text("Do Not Play AI Matches").fontAlign(SwingConstants.RIGHT).build(); + randomAIMatches.setToolTipText("If set to 1, AI vs. AI matches in draft tournaments will not be played and their outcome will be decided randomly instead."); + pnlDraftTournaments.add(randomAIMatches, labelConstraints); + pnlDraftTournaments.add(new PrefInput(QPref.RANDOMLY_DECIDE_AI_VS_AI, QuestPreferencesErrType.DRAFT_TOURNAMENTS), fieldConstraints); + + } + /** */ @SuppressWarnings("serial") public class PrefInput extends SkinnedTextField { diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java index 1faa00a7ce7..6d8e0946b8b 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestPrefsScreen.java @@ -29,7 +29,8 @@ public class QuestPrefsScreen extends FScreen { DIFFICULTY_EASY, DIFFICULTY_MEDIUM, DIFFICULTY_HARD, - DIFFICULTY_EXPERT + DIFFICULTY_EXPERT, + DRAFT_TOURNAMENTS } private FScrollPane scroller = add(new FScrollPane() { @@ -88,6 +89,10 @@ public class QuestPrefsScreen extends FScreen { scroller.add(new PrefsOption("Playset Size: Basic Lands", QPref.PLAYSET_BASIC_LAND_SIZE, PrefsGroup.SHOP)); scroller.add(new PrefsOption("Playset Size: Any Number", QPref.PLAYSET_ANY_NUMBER_SIZE, PrefsGroup.SHOP)); + //Quest Draft Tournament Preferences + scroller.add(new PrefsHeader("Quest Draft Tournaments", FSkinImage.QUEST_NOTES, PrefsGroup.DIFFICULTY_EXPERT)); + scroller.add(new PrefsOption("Do Not Play AI Matches", QPref.RANDOMLY_DECIDE_AI_VS_AI, PrefsGroup.DRAFT_TOURNAMENTS)); + //Difficulty Adjustments (All) scroller.add(new PrefsHeader("Difficulty Adjustments (All)", FSkinImage.QUEST_NOTES, PrefsGroup.DIFFICULTY_ALL)); //scroller.add(new PrefsOption("Starting basic lands", QPref.STARTING_BASIC_LANDS, PrefsGroup.DIFFICULTY_ALL)); // Add Basic Lands is used instead @@ -95,7 +100,7 @@ public class QuestPrefsScreen extends FScreen { scroller.add(new PrefsOption("Color bias (1-100%)", QPref.STARTING_POOL_COLOR_BIAS, PrefsGroup.DIFFICULTY_ALL)); scroller.add(new PrefsOption("Penalty for loss", QPref.PENALTY_LOSS, PrefsGroup.DIFFICULTY_ALL)); - //Difficult Adjustments (Easy) + //Difficulty Adjustments (Easy) scroller.add(new PrefsHeader("Difficulty Adjustments (Easy)", FSkinImage.QUEST_NOTES, PrefsGroup.DIFFICULTY_EASY)); scroller.add(new PrefsOption("Wins For Booster", QPref.WINS_BOOSTER_EASY, PrefsGroup.DIFFICULTY_EASY)); scroller.add(new PrefsOption("Wins For Rank Increase", QPref.WINS_RANKUP_EASY, PrefsGroup.DIFFICULTY_EASY)); @@ -107,7 +112,7 @@ public class QuestPrefsScreen extends FScreen { scroller.add(new PrefsOption("Starting rares", QPref.STARTING_RARES_EASY, PrefsGroup.DIFFICULTY_EASY)); scroller.add(new PrefsOption("Starting credits", QPref.STARTING_CREDITS_EASY, PrefsGroup.DIFFICULTY_EASY)); - //Difficult Adjustments (Medium) + //Difficulty Adjustments (Medium) scroller.add(new PrefsHeader("Difficulty Adjustments (Medium)", FSkinImage.QUEST_NOTES, PrefsGroup.DIFFICULTY_MEDIUM)); scroller.add(new PrefsOption("Wins For Booster", QPref.WINS_BOOSTER_MEDIUM, PrefsGroup.DIFFICULTY_MEDIUM)); scroller.add(new PrefsOption("Wins For Rank Increase", QPref.WINS_RANKUP_MEDIUM, PrefsGroup.DIFFICULTY_MEDIUM)); @@ -119,7 +124,7 @@ public class QuestPrefsScreen extends FScreen { scroller.add(new PrefsOption("Starting rares", QPref.STARTING_RARES_MEDIUM, PrefsGroup.DIFFICULTY_MEDIUM)); scroller.add(new PrefsOption("Starting credits", QPref.STARTING_CREDITS_MEDIUM, PrefsGroup.DIFFICULTY_MEDIUM)); - //Difficult Adjustments (Hard) + //Difficulty Adjustments (Hard) scroller.add(new PrefsHeader("Difficulty Adjustments (Hard)", FSkinImage.QUEST_NOTES, PrefsGroup.DIFFICULTY_HARD)); scroller.add(new PrefsOption("Wins For Booster", QPref.WINS_BOOSTER_HARD, PrefsGroup.DIFFICULTY_HARD)); scroller.add(new PrefsOption("Wins For Rank Increase", QPref.WINS_RANKUP_HARD, PrefsGroup.DIFFICULTY_HARD)); @@ -131,7 +136,7 @@ public class QuestPrefsScreen extends FScreen { scroller.add(new PrefsOption("Starting rares", QPref.STARTING_RARES_HARD, PrefsGroup.DIFFICULTY_HARD)); scroller.add(new PrefsOption("Starting credits", QPref.STARTING_CREDITS_HARD, PrefsGroup.DIFFICULTY_HARD)); - //Difficult Adjustments (Expert) + //Difficulty Adjustments (Expert) scroller.add(new PrefsHeader("Difficulty Adjustments (Expert)", FSkinImage.QUEST_NOTES, PrefsGroup.DIFFICULTY_EXPERT)); scroller.add(new PrefsOption("Wins For Booster", QPref.WINS_BOOSTER_EXPERT, PrefsGroup.DIFFICULTY_EXPERT)); scroller.add(new PrefsOption("Wins For Rank Increase", QPref.WINS_RANKUP_EXPERT, PrefsGroup.DIFFICULTY_EXPERT)); @@ -214,6 +219,9 @@ public class QuestPrefsScreen extends FScreen { case SHOP: prefType = "Shop Preferences"; break; + case DRAFT_TOURNAMENTS: + prefType = "Draft Tournaments"; + break; default: prefType = "Difficulty Adjustments"; break; diff --git a/forge-gui/src/main/java/forge/quest/QuestDraftUtils.java b/forge-gui/src/main/java/forge/quest/QuestDraftUtils.java index 1517c1d9bbf..cfdd20b5027 100644 --- a/forge-gui/src/main/java/forge/quest/QuestDraftUtils.java +++ b/forge-gui/src/main/java/forge/quest/QuestDraftUtils.java @@ -16,12 +16,15 @@ import forge.match.HostedMatch; import forge.model.FModel; import forge.player.GamePlayerUtil; import forge.properties.ForgePreferences.FPref; +import forge.quest.data.QuestPreferences; import forge.tournament.system.TournamentBracket; import forge.tournament.system.TournamentPairing; import forge.tournament.system.TournamentPlayer; +import forge.util.MyRandom; import forge.util.storage.IStorage; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class QuestDraftUtils { @@ -146,6 +149,11 @@ public class QuestDraftUtils { latestSet--; } + if (latestSet == currentStandings.length - 1) { + // No more matches left + return; + } + //Fill in any missing spots in previous brackets boolean foundMatchups = false; for (int i = 0; i <= latestSet && i <= 14; i += 2) { @@ -262,6 +270,15 @@ public class QuestDraftUtils { gui.enableOverlay(); final DraftMatchup nextMatch = matchups.remove(0); + + if (FModel.getQuestPreferences().getPrefInt(QuestPreferences.QPref.RANDOMLY_DECIDE_AI_VS_AI) == 1) { + // the user asked to decide the AI vs AI match randomly, so just call the UI update and leave the rest to injection code + if (injectRandomMatchOutcome(false)) { + update(gui); + return; + } + } + matchInProgress = true; if (nextMatch.hasHumanPlayer()) { @@ -394,4 +411,28 @@ public class QuestDraftUtils { return humanPlayer != null; } } + + public static boolean injectRandomMatchOutcome(boolean simHumanMatches) { + QuestEventDraft qd = FModel.getQuest().getAchievements().getCurrentDraft(); + + int pos = Arrays.asList(qd.getStandings()).indexOf(QuestEventDraft.UNDETERMINED); + int offset = (pos - 8) * 2; + + String sid1 = qd.getStandings()[offset]; + String sid2 = qd.getStandings()[offset + 1]; + + if (sid1.equals(QuestEventDraft.HUMAN) || sid2.equals(QuestEventDraft.HUMAN)) { + if (!simHumanMatches) { + return false; + } + } + + // TODO: bias the outcome towards a deck with higher total card draft rating value instead of going 50-50 + boolean randomWinner = MyRandom.getRandom().nextBoolean(); + qd.getStandings()[pos] = randomWinner ? sid1 : sid2; + + FModel.getQuest().save(); + + return true; + } } diff --git a/forge-gui/src/main/java/forge/quest/QuestTournamentController.java b/forge-gui/src/main/java/forge/quest/QuestTournamentController.java index 43301815706..38d847882af 100644 --- a/forge-gui/src/main/java/forge/quest/QuestTournamentController.java +++ b/forge-gui/src/main/java/forge/quest/QuestTournamentController.java @@ -19,6 +19,7 @@ import forge.properties.ForgePreferences.FPref; import forge.quest.QuestDraftUtils.Mode; import forge.quest.QuestEventDraft.QuestDraftFormat; import forge.quest.data.QuestAchievements; +import forge.quest.data.QuestPreferences; import forge.tournament.system.TournamentBracket; import forge.tournament.system.TournamentPairing; import forge.tournament.system.TournamentPlayer; @@ -459,5 +460,11 @@ public class QuestTournamentController { gui = GuiBase.getInterface().getNewGuiGame(); QuestDraftUtils.startNextMatch(gui); + + if (FModel.getQuestPreferences().getPrefInt(QuestPreferences.QPref.RANDOMLY_DECIDE_AI_VS_AI) == 1) { + // need to force a view update after a random match outcome was injected into standings + view.populate(); + update(); + } } } diff --git a/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java b/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java index 0103672b461..8976a3bc421 100644 --- a/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java +++ b/forge-gui/src/main/java/forge/quest/data/QuestPreferences.java @@ -168,7 +168,9 @@ public class QuestPreferences extends PreferencesStore i PLAYSET_ANY_NUMBER_SIZE("500"), PLAYSET_BASIC_LAND_SIZE("50"), - ITEM_LEVEL_RESTRICTION("1"); + ITEM_LEVEL_RESTRICTION("1"), + + RANDOMLY_DECIDE_AI_VS_AI("0"); private final String strDefaultVal;