From e0c858a3d6852595e2dda3784598c59ae0b9b6f9 Mon Sep 17 00:00:00 2001 From: friarsol Date: Sat, 14 Dec 2019 22:21:23 -0500 Subject: [PATCH 1/4] Only split the first colon from Puzzle metadata --- forge-gui/src/main/java/forge/puzzle/Puzzle.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/src/main/java/forge/puzzle/Puzzle.java b/forge-gui/src/main/java/forge/puzzle/Puzzle.java index 39904881b7e..306866f538f 100644 --- a/forge-gui/src/main/java/forge/puzzle/Puzzle.java +++ b/forge-gui/src/main/java/forge/puzzle/Puzzle.java @@ -36,7 +36,7 @@ public class Puzzle extends GameState implements InventoryItem, Comparable metadataLines) { for(String line : metadataLines) { - String[] split = line.split(":"); + String[] split = line.split(":", 2); if ("Name".equalsIgnoreCase(split[0])) { this.name = split[1].trim(); } else if ("Goal".equalsIgnoreCase(split[0])) { From b05dc40a1c3fb8c23729bd4c491f234130452d8b Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 17 Dec 2019 17:50:25 +0300 Subject: [PATCH 2/4] - Added puzzle PS_ELD9. --- forge-gui/res/puzzle/PS_ELD9.pzl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 forge-gui/res/puzzle/PS_ELD9.pzl diff --git a/forge-gui/res/puzzle/PS_ELD9.pzl b/forge-gui/res/puzzle/PS_ELD9.pzl new file mode 100644 index 00000000000..db68e856968 --- /dev/null +++ b/forge-gui/res/puzzle/PS_ELD9.pzl @@ -0,0 +1,21 @@ +[metadata] +Name:Possibility Storm - Throne of Eldraine #09 +URL:http://www.possibilitystorm.com/wp-content/uploads/2019/12/140.-ELD9-1-scaled.jpg +Goal:Win +Turns:1 +Difficulty:Mythic +Description:Win this turn. Your opponent has a Hypnotic Sprite in their hand. Assume they have {2}{U}{U}{U} available. You have not yet played a land this turn. The solution must satisfy all possible opponent's choices. Your opponent's Kenrith, the Returned King is a 3/3 Elk. Both graveyards start empty. Thicket Crasher currently has -2/-0 from Mu Yanling's first loyalty ability. +[state] +humanlife=20 +ailife=13 +humanlandsplayed=0 +turn=1 +activeplayer=human +activephase=MAIN1 +humanhand=Storm the Citadel;Claim the Firstborn;Embercleave;Searing Barrage;Tuinvale Treefolk;Giant Opportunity;Gingerbread Cabin;Bond of Passion +humanbattlefield=Sunder Shaman|Tapped;Thicket Crasher|Id:2;Lucky Clover;Cloudkin Seer;Oko, Thief of Crowns|Counters:LOYALTY=5;Fresh-Faced Recruit;Stomping Ground|NoETBTrigs;Stomping Ground|NoETBTrigs;Stomping Ground|NoETBTrigs;Stomping Ground|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs +aihand=Hypnotic Sprite +aibattlefield=Mu Yanling, Sky Dancer|Counters:LOYALTY=4;Vivien, Champion of the Wilds|Counters:LOYALTY=4;Hypnotic Sprite;Kenrith, the Returned King|Id:1;Sphinx of the Guildpact;Pattern Matcher +aipersistentmana=C C U U U U +humanprecast=Oko, Thief of Crowns:2->1 +aiprecast=Mu Yanling, Sky Dancer:1->2 From 50e0387cda9b047b0110aa05ac03cfe54eef8e30 Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 17 Dec 2019 17:52:17 +0300 Subject: [PATCH 3/4] - Fix AI persistent mana in PS_ELD9. --- forge-gui/res/puzzle/PS_ELD9.pzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/puzzle/PS_ELD9.pzl b/forge-gui/res/puzzle/PS_ELD9.pzl index db68e856968..00fd396bd8a 100644 --- a/forge-gui/res/puzzle/PS_ELD9.pzl +++ b/forge-gui/res/puzzle/PS_ELD9.pzl @@ -16,6 +16,6 @@ humanhand=Storm the Citadel;Claim the Firstborn;Embercleave;Searing Barrage;Tuin humanbattlefield=Sunder Shaman|Tapped;Thicket Crasher|Id:2;Lucky Clover;Cloudkin Seer;Oko, Thief of Crowns|Counters:LOYALTY=5;Fresh-Faced Recruit;Stomping Ground|NoETBTrigs;Stomping Ground|NoETBTrigs;Stomping Ground|NoETBTrigs;Stomping Ground|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs aihand=Hypnotic Sprite aibattlefield=Mu Yanling, Sky Dancer|Counters:LOYALTY=4;Vivien, Champion of the Wilds|Counters:LOYALTY=4;Hypnotic Sprite;Kenrith, the Returned King|Id:1;Sphinx of the Guildpact;Pattern Matcher -aipersistentmana=C C U U U U +aipersistentmana=C C U U U humanprecast=Oko, Thief of Crowns:2->1 aiprecast=Mu Yanling, Sky Dancer:1->2 From d63106a71af2f6d243df7dfe979e6310ce59db00 Mon Sep 17 00:00:00 2001 From: friarsol Date: Tue, 17 Dec 2019 21:16:17 -0500 Subject: [PATCH 4/4] Save completed puzzles, and sort them to the bottom of the screen --- .../home/puzzle/CSubmenuPuzzleSolve.java | 7 +++ .../main/java/forge/match/HostedMatch.java | 6 +++ .../java/forge/properties/ForgeConstants.java | 1 + .../src/main/java/forge/puzzle/Puzzle.java | 54 +++++++++++++++++-- .../src/main/java/forge/puzzle/PuzzleIO.java | 10 +++- 5 files changed, 73 insertions(+), 5 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/puzzle/CSubmenuPuzzleSolve.java b/forge-gui-desktop/src/main/java/forge/screens/home/puzzle/CSubmenuPuzzleSolve.java index 29d2ea6db9c..ce3e75a2ee2 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/puzzle/CSubmenuPuzzleSolve.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/puzzle/CSubmenuPuzzleSolve.java @@ -96,6 +96,13 @@ public enum CSubmenuPuzzleSolve implements ICDoc, IMenuProvider { } }); + hostedMatch.setEndGameHook((new Runnable() { + @Override + public void run() { + selected.savePuzzleSolve(hostedMatch.getGame().getOutcome().isWinner(GamePlayerUtil.getGuiPlayer())); + } + })); + final List players = new ArrayList<>(); final RegisteredPlayer human = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.getGuiPlayer()); human.setStartingHand(0); diff --git a/forge-gui/src/main/java/forge/match/HostedMatch.java b/forge-gui/src/main/java/forge/match/HostedMatch.java index 4c71ebea9ce..f939c97e874 100644 --- a/forge-gui/src/main/java/forge/match/HostedMatch.java +++ b/forge-gui/src/main/java/forge/match/HostedMatch.java @@ -60,6 +60,7 @@ public class HostedMatch { private String title; public HashMap gameControllers = null; private Runnable startGameHook = null; + private Runnable endGameHook = null; private final List humanControllers = Lists.newArrayList(); private Map guis; private int humanCount; @@ -73,6 +74,7 @@ public class HostedMatch { public void setStartGameHook(Runnable hook) { startGameHook = hook; } + public void setEndGameHook(Runnable hook) { endGameHook = hook; } private static GameRules getDefaultRules(final GameType gameType) { final GameRules gameRules = new GameRules(gameType); @@ -241,6 +243,10 @@ public class HostedMatch { } // Actually start the game! match.startGame(game, startGameHook); + // this function waits? + if (endGameHook != null){ + endGameHook.run(); + } // After game is over... isMatchOver = match.isMatchOver(); diff --git a/forge-gui/src/main/java/forge/properties/ForgeConstants.java b/forge-gui/src/main/java/forge/properties/ForgeConstants.java index ec4be9400c4..63d3894158a 100644 --- a/forge-gui/src/main/java/forge/properties/ForgeConstants.java +++ b/forge-gui/src/main/java/forge/properties/ForgeConstants.java @@ -214,6 +214,7 @@ public final class ForgeConstants { public static final String USER_PREFS_DIR = USER_DIR + "preferences" + PATH_SEPARATOR; public static final String USER_GAMES_DIR = USER_DIR + "games" + PATH_SEPARATOR; public static final String USER_FORMATS_DIR = USER_DIR + "customformats" + PATH_SEPARATOR; + public static final String USER_PUZZLE_DIR = USER_DIR + "puzzle" + PATH_SEPARATOR; public static final String LOG_FILE = USER_DIR + "forge.log"; public static final String ACHIEVEMENTS_DIR = USER_DIR + "achievements" + PATH_SEPARATOR; public static final String DECK_DRAFT_DIR = DECK_BASE_DIR + "draft" + PATH_SEPARATOR; diff --git a/forge-gui/src/main/java/forge/puzzle/Puzzle.java b/forge-gui/src/main/java/forge/puzzle/Puzzle.java index 306866f538f..7a8375b5450 100644 --- a/forge-gui/src/main/java/forge/puzzle/Puzzle.java +++ b/forge-gui/src/main/java/forge/puzzle/Puzzle.java @@ -14,12 +14,16 @@ import forge.game.zone.ZoneType; import forge.item.IPaperCard; import forge.item.InventoryItem; import forge.model.FModel; +import forge.properties.ForgeConstants; +import java.io.File; +import java.io.IOException; import java.util.List; import java.util.Map; public class Puzzle extends GameState implements InventoryItem, Comparable { String name; + String filename; String goal; String url; String difficulty; @@ -27,11 +31,18 @@ public class Puzzle extends GameState implements InventoryItem, Comparable> puzzleLines) { + this(puzzleLines, "", false); + } + + public Puzzle(Map> puzzleLines, String filename, boolean completed) { loadMetaData(puzzleLines.get("metadata")); loadGameState(puzzleLines.get("state")); // Generate goal enforcement + this.filename = filename; + this.completed = completed; } private void loadMetaData(List metadataLines) { @@ -215,13 +226,50 @@ public class Puzzle extends GameState implements InventoryItem, Comparable loadPuzzles() { String[] pList; @@ -33,13 +34,18 @@ public class PuzzleIO { for (final String element : pList) { if (element.endsWith(SUFFIX_DATA)) { final List pfData = FileUtil.readFile(ForgeConstants.PUZZLE_DIR + element); - puzzles.add(new Puzzle(parsePuzzleSections(pfData))); + + String filename = element.replace(SUFFIX_DATA, ""); + boolean completed = FileUtil.doesFileExist(ForgeConstants.USER_PUZZLE_DIR + element.replace(SUFFIX_DATA, SUFFIX_COMPLETE)); + + // Pass file name into Puzzle so it can save the completed name to match + puzzles.add(new Puzzle(parsePuzzleSections(pfData), filename, completed)); } } return puzzles; } - public static final Map> parsePuzzleSections(List pfData) { + public static Map> parsePuzzleSections(List pfData) { return FileSection.parseSections(pfData); }