Initial checkin for Puzzle Mode

This commit is contained in:
Sol
2017-04-08 15:17:07 +00:00
parent 5592139454
commit 836ebdc5e6
27 changed files with 908 additions and 90 deletions

View File

@@ -54,6 +54,7 @@ public class HostedMatch {
private Match match;
private Game game;
private String title;
private Runnable startGameHook = null;
private final List<PlayerControllerHuman> humanControllers = Lists.newArrayList();
private Map<RegisteredPlayer, IGuiGame> guis;
private int humanCount;
@@ -62,7 +63,10 @@ public class HostedMatch {
private final Map<PlayerControllerHuman, NextGameDecision> nextGameDecisions = Maps.newHashMap();
private boolean isMatchOver = false;
public HostedMatch() {
public HostedMatch() {}
public void setStartGameHook(Runnable hook) {
startGameHook = hook;
}
private static GameRules getDefaultRules(final GameType gameType) {
@@ -216,9 +220,8 @@ public class HostedMatch {
playbackControl.setGame(game);
game.subscribeToEvents(playbackControl);
}
// Actually start the game!
match.startGame(game);
match.startGame(game, startGameHook);
// After game is over...
isMatchOver = match.isMatchOver();

View File

@@ -62,6 +62,8 @@ public final class ForgeConstants {
public static final String MUSIC_DIR = RES_DIR + "music" + PATH_SEPARATOR;
public static final String LANG_DIR = RES_DIR + "languages" + PATH_SEPARATOR;
public static final String EFFECTS_DIR = RES_DIR + "effects" + PATH_SEPARATOR;
public static final String PUZZLE_DIR = RES_DIR + "puzzle" + PATH_SEPARATOR;
private static final String QUEST_DIR = RES_DIR + "quest" + PATH_SEPARATOR;
public static final String QUEST_WORLD_DIR = QUEST_DIR + "world" + PATH_SEPARATOR;

View File

@@ -108,6 +108,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
SUBMENU_ONLINE ("false"),
SUBMENU_GAUNTLET ("false"),
SUBMENU_QUEST ("false"),
SUBMENU_PUZZLE("false"),
SUBMENU_SETTINGS ("false"),
SUBMENU_UTILITIES ("false"),

View File

@@ -0,0 +1,104 @@
package forge.puzzle;
import forge.ai.GameState;
import forge.game.Game;
import forge.game.ability.AbilityFactory;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerHandler;
import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType;
import forge.item.IPaperCard;
import forge.item.InventoryItem;
import forge.model.FModel;
import java.util.List;
import java.util.Map;
public class Puzzle extends GameState implements InventoryItem {
String name;
String goal;
String url;
int turns;
public Puzzle(Map<String, List<String>> puzzleLines) {
loadMetaData(puzzleLines.get("metadata"));
loadGameState(puzzleLines.get("state"));
// Generate goal enforcement
}
private void loadMetaData(List<String> metadataLines) {
for(String line : metadataLines) {
String[] split = line.split(":");
if ("Name".equalsIgnoreCase(split[0])) {
this.name = split[1];
} else if ("Goal".equalsIgnoreCase(split[0])) {
this.goal = split[1];
} else if ("Url".equalsIgnoreCase(split[0])) {
this.url = split[1];
} else if ("Turns".equalsIgnoreCase(split[0])) {
this.turns = Integer.parseInt(split[1]);
}
}
}
private void loadGameState(List<String> stateLines) {
this.parse(stateLines);
}
public IPaperCard getPaperCard(final String cardName) {
return FModel.getMagicDb().getCommonCards().getCard(cardName);
}
public void addGoalEnforcement(Game game) {
Player human = null;
for(Player p : game.getPlayers()) {
if (p.getController().isGuiPlayer()) {
human = p;
}
}
Card goalCard = new Card(-1, game);
goalCard.setOwner(human);
goalCard.setImageKey("t:puzzle");
goalCard.setName("Puzzle Goal");
goalCard.addType("Effect");
{
final String loseTrig = "Mode$ Phase | Phase$ Cleanup | TriggerZones$ Command | Static$ True | " +
"ValidPlayer$ You | TriggerDescription$ At the beginning of your cleanup step, you lose the game.";
final String loseEff = "DB$ LosesGame | Defined$ You";
final Trigger loseTrigger = TriggerHandler.parseTrigger(loseTrig, goalCard, true);
loseTrigger.setOverridingAbility(AbilityFactory.getAbility(loseEff, goalCard));
goalCard.addTrigger(loseTrigger);
}
human.getZone(ZoneType.Command).add(goalCard);
}
@Override
protected void applyGameOnThread(final Game game) {
super.applyGameOnThread(game);
addGoalEnforcement(game);
}
@Override
public String getItemType() {
return "Puzzle";
}
@Override
public String getImageKey(boolean altState) {
return null;
}
@Override
public String getName() {
return name;
}
public String toString() { return name; }
}

View File

@@ -0,0 +1,50 @@
package forge.puzzle;
import com.google.common.collect.Lists;
import forge.properties.ForgeConstants;
import forge.util.FileSection;
import forge.util.FileUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class PuzzleIO {
public static final String TXF_PROMPT = "[New Puzzle]";
public static final String SUFFIX_DATA = ".pzl";
public static ArrayList<Puzzle> loadPuzzles() {
String[] pList;
// get list of custom draft files
final File pFolder = new File(ForgeConstants.PUZZLE_DIR);
if (!pFolder.exists()) {
throw new RuntimeException("Puzzles : folder not found -- folder is " + pFolder.getAbsolutePath());
}
if (!pFolder.isDirectory()) {
throw new RuntimeException("Puzzles : not a folder -- " + pFolder.getAbsolutePath());
}
pList = pFolder.list();
ArrayList<Puzzle> puzzles = Lists.newArrayList();
for (final String element : pList) {
if (element.endsWith(SUFFIX_DATA)) {
final List<String> pfData = FileUtil.readFile(ForgeConstants.PUZZLE_DIR + element);
puzzles.add(new Puzzle(parsePuzzleSections(pfData)));
}
}
return puzzles;
}
public static final Map<String, List<String>> parsePuzzleSections(List<String> pfData) {
return FileSection.parseSections(pfData);
}
public static File getPuzzleFile(final String name) {
return new File(ForgeConstants.PUZZLE_DIR, name + SUFFIX_DATA);
}
}