mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -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<RegisteredPlayer> players = new ArrayList<>();
|
final List<RegisteredPlayer> players = new ArrayList<>();
|
||||||
final RegisteredPlayer human = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
final RegisteredPlayer human = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||||
human.setStartingHand(0);
|
human.setStartingHand(0);
|
||||||
|
|||||||
21
forge-gui/res/puzzle/PS_ELD9.pzl
Normal file
21
forge-gui/res/puzzle/PS_ELD9.pzl
Normal file
@@ -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
|
||||||
|
humanprecast=Oko, Thief of Crowns:2->1
|
||||||
|
aiprecast=Mu Yanling, Sky Dancer:1->2
|
||||||
@@ -60,6 +60,7 @@ public class HostedMatch {
|
|||||||
private String title;
|
private String title;
|
||||||
public HashMap<LobbySlot, IGameController> gameControllers = null;
|
public HashMap<LobbySlot, IGameController> gameControllers = null;
|
||||||
private Runnable startGameHook = null;
|
private Runnable startGameHook = null;
|
||||||
|
private Runnable endGameHook = null;
|
||||||
private final List<PlayerControllerHuman> humanControllers = Lists.newArrayList();
|
private final List<PlayerControllerHuman> humanControllers = Lists.newArrayList();
|
||||||
private Map<RegisteredPlayer, IGuiGame> guis;
|
private Map<RegisteredPlayer, IGuiGame> guis;
|
||||||
private int humanCount;
|
private int humanCount;
|
||||||
@@ -73,6 +74,7 @@ public class HostedMatch {
|
|||||||
public void setStartGameHook(Runnable hook) {
|
public void setStartGameHook(Runnable hook) {
|
||||||
startGameHook = hook;
|
startGameHook = hook;
|
||||||
}
|
}
|
||||||
|
public void setEndGameHook(Runnable hook) { endGameHook = hook; }
|
||||||
|
|
||||||
private static GameRules getDefaultRules(final GameType gameType) {
|
private static GameRules getDefaultRules(final GameType gameType) {
|
||||||
final GameRules gameRules = new GameRules(gameType);
|
final GameRules gameRules = new GameRules(gameType);
|
||||||
@@ -241,6 +243,10 @@ public class HostedMatch {
|
|||||||
}
|
}
|
||||||
// Actually start the game!
|
// Actually start the game!
|
||||||
match.startGame(game, startGameHook);
|
match.startGame(game, startGameHook);
|
||||||
|
// this function waits?
|
||||||
|
if (endGameHook != null){
|
||||||
|
endGameHook.run();
|
||||||
|
}
|
||||||
|
|
||||||
// After game is over...
|
// After game is over...
|
||||||
isMatchOver = match.isMatchOver();
|
isMatchOver = match.isMatchOver();
|
||||||
|
|||||||
@@ -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_PREFS_DIR = USER_DIR + "preferences" + PATH_SEPARATOR;
|
||||||
public static final String USER_GAMES_DIR = USER_DIR + "games" + 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_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 LOG_FILE = USER_DIR + "forge.log";
|
||||||
public static final String ACHIEVEMENTS_DIR = USER_DIR + "achievements" + PATH_SEPARATOR;
|
public static final String ACHIEVEMENTS_DIR = USER_DIR + "achievements" + PATH_SEPARATOR;
|
||||||
public static final String DECK_DRAFT_DIR = DECK_BASE_DIR + "draft" + PATH_SEPARATOR;
|
public static final String DECK_DRAFT_DIR = DECK_BASE_DIR + "draft" + PATH_SEPARATOR;
|
||||||
|
|||||||
@@ -14,12 +14,16 @@ import forge.game.zone.ZoneType;
|
|||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.item.InventoryItem;
|
import forge.item.InventoryItem;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
|
import forge.properties.ForgeConstants;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class Puzzle extends GameState implements InventoryItem, Comparable<Puzzle> {
|
public class Puzzle extends GameState implements InventoryItem, Comparable<Puzzle> {
|
||||||
String name;
|
String name;
|
||||||
|
String filename;
|
||||||
String goal;
|
String goal;
|
||||||
String url;
|
String url;
|
||||||
String difficulty;
|
String difficulty;
|
||||||
@@ -27,16 +31,23 @@ public class Puzzle extends GameState implements InventoryItem, Comparable<Puzzl
|
|||||||
String targets;
|
String targets;
|
||||||
int targetCount = 1;
|
int targetCount = 1;
|
||||||
int turns;
|
int turns;
|
||||||
|
boolean completed;
|
||||||
|
|
||||||
public Puzzle(Map<String, List<String>> puzzleLines) {
|
public Puzzle(Map<String, List<String>> puzzleLines) {
|
||||||
|
this(puzzleLines, "", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Puzzle(Map<String, List<String>> puzzleLines, String filename, boolean completed) {
|
||||||
loadMetaData(puzzleLines.get("metadata"));
|
loadMetaData(puzzleLines.get("metadata"));
|
||||||
loadGameState(puzzleLines.get("state"));
|
loadGameState(puzzleLines.get("state"));
|
||||||
// Generate goal enforcement
|
// Generate goal enforcement
|
||||||
|
this.filename = filename;
|
||||||
|
this.completed = completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadMetaData(List<String> metadataLines) {
|
private void loadMetaData(List<String> metadataLines) {
|
||||||
for(String line : metadataLines) {
|
for(String line : metadataLines) {
|
||||||
String[] split = line.split(":");
|
String[] split = line.split(":", 2);
|
||||||
if ("Name".equalsIgnoreCase(split[0])) {
|
if ("Name".equalsIgnoreCase(split[0])) {
|
||||||
this.name = split[1].trim();
|
this.name = split[1].trim();
|
||||||
} else if ("Goal".equalsIgnoreCase(split[0])) {
|
} else if ("Goal".equalsIgnoreCase(split[0])) {
|
||||||
@@ -215,13 +226,50 @@ public class Puzzle extends GameState implements InventoryItem, Comparable<Puzzl
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() { return name; }
|
public boolean getCompleted() { return completed; }
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (this.completed) {
|
||||||
|
sb.append("[COMPLETED] ");
|
||||||
|
}
|
||||||
|
sb.append(name);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public int compareTo(Puzzle pzl) throws ClassCastException {
|
public int compareTo(Puzzle pzl) throws ClassCastException {
|
||||||
if (!(pzl instanceof Puzzle)) {
|
if (!(pzl instanceof Puzzle)) {
|
||||||
throw new ClassCastException("Tried to compare a Puzzle object to a non-Puzzle object.");
|
throw new ClassCastException("Tried to compare a Puzzle object to a non-Puzzle object.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return getName().compareTo(pzl.getName());
|
if (this.completed == pzl.getCompleted()) {
|
||||||
|
return getName().compareTo(pzl.getName());
|
||||||
|
} else if (this.completed) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean savePuzzleSolve(final boolean completed) {
|
||||||
|
if (!completed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
File directory = new File(ForgeConstants.USER_PUZZLE_DIR);
|
||||||
|
if (!directory.exists()) {
|
||||||
|
directory.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
File store = new File(ForgeConstants.USER_PUZZLE_DIR, filename + PuzzleIO.SUFFIX_COMPLETE);
|
||||||
|
if (!store.exists()) {
|
||||||
|
try {
|
||||||
|
store.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
this.completed = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ public class PuzzleIO {
|
|||||||
|
|
||||||
public static final String TXF_PROMPT = "[New Puzzle]";
|
public static final String TXF_PROMPT = "[New Puzzle]";
|
||||||
public static final String SUFFIX_DATA = ".pzl";
|
public static final String SUFFIX_DATA = ".pzl";
|
||||||
|
public static final String SUFFIX_COMPLETE = ".complete";
|
||||||
|
|
||||||
public static ArrayList<Puzzle> loadPuzzles() {
|
public static ArrayList<Puzzle> loadPuzzles() {
|
||||||
String[] pList;
|
String[] pList;
|
||||||
@@ -33,13 +34,18 @@ public class PuzzleIO {
|
|||||||
for (final String element : pList) {
|
for (final String element : pList) {
|
||||||
if (element.endsWith(SUFFIX_DATA)) {
|
if (element.endsWith(SUFFIX_DATA)) {
|
||||||
final List<String> pfData = FileUtil.readFile(ForgeConstants.PUZZLE_DIR + element);
|
final List<String> 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;
|
return puzzles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Map<String, List<String>> parsePuzzleSections(List<String> pfData) {
|
public static Map<String, List<String>> parsePuzzleSections(List<String> pfData) {
|
||||||
return FileSection.parseSections(pfData);
|
return FileSection.parseSections(pfData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user