diff options
author | Joffrey Bion <joffrey.bion@amadeus.com> | 2018-07-05 19:11:15 +0200 |
---|---|---|
committer | Joffrey Bion <joffrey.bion@amadeus.com> | 2018-07-06 14:17:18 +0200 |
commit | 8aa317a8b236896f2a0b2037a99feb6977ac0881 (patch) | |
tree | 4b2e8d7c85ab6d2f1593cb9cf1c7f8bd51b063dd | |
parent | Kotlin mig: api package (diff) | |
download | seven-wonders-8aa317a8b236896f2a0b2037a99feb6977ac0881.tar.gz seven-wonders-8aa317a8b236896f2a0b2037a99feb6977ac0881.tar.bz2 seven-wonders-8aa317a8b236896f2a0b2037a99feb6977ac0881.zip |
Kotlin mig: game definitions
43 files changed, 633 insertions, 850 deletions
diff --git a/backend/src/test/java/org/luxons/sevenwonders/controllers/LobbyControllerTest.java b/backend/src/test/java/org/luxons/sevenwonders/controllers/LobbyControllerTest.java index 567cd654..2da7e3c1 100644 --- a/backend/src/test/java/org/luxons/sevenwonders/controllers/LobbyControllerTest.java +++ b/backend/src/test/java/org/luxons/sevenwonders/controllers/LobbyControllerTest.java @@ -27,7 +27,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; -import static org.luxons.sevenwonders.game.data.definitions.WonderSidePickMethod.ALL_A; +import static org.luxons.sevenwonders.game.data.WonderSidePickMethod.ALL_A; public class LobbyControllerTest { diff --git a/game-engine/build.gradle b/game-engine/build.gradle index 5a3cc4ea..97067176 100644 --- a/game-engine/build.gradle +++ b/game-engine/build.gradle @@ -16,11 +16,11 @@ configurations { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - implementation 'com.google.code.gson:gson:2.8.0' + implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' + implementation 'com.github.salomonbrys.kotson:kotson:2.5.0' testImplementation 'junit:junit:4.12' - checkstyleConfig "org.hildan.checkstyle:checkstyle-config:2.1.0" - ktlint "com.github.shyiko:ktlint:0.24.0" + checkstyleConfig 'org.hildan.checkstyle:checkstyle-config:2.1.0' + ktlint 'com.github.shyiko:ktlint:0.24.0' } checkstyle { diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java deleted file mode 100644 index 0402a26d..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.luxons.sevenwonders.game.data; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.luxons.sevenwonders.game.Game; -import org.luxons.sevenwonders.game.Settings; -import org.luxons.sevenwonders.game.api.CustomizableSettings; -import org.luxons.sevenwonders.game.boards.Board; -import org.luxons.sevenwonders.game.cards.Decks; -import org.luxons.sevenwonders.game.data.definitions.DecksDefinition; -import org.luxons.sevenwonders.game.data.definitions.WonderDefinition; -import org.luxons.sevenwonders.game.wonders.Wonder; - -public class GameDefinition { - - private final GlobalRules rules; - - private final WonderDefinition[] wonders; - - private final DecksDefinition decksDefinition; - - GameDefinition(GlobalRules rules, WonderDefinition[] wonders, DecksDefinition decksDefinition) { - this.rules = rules; - this.wonders = wonders; - this.decksDefinition = decksDefinition; - } - - public int getMinPlayers() { - return rules.getMinPlayers(); - } - - public int getMaxPlayers() { - return rules.getMaxPlayers(); - } - - public Game initGame(long id, CustomizableSettings customSettings, int nbPlayers) { - Settings settings = new Settings(nbPlayers, customSettings); - List<Board> boards = assignBoards(settings, nbPlayers); - Decks decks = decksDefinition.create(settings); - return new Game(id, settings, nbPlayers, boards, decks); - } - - private List<Board> assignBoards(Settings settings, int nbPlayers) { - List<WonderDefinition> randomizedWonders = Arrays.asList(wonders); - Collections.shuffle(randomizedWonders, settings.getRandom()); - - List<Board> boards = new ArrayList<>(nbPlayers); - for (int i = 0; i < nbPlayers; i++) { - WonderDefinition def = randomizedWonders.get(i); - Wonder w = def.create(settings); - Board b = new Board(w, i, settings); - boards.add(b); - } - return boards; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/GameDefinitionLoader.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/GameDefinitionLoader.java deleted file mode 100644 index a1bd7b8d..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/GameDefinitionLoader.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.luxons.sevenwonders.game.data; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.lang.reflect.Type; -import java.util.List; - -import org.luxons.sevenwonders.game.data.definitions.DecksDefinition; -import org.luxons.sevenwonders.game.data.definitions.WonderDefinition; -import org.luxons.sevenwonders.game.data.serializers.NumericEffectSerializer; -import org.luxons.sevenwonders.game.data.serializers.ProductionIncreaseSerializer; -import org.luxons.sevenwonders.game.data.serializers.ProductionSerializer; -import org.luxons.sevenwonders.game.data.serializers.ResourceTypeSerializer; -import org.luxons.sevenwonders.game.data.serializers.ResourceTypesSerializer; -import org.luxons.sevenwonders.game.data.serializers.ResourcesSerializer; -import org.luxons.sevenwonders.game.data.serializers.ScienceProgressSerializer; -import org.luxons.sevenwonders.game.effects.GoldIncrease; -import org.luxons.sevenwonders.game.effects.MilitaryReinforcements; -import org.luxons.sevenwonders.game.effects.ProductionIncrease; -import org.luxons.sevenwonders.game.effects.RawPointsIncrease; -import org.luxons.sevenwonders.game.effects.ScienceProgress; -import org.luxons.sevenwonders.game.resources.Production; -import org.luxons.sevenwonders.game.resources.ResourceType; -import org.luxons.sevenwonders.game.resources.Resources; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; - -public class GameDefinitionLoader { - - private static final String BASE_PACKAGE = GameDefinitionLoader.class.getPackage().getName(); - - private static final String BASE_PACKAGE_PATH = '/' + BASE_PACKAGE.replace('.', '/'); - - private static final String GLOBAL_RULES_FILE = "global_rules.json"; - - private static final String CARDS_FILE = "cards.json"; - - private static final String WONDERS_FILE = "wonders.json"; - - private final GameDefinition gameDefinition; - - public GameDefinitionLoader() { - gameDefinition = load(); - } - - public GameDefinition getGameDefinition() { - return gameDefinition; - } - - private static GameDefinition load() { - return new GameDefinition(loadGlobalRules(), loadWonders(), loadDecks()); - } - - private static GlobalRules loadGlobalRules() { - return readJsonFile(GLOBAL_RULES_FILE, GlobalRules.class); - } - - private static WonderDefinition[] loadWonders() { - return readJsonFile(WONDERS_FILE, WonderDefinition[].class); - } - - private static DecksDefinition loadDecks() { - return readJsonFile(CARDS_FILE, DecksDefinition.class); - } - - private static <T> T readJsonFile(String filename, Class<T> clazz) { - InputStream in = GameDefinitionLoader.class.getResourceAsStream(BASE_PACKAGE_PATH + '/' + filename); - Reader reader = new BufferedReader(new InputStreamReader(in)); - Gson gson = createGson(); - return gson.fromJson(reader, clazz); - } - - private static Gson createGson() { - Type resourceTypeList = new TypeToken<List<ResourceType>>() {}.getType(); - return new GsonBuilder().disableHtmlEscaping() - .registerTypeAdapter(Resources.class, new ResourcesSerializer()) - .registerTypeAdapter(ResourceType.class, new ResourceTypeSerializer()) - .registerTypeAdapter(resourceTypeList, new ResourceTypesSerializer()) - .registerTypeAdapter(Production.class, new ProductionSerializer()) - .registerTypeAdapter(ProductionIncrease.class, new ProductionIncreaseSerializer()) - .registerTypeAdapter(MilitaryReinforcements.class, new NumericEffectSerializer()) - .registerTypeAdapter(RawPointsIncrease.class, new NumericEffectSerializer()) - .registerTypeAdapter(GoldIncrease.class, new NumericEffectSerializer()) - .registerTypeAdapter(ScienceProgress.class, new ScienceProgressSerializer()) - .create(); - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/GlobalRules.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/GlobalRules.java deleted file mode 100644 index 526bebad..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/GlobalRules.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.luxons.sevenwonders.game.data; - -@SuppressWarnings("unused") // fields are set by Gson -class GlobalRules { - - private int minPlayers; - - private int maxPlayers; - - int getMinPlayers() { - return minPlayers; - } - - int getMaxPlayers() { - return maxPlayers; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/CardDefinition.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/CardDefinition.java deleted file mode 100644 index 621bed2c..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/CardDefinition.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.luxons.sevenwonders.game.data.definitions; - -import java.util.List; -import java.util.Map; - -import org.luxons.sevenwonders.game.Settings; -import org.luxons.sevenwonders.game.cards.Card; -import org.luxons.sevenwonders.game.cards.Color; -import org.luxons.sevenwonders.game.cards.Requirements; - -@SuppressWarnings("unused") // the fields are injected by Gson -public class CardDefinition implements Definition<Card> { - - private String name; - - private Color color; - - private Requirements requirements; - - private EffectsDefinition effect; - - private String chainParent; - - private List<String> chainChildren; - - private Map<Integer, Integer> countPerNbPlayer; - - private String image; - - @Override - public Card create(Settings settings) { - return new Card(name, color, requirements, effect.create(settings), chainParent, chainChildren, image); - } - - Map<Integer, Integer> getCountPerNbPlayer() { - return countPerNbPlayer; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.java deleted file mode 100644 index 6f97e55f..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.luxons.sevenwonders.game.data.definitions; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.luxons.sevenwonders.game.Settings; -import org.luxons.sevenwonders.game.cards.Card; -import org.luxons.sevenwonders.game.cards.CardBack; -import org.luxons.sevenwonders.game.cards.Decks; - -@SuppressWarnings("unused,MismatchedQueryAndUpdateOfCollection") // the fields are injected by Gson -public class DecksDefinition implements Definition<Decks> { - - private List<CardDefinition> age1; - - private List<CardDefinition> age2; - - private List<CardDefinition> age3; - - private String age1Back; - - private String age2Back; - - private String age3Back; - - private List<CardDefinition> guildCards; - - @Override - public Decks create(Settings settings) { - Map<Integer, List<Card>> cardsPerAge = new HashMap<>(); - cardsPerAge.put(1, prepareStandardDeck(age1, settings, age1Back)); - cardsPerAge.put(2, prepareStandardDeck(age2, settings, age2Back)); - cardsPerAge.put(3, prepareAge3Deck(settings)); - return new Decks(cardsPerAge); - } - - private static List<Card> prepareStandardDeck(List<CardDefinition> defs, Settings settings, String backImage) { - CardBack back = new CardBack(backImage); - List<Card> cards = createDeck(defs, settings, back); - Collections.shuffle(cards, settings.getRandom()); - return cards; - } - - private List<Card> prepareAge3Deck(Settings settings) { - CardBack back = new CardBack(age3Back); - List<Card> age3deck = createDeck(age3, settings, back); - age3deck.addAll(createGuildCards(settings, back)); - Collections.shuffle(age3deck, settings.getRandom()); - return age3deck; - } - - private static List<Card> createDeck(List<CardDefinition> defs, Settings settings, CardBack back) { - List<Card> cards = new ArrayList<>(); - for (CardDefinition def : defs) { - for (int i = 0; i < def.getCountPerNbPlayer().get(settings.getNbPlayers()); i++) { - Card card = def.create(settings); - card.setBack(back); - cards.add(card); - } - } - return cards; - } - - private List<Card> createGuildCards(Settings settings, CardBack back) { - List<Card> guild = guildCards.stream() - .map((def) -> def.create(settings)) - .peek(c -> c.setBack(back)) - .collect(Collectors.toList()); - Collections.shuffle(guild, settings.getRandom()); - return guild.subList(0, settings.getNbPlayers() + 2); - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/Definition.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/Definition.java deleted file mode 100644 index 6c6b4b19..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/Definition.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.luxons.sevenwonders.game.data.definitions; - -import org.luxons.sevenwonders.game.Settings; - -/** - * Represents a deserialized JSON definition of some data about the game. It is settings-agnostic. An instance of - * in-game data can be generated from this, given specific game settings. - * - * @param <T> - * the type of in-game object that can be generated from this definition - */ -public interface Definition<T> { - - /** - * Creates a T object from the given settings. This method mustn't mutate this Definition as it may be called - * multiple times with different settings. - * - * @param settings - * the game settings to use to generate a game-specific object from this definition - * - * @return the new game-specific object created from this definition - */ - T create(Settings settings); -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/EffectsDefinition.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/EffectsDefinition.java deleted file mode 100644 index e35463d4..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/EffectsDefinition.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.luxons.sevenwonders.game.data.definitions; - -import java.util.ArrayList; -import java.util.List; - -import org.luxons.sevenwonders.game.Settings; -import org.luxons.sevenwonders.game.effects.BonusPerBoardElement; -import org.luxons.sevenwonders.game.effects.Discount; -import org.luxons.sevenwonders.game.effects.Effect; -import org.luxons.sevenwonders.game.effects.GoldIncrease; -import org.luxons.sevenwonders.game.effects.MilitaryReinforcements; -import org.luxons.sevenwonders.game.effects.ProductionIncrease; -import org.luxons.sevenwonders.game.effects.RawPointsIncrease; -import org.luxons.sevenwonders.game.effects.ScienceProgress; -import org.luxons.sevenwonders.game.effects.SpecialAbility; -import org.luxons.sevenwonders.game.effects.SpecialAbilityActivation; - -@SuppressWarnings("unused") // the fields are injected by Gson -public class EffectsDefinition implements Definition<List<Effect>> { - - private GoldIncrease gold; - - private MilitaryReinforcements military; - - private ScienceProgress science; - - private Discount discount; - - private BonusPerBoardElement perBoardElement; - - private ProductionIncrease production; - - private RawPointsIncrease points; - - private SpecialAbility action; - - @Override - public List<Effect> create(Settings settings) { - List<Effect> effects = new ArrayList<>(); - if (gold != null) { - effects.add(gold); - } - if (military != null) { - effects.add(military); - } - if (science != null) { - effects.add(science); - } - if (discount != null) { - effects.add(discount); - } - if (perBoardElement != null) { - effects.add(perBoardElement); - } - if (production != null) { - effects.add(production); - } - if (points != null) { - effects.add(points); - } - if (action != null) { - effects.add(new SpecialAbilityActivation(action)); - } - return effects; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.java deleted file mode 100644 index a972a517..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.luxons.sevenwonders.game.data.definitions; - -import java.util.Map; - -import org.luxons.sevenwonders.game.Settings; -import org.luxons.sevenwonders.game.wonders.Wonder; - -@SuppressWarnings("unused,MismatchedQueryAndUpdateOfCollection") // the fields are injected by Gson -public class WonderDefinition implements Definition<Wonder> { - - private String name; - - private Map<WonderSide, WonderSideDefinition> sides; - - @Override - public Wonder create(Settings settings) { - Wonder wonder = new Wonder(); - wonder.setName(name); - - WonderSideDefinition wonderSideDef = sides.get(settings.pickWonderSide()); - wonder.setInitialResource(wonderSideDef.getInitialResource()); - wonder.setStages(wonderSideDef.createStages(settings)); - wonder.setImage(wonderSideDef.getImage()); - return wonder; - } - -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderSide.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderSide.java deleted file mode 100644 index 34091350..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderSide.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.luxons.sevenwonders.game.data.definitions; - -public enum WonderSide { - A, - B -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderSideDefinition.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderSideDefinition.java deleted file mode 100644 index c84bba4e..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderSideDefinition.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.luxons.sevenwonders.game.data.definitions; - -import java.util.List; -import java.util.stream.Collectors; - -import org.luxons.sevenwonders.game.Settings; -import org.luxons.sevenwonders.game.resources.ResourceType; -import org.luxons.sevenwonders.game.wonders.WonderStage; - -// the fields are injected by Gson -@SuppressWarnings("unused,MismatchedQueryAndUpdateOfCollection") -class WonderSideDefinition { - - private ResourceType initialResource; - - private List<WonderStageDefinition> stages; - - private String image; - - ResourceType getInitialResource() { - return initialResource; - } - - List<WonderStage> createStages(Settings settings) { - return stages.stream().map(def -> def.create(settings)).collect(Collectors.toList()); - } - - String getImage() { - return image; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderSidePickMethod.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderSidePickMethod.java deleted file mode 100644 index 08aaad14..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderSidePickMethod.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.luxons.sevenwonders.game.data.definitions; - -import java.util.Random; - -public enum WonderSidePickMethod { - ALL_A { - @Override - public WonderSide pickSide(Random random, WonderSide lastPickedSide) { - return WonderSide.A; - } - }, - ALL_B { - @Override - public WonderSide pickSide(Random random, WonderSide lastPickedSide) { - return WonderSide.B; - } - }, - EACH_RANDOM { - @Override - public WonderSide pickSide(Random random, WonderSide lastPickedSide) { - return random.nextBoolean() ? WonderSide.A : WonderSide.B; - } - }, - SAME_RANDOM_FOR_ALL { - @Override - public WonderSide pickSide(Random random, WonderSide lastPickedSide) { - if (lastPickedSide == null) { - return random.nextBoolean() ? WonderSide.A : WonderSide.B; - } else { - return lastPickedSide; - } - } - }; - - public abstract WonderSide pickSide(Random random, WonderSide lastPickedSide); -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderStageDefinition.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderStageDefinition.java deleted file mode 100644 index 230484ee..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/definitions/WonderStageDefinition.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.luxons.sevenwonders.game.data.definitions; - -import org.luxons.sevenwonders.game.Settings; -import org.luxons.sevenwonders.game.cards.Requirements; -import org.luxons.sevenwonders.game.wonders.WonderStage; - -@SuppressWarnings("unused") // the fields are injected by Gson -public class WonderStageDefinition implements Definition<WonderStage> { - - private Requirements requirements; - - private EffectsDefinition effects; - - @Override - public WonderStage create(Settings settings) { - return new WonderStage(requirements, effects.create(settings)); - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/NumericEffectSerializer.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/NumericEffectSerializer.java deleted file mode 100644 index c0a75d80..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/NumericEffectSerializer.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.luxons.sevenwonders.game.data.serializers; - -import java.lang.reflect.Type; - -import org.luxons.sevenwonders.game.effects.Effect; -import org.luxons.sevenwonders.game.effects.GoldIncrease; -import org.luxons.sevenwonders.game.effects.MilitaryReinforcements; -import org.luxons.sevenwonders.game.effects.RawPointsIncrease; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -public class NumericEffectSerializer implements JsonSerializer<Effect>, JsonDeserializer<Effect> { - - @Override - public JsonElement serialize(Effect effect, Type typeOfSrc, JsonSerializationContext context) { - int value; - if (MilitaryReinforcements.class.equals(typeOfSrc)) { - value = ((MilitaryReinforcements) effect).getCount(); - } else if (GoldIncrease.class.equals(typeOfSrc)) { - value = ((GoldIncrease) effect).getAmount(); - } else if (RawPointsIncrease.class.equals(typeOfSrc)) { - value = ((RawPointsIncrease) effect).getPoints(); - } else { - throw new IllegalArgumentException("Unknown numeric effect " + typeOfSrc.getTypeName()); - } - return new JsonPrimitive(value); - } - - @Override - public Effect deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - int value = json.getAsInt(); - if (MilitaryReinforcements.class.equals(typeOfT)) { - return new MilitaryReinforcements(value); - } else if (GoldIncrease.class.equals(typeOfT)) { - return new GoldIncrease(value); - } else if (RawPointsIncrease.class.equals(typeOfT)) { - return new RawPointsIncrease(value); - } - throw new IllegalArgumentException("Unknown numeric effet " + typeOfT.getTypeName()); - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializer.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializer.java deleted file mode 100644 index c3eb1386..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializer.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.luxons.sevenwonders.game.data.serializers; - -import java.lang.reflect.Type; - -import org.luxons.sevenwonders.game.effects.ProductionIncrease; -import org.luxons.sevenwonders.game.resources.Production; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -public class ProductionIncreaseSerializer implements JsonSerializer<ProductionIncrease>, - JsonDeserializer<ProductionIncrease> { - - @Override - public JsonElement serialize(ProductionIncrease productionIncrease, Type typeOfSrc, - JsonSerializationContext context) { - Production production = productionIncrease.getProduction(); - JsonElement json = context.serialize(production); - if (!json.isJsonNull() && !productionIncrease.isSellable()) { - return new JsonPrimitive(wrapInBrackets(json.getAsString())); - } - return json; - } - - private String wrapInBrackets(String str) { - return '(' + str + ')'; - } - - @Override - public ProductionIncrease deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - ProductionIncrease productionIncrease = new ProductionIncrease(); - - String resourcesStr = json.getAsString(); - boolean isSellable = !resourcesStr.startsWith("("); - if (!isSellable) { - resourcesStr = unwrapBrackets(resourcesStr); - json = new JsonPrimitive(resourcesStr); - } - productionIncrease.setSellable(isSellable); - - Production production = context.deserialize(json, Production.class); - productionIncrease.setProduction(production); - return productionIncrease; - } - - private static String unwrapBrackets(String str) { - return str.substring(1, str.length() - 1); - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.java deleted file mode 100644 index 178134bb..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.luxons.sevenwonders.game.data.serializers; - -import java.lang.reflect.Type; -import java.util.Set; -import java.util.stream.Collectors; - -import org.luxons.sevenwonders.game.resources.Production; -import org.luxons.sevenwonders.game.resources.ResourceType; -import org.luxons.sevenwonders.game.resources.Resources; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -public class ProductionSerializer implements JsonSerializer<Production>, JsonDeserializer<Production> { - - @Override - public JsonElement serialize(Production production, Type typeOfSrc, JsonSerializationContext context) { - Resources fixedResources = production.getFixedResources(); - Set<Set<ResourceType>> choices = production.getAlternativeResources(); - if (fixedResources.isEmpty()) { - return serializeAsChoice(choices, context); - } else if (choices.isEmpty()) { - return serializeAsResources(fixedResources, context); - } else { - throw new IllegalArgumentException("Cannot serialize a production with mixed fixed resources and choices"); - } - } - - private static JsonElement serializeAsChoice(Set<Set<ResourceType>> choices, JsonSerializationContext context) { - if (choices.isEmpty()) { - return JsonNull.INSTANCE; - } - if (choices.size() > 1) { - throw new IllegalArgumentException("Cannot serialize a production with more than one choice"); - } - String str = choices.stream() - .flatMap(Set::stream) - .map(ResourceType::getSymbol) - .map(Object::toString) - .collect(Collectors.joining("/")); - return context.serialize(str); - } - - private static JsonElement serializeAsResources(Resources fixedResources, JsonSerializationContext context) { - return context.serialize(fixedResources); - } - - @Override - public Production deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - String resourcesStr = json.getAsString(); - Production production = new Production(); - if (resourcesStr.contains("/")) { - production.addChoice(createChoice(resourcesStr)); - } else { - Resources fixedResources = context.deserialize(json, Resources.class); - production.addAll(fixedResources); - } - return production; - } - - private ResourceType[] createChoice(String choiceStr) { - String[] symbols = choiceStr.split("/"); - ResourceType[] choice = new ResourceType[symbols.length]; - for (int i = 0; i < symbols.length; i++) { - if (symbols[i].length() != 1) { - throw new IllegalArgumentException("Choice elements must be resource types, got " + symbols[i]); - } - choice[i] = ResourceType.fromSymbol(symbols[i].charAt(0)); - } - return choice; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ResourceTypeSerializer.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ResourceTypeSerializer.java deleted file mode 100644 index d2a49180..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ResourceTypeSerializer.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.luxons.sevenwonders.game.data.serializers; - -import java.lang.reflect.Type; - -import org.luxons.sevenwonders.game.resources.ResourceType; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -public class ResourceTypeSerializer implements JsonSerializer<ResourceType>, JsonDeserializer<ResourceType> { - - @Override - public JsonElement serialize(ResourceType type, Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive(type.getSymbol()); - } - - @Override - public ResourceType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - String str = json.getAsString(); - if (str.isEmpty()) { - throw new IllegalArgumentException("Empty string is not a valid resource type"); - } - return ResourceType.fromSymbol(str.charAt(0)); - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ResourceTypesSerializer.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ResourceTypesSerializer.java deleted file mode 100644 index 89d3e723..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ResourceTypesSerializer.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.luxons.sevenwonders.game.data.serializers; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import org.luxons.sevenwonders.game.resources.ResourceType; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -public class ResourceTypesSerializer implements JsonSerializer<List<ResourceType>>, - JsonDeserializer<List<ResourceType>> { - - @Override - public JsonElement serialize(List<ResourceType> resources, Type typeOfSrc, JsonSerializationContext context) { - String s = resources.stream().map(ResourceType::getSymbol).map(Object::toString).collect(Collectors.joining()); - return new JsonPrimitive(s); - } - - @Override - public List<ResourceType> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - String s = json.getAsString(); - List<ResourceType> resources = new ArrayList<>(); - for (char c : s.toCharArray()) { - resources.add(ResourceType.fromSymbol(c)); - } - return resources; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.java deleted file mode 100644 index 9c27b2a1..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.luxons.sevenwonders.game.data.serializers; - -import java.lang.reflect.Type; -import java.util.stream.Collectors; - -import org.luxons.sevenwonders.game.resources.ResourceType; -import org.luxons.sevenwonders.game.resources.Resources; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -public class ResourcesSerializer implements JsonSerializer<Resources>, JsonDeserializer<Resources> { - - @Override - public JsonElement serialize(Resources resources, Type typeOfSrc, JsonSerializationContext context) { - String s = resources.asList() - .stream() - .map(ResourceType::getSymbol) - .map(Object::toString) - .collect(Collectors.joining()); - return s.isEmpty() ? JsonNull.INSTANCE : new JsonPrimitive(s); - } - - @Override - public Resources deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - String s = json.getAsString(); - Resources resources = new Resources(); - for (char c : s.toCharArray()) { - resources.add(ResourceType.fromSymbol(c), 1); - } - return resources; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ScienceProgressSerializer.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ScienceProgressSerializer.java deleted file mode 100644 index cecad405..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/data/serializers/ScienceProgressSerializer.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.luxons.sevenwonders.game.data.serializers; - -import java.lang.reflect.Type; - -import org.luxons.sevenwonders.game.boards.Science; -import org.luxons.sevenwonders.game.boards.ScienceType; -import org.luxons.sevenwonders.game.effects.ScienceProgress; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -public class ScienceProgressSerializer implements JsonSerializer<ScienceProgress>, JsonDeserializer<ScienceProgress> { - - @Override - public JsonElement serialize(ScienceProgress scienceProgress, Type typeOfSrc, JsonSerializationContext context) { - Science science = scienceProgress.getScience(); - - if (science.size() > 1) { - throw new UnsupportedOperationException("Cannot serialize science containing more than one element"); - } - - for (ScienceType type : ScienceType.values()) { - int quantity = science.getQuantity(type); - if (quantity == 1) { - return context.serialize(type); - } - } - - if (science.getJokers() == 1) { - return new JsonPrimitive("any"); - } - - return JsonNull.INSTANCE; - } - - @Override - public ScienceProgress deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - String s = json.getAsString(); - ScienceProgress scienceProgress = new ScienceProgress(); - Science science = new Science(); - if ("any".equals(s)) { - science.addJoker(1); - } else { - science.add(deserializeScienceType(json, context), 1); - } - scienceProgress.setScience(science); - return scienceProgress; - } - - private ScienceType deserializeScienceType(JsonElement json, JsonDeserializationContext context) { - ScienceType type = context.deserialize(json, ScienceType.class); - if (type == null) { - throw new IllegalArgumentException("Invalid science type " + json.getAsString()); - } - return type; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/resources/ResourceType.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/resources/ResourceType.java index baad8451..644437df 100644 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/resources/ResourceType.java +++ b/game-engine/src/main/java/org/luxons/sevenwonders/game/resources/ResourceType.java @@ -26,6 +26,14 @@ public enum ResourceType { this.symbol = symbol; } + public static ResourceType fromSymbol(String symbol) { + if (symbol.length() != 1) { + throw new IllegalArgumentException("The given symbol must be a valid single-char resource type, got " + + symbol); + } + return fromSymbol(symbol.charAt(0)); + } + public static ResourceType fromSymbol(Character symbol) { ResourceType type = typesPerSymbol.get(symbol); if (type == null) { diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/Settings.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Settings.kt index 70dddccf..fac3979e 100644 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/Settings.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Settings.kt @@ -1,8 +1,8 @@ package org.luxons.sevenwonders.game import org.luxons.sevenwonders.game.api.CustomizableSettings -import org.luxons.sevenwonders.game.data.definitions.WonderSide -import org.luxons.sevenwonders.game.data.definitions.WonderSidePickMethod +import org.luxons.sevenwonders.game.data.WonderSide +import org.luxons.sevenwonders.game.data.WonderSidePickMethod import java.util.Random class Settings @JvmOverloads constructor( diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt index 354aecb6..e4efb9e3 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt @@ -1,6 +1,6 @@ package org.luxons.sevenwonders.game.api -import org.luxons.sevenwonders.game.data.definitions.WonderSidePickMethod +import org.luxons.sevenwonders.game.data.WonderSidePickMethod data class CustomizableSettings( val randomSeedForTests: Long? = null, diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinition.kt new file mode 100644 index 00000000..b7a859eb --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinition.kt @@ -0,0 +1,30 @@ +package org.luxons.sevenwonders.game.data + +import org.luxons.sevenwonders.game.Game +import org.luxons.sevenwonders.game.Settings +import org.luxons.sevenwonders.game.api.CustomizableSettings +import org.luxons.sevenwonders.game.boards.Board +import org.luxons.sevenwonders.game.data.definitions.DecksDefinition +import org.luxons.sevenwonders.game.data.definitions.WonderDefinition + +class GameDefinition internal constructor( + rules: GlobalRules, + private val wonders: Array<WonderDefinition>, + private val decksDefinition: DecksDefinition +) { + val minPlayers: Int = rules.minPlayers + val maxPlayers: Int = rules.maxPlayers + + fun initGame(id: Long, customSettings: CustomizableSettings, nbPlayers: Int): Game { + val settings = Settings(nbPlayers, customSettings) + val boards = assignBoards(settings, nbPlayers) + val decks = decksDefinition.prepareDecks(settings) + return Game(id, settings, nbPlayers, boards, decks) + } + + private fun assignBoards(settings: Settings, nbPlayers: Int): List<Board> { + val randomizedWonders = wonders.toMutableList() + randomizedWonders.shuffle(settings.random) + return randomizedWonders.take(nbPlayers).mapIndexed { i, wDef -> Board(wDef.create(settings), i, settings) } + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinitionLoader.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinitionLoader.kt new file mode 100644 index 00000000..22ecc488 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinitionLoader.kt @@ -0,0 +1,63 @@ +package org.luxons.sevenwonders.game.data + +import com.github.salomonbrys.kotson.registerTypeAdapter +import com.github.salomonbrys.kotson.typeToken +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.google.gson.JsonNull +import com.google.gson.JsonPrimitive +import org.luxons.sevenwonders.game.data.definitions.DecksDefinition +import org.luxons.sevenwonders.game.data.definitions.WonderDefinition +import org.luxons.sevenwonders.game.data.serializers.NumericEffectSerializer +import org.luxons.sevenwonders.game.data.serializers.ProductionIncreaseSerializer +import org.luxons.sevenwonders.game.data.serializers.ProductionSerializer +import org.luxons.sevenwonders.game.data.serializers.ResourceTypeSerializer +import org.luxons.sevenwonders.game.data.serializers.ResourceTypesSerializer +import org.luxons.sevenwonders.game.data.serializers.ResourcesSerializer +import org.luxons.sevenwonders.game.data.serializers.ScienceProgressSerializer +import org.luxons.sevenwonders.game.effects.GoldIncrease +import org.luxons.sevenwonders.game.effects.MilitaryReinforcements +import org.luxons.sevenwonders.game.effects.ProductionIncrease +import org.luxons.sevenwonders.game.effects.RawPointsIncrease +import org.luxons.sevenwonders.game.effects.ScienceProgress +import org.luxons.sevenwonders.game.resources.Production +import org.luxons.sevenwonders.game.resources.ResourceType +import org.luxons.sevenwonders.game.resources.Resources + +class GameDefinitionLoader { + + val gameDefinition: GameDefinition by lazy { load() } + + private fun load(): GameDefinition { + val gson: Gson = createGson() + val rules = loadJson("global_rules.json", GlobalRules::class.java, gson) + val wonders = loadJson("wonders.json", Array<WonderDefinition>::class.java, gson) + val decksDefinition = loadJson("cards.json", DecksDefinition::class.java, gson) + return GameDefinition(rules, wonders, decksDefinition) + } + + private fun <T> loadJson(filename: String, clazz: Class<T>, gson: Gson): T { + val packageAsPath = GameDefinitionLoader::class.java.`package`.name.replace('.', '/') + val resourcePath = "/$packageAsPath/$filename" + val resource = GameDefinitionLoader::class.java.getResource(resourcePath) + val json = resource.readText() + return gson.fromJson(json, clazz) + } + + private fun createGson(): Gson { + return GsonBuilder().disableHtmlEscaping() + .registerTypeAdapter<Resources>(ResourcesSerializer()) + .registerTypeAdapter<ResourceType>(ResourceTypeSerializer()) + .registerTypeAdapter<List<ResourceType>>(ResourceTypesSerializer()) + .registerTypeAdapter<Production>(ProductionSerializer()) + .registerTypeAdapter<ProductionIncrease>(ProductionIncreaseSerializer()) + .registerTypeAdapter<MilitaryReinforcements>(NumericEffectSerializer()) + .registerTypeAdapter<RawPointsIncrease>(NumericEffectSerializer()) + .registerTypeAdapter<GoldIncrease>(NumericEffectSerializer()) + .registerTypeAdapter<ScienceProgress>(ScienceProgressSerializer()) + .create() + } + + private inline fun <reified T: Any> GsonBuilder.registerTypeAdapter(typeAdapter: Any): GsonBuilder + = this.registerTypeAdapter(typeToken<T>(), typeAdapter) +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GlobalRules.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GlobalRules.kt new file mode 100644 index 00000000..f472cc2a --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GlobalRules.kt @@ -0,0 +1,6 @@ +package org.luxons.sevenwonders.game.data + +internal data class GlobalRules( + val minPlayers: Int, + val maxPlayers: Int +) diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/WonderSide.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/WonderSide.kt new file mode 100644 index 00000000..4a818fc4 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/WonderSide.kt @@ -0,0 +1,6 @@ +package org.luxons.sevenwonders.game.data + +enum class WonderSide { + A, + B +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/WonderSidePickMethod.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/WonderSidePickMethod.kt new file mode 100644 index 00000000..29fe2126 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/WonderSidePickMethod.kt @@ -0,0 +1,28 @@ +package org.luxons.sevenwonders.game.data + +import java.util.Random + +enum class WonderSidePickMethod { + ALL_A { + override fun pickSide(random: Random, lastPickedSide: WonderSide?): WonderSide { + return WonderSide.A + } + }, + ALL_B { + override fun pickSide(random: Random, lastPickedSide: WonderSide?): WonderSide { + return WonderSide.B + } + }, + EACH_RANDOM { + override fun pickSide(random: Random, lastPickedSide: WonderSide?): WonderSide { + return if (random.nextBoolean()) WonderSide.A else WonderSide.B + } + }, + SAME_RANDOM_FOR_ALL { + override fun pickSide(random: Random, lastPickedSide: WonderSide?): WonderSide { + return lastPickedSide ?: if (random.nextBoolean()) WonderSide.A else WonderSide.B + } + }; + + abstract fun pickSide(random: Random, lastPickedSide: WonderSide?): WonderSide +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/CardDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/CardDefinition.kt new file mode 100644 index 00000000..2827564b --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/CardDefinition.kt @@ -0,0 +1,20 @@ +package org.luxons.sevenwonders.game.data.definitions + +import org.luxons.sevenwonders.game.cards.Card +import org.luxons.sevenwonders.game.cards.Color +import org.luxons.sevenwonders.game.cards.Requirements + +internal class CardDefinition( + private val name: String, + private val color: Color, + private val requirements: Requirements? = null, + private val effect: EffectsDefinition, + private val chainParent: String? = null, + private val chainChildren: List<String> = emptyList(), + private val image: String? = null, + private val countPerNbPlayer: Map<Int, Int> +) { + fun create(nbPlayers: Int): List<Card> = List( countPerNbPlayer[nbPlayers]!!) { create() } + + fun create(): Card = Card(name, color, requirements, effect.create(), chainParent, chainChildren, image) +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt new file mode 100644 index 00000000..a09f0642 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt @@ -0,0 +1,53 @@ +package org.luxons.sevenwonders.game.data.definitions + +import org.luxons.sevenwonders.game.Settings +import org.luxons.sevenwonders.game.cards.Card +import org.luxons.sevenwonders.game.cards.CardBack +import org.luxons.sevenwonders.game.cards.Decks + +internal class DecksDefinition( + private val age1: List<CardDefinition>, + private val age2: List<CardDefinition>, + private val age3: List<CardDefinition>, + private val age1Back: String, + private val age2Back: String, + private val age3Back: String, + private val guildCards: List<CardDefinition> +) { + fun prepareDecks(settings: Settings): Decks { + val cardsPerAge = mapOf( + 1 to prepareStandardDeck(age1, settings, age1Back), + 2 to prepareStandardDeck(age2, settings, age2Back), + 3 to prepareAge3Deck(settings) + ) + return Decks(cardsPerAge) + } + + private fun prepareStandardDeck(defs: List<CardDefinition>, settings: Settings, backImage: String): List<Card> { + val back = CardBack(backImage) + val cards = createDeck(defs, settings, back).toMutableList() + cards.shuffle(settings.random) + return cards + } + + private fun prepareAge3Deck(settings: Settings): List<Card> { + val back = CardBack(age3Back) + val age3deck = createDeck(age3, settings, back).toMutableList() + age3deck.addAll(createGuildCards(settings, back)) + age3deck.shuffle(settings.random) + return age3deck + } + + private fun createDeck(defs: List<CardDefinition>, settings: Settings, back: CardBack): List<Card> { + return defs.flatMap { it.create(settings.nbPlayers) }.onEach { it.back = back } + } + + private fun createGuildCards(settings: Settings, back: CardBack): List<Card> { + val guild = guildCards + .map { it.create() } + .map { c -> c.back = back; c } + .toMutableList() + guild.shuffle(settings.random) + return guild.subList(0, settings.nbPlayers + 2) + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/EffectsDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/EffectsDefinition.kt new file mode 100644 index 00000000..978ec4a6 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/EffectsDefinition.kt @@ -0,0 +1,53 @@ +package org.luxons.sevenwonders.game.data.definitions + +import org.luxons.sevenwonders.game.effects.BonusPerBoardElement +import org.luxons.sevenwonders.game.effects.Discount +import org.luxons.sevenwonders.game.effects.Effect +import org.luxons.sevenwonders.game.effects.GoldIncrease +import org.luxons.sevenwonders.game.effects.MilitaryReinforcements +import org.luxons.sevenwonders.game.effects.ProductionIncrease +import org.luxons.sevenwonders.game.effects.RawPointsIncrease +import org.luxons.sevenwonders.game.effects.ScienceProgress +import org.luxons.sevenwonders.game.effects.SpecialAbility +import org.luxons.sevenwonders.game.effects.SpecialAbilityActivation +import java.util.ArrayList + +internal data class EffectsDefinition( + private val gold: GoldIncrease? = null, + private val military: MilitaryReinforcements? = null, + private val science: ScienceProgress? = null, + private val discount: Discount? = null, + private val perBoardElement: BonusPerBoardElement? = null, + private val production: ProductionIncrease? = null, + private val points: RawPointsIncrease? = null, + private val action: SpecialAbility? = null +) { + fun create(): List<Effect> { + val effects = ArrayList<Effect>() + if (gold != null) { + effects.add(gold) + } + if (military != null) { + effects.add(military) + } + if (science != null) { + effects.add(science) + } + if (discount != null) { + effects.add(discount) + } + if (perBoardElement != null) { + effects.add(perBoardElement) + } + if (production != null) { + effects.add(production) + } + if (points != null) { + effects.add(points) + } + if (action != null) { + effects.add(SpecialAbilityActivation(action)) + } + return effects + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.kt new file mode 100644 index 00000000..558f16e8 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.kt @@ -0,0 +1,21 @@ +package org.luxons.sevenwonders.game.data.definitions + +import org.luxons.sevenwonders.game.Settings +import org.luxons.sevenwonders.game.data.WonderSide +import org.luxons.sevenwonders.game.wonders.Wonder + +internal data class WonderDefinition( + private val name: String, + private val sides: Map<WonderSide, WonderSideDefinition> +) { + fun create(settings: Settings): Wonder { + val wonder = Wonder() + wonder.name = name + + val wonderSideDef = sides[settings.pickWonderSide()]!! + wonder.initialResource = wonderSideDef.initialResource + wonder.stages = wonderSideDef.createStages() + wonder.image = wonderSideDef.image + return wonder + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderSideDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderSideDefinition.kt new file mode 100644 index 00000000..247432e3 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderSideDefinition.kt @@ -0,0 +1,14 @@ +package org.luxons.sevenwonders.game.data.definitions + +import org.luxons.sevenwonders.game.resources.ResourceType +import org.luxons.sevenwonders.game.wonders.WonderStage + +internal class WonderSideDefinition( + val initialResource: ResourceType, + private val stages: List<WonderStageDefinition>, + val image: String +) { + fun createStages(): List<WonderStage> { + return stages.map { def -> def.create() } + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderStageDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderStageDefinition.kt new file mode 100644 index 00000000..3d2872d0 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderStageDefinition.kt @@ -0,0 +1,13 @@ +package org.luxons.sevenwonders.game.data.definitions + +import org.luxons.sevenwonders.game.cards.Requirements +import org.luxons.sevenwonders.game.wonders.WonderStage + +internal class WonderStageDefinition( + private val requirements: Requirements, + private val effects: EffectsDefinition +) { + fun create(): WonderStage { + return WonderStage(requirements, effects.create()) + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/NumericEffectSerializer.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/NumericEffectSerializer.kt new file mode 100644 index 00000000..510a511c --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/NumericEffectSerializer.kt @@ -0,0 +1,40 @@ +package org.luxons.sevenwonders.game.data.serializers + +import java.lang.reflect.Type + +import org.luxons.sevenwonders.game.effects.Effect +import org.luxons.sevenwonders.game.effects.GoldIncrease +import org.luxons.sevenwonders.game.effects.MilitaryReinforcements +import org.luxons.sevenwonders.game.effects.RawPointsIncrease + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.google.gson.JsonParseException +import com.google.gson.JsonPrimitive +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer + +class NumericEffectSerializer : JsonSerializer<Effect>, JsonDeserializer<Effect> { + + override fun serialize(effect: Effect, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { + val value: Int = when (effect) { + is MilitaryReinforcements -> effect.count + is GoldIncrease -> effect.amount + is RawPointsIncrease -> effect.points + else -> throw IllegalArgumentException("Unknown numeric effect " + effect.javaClass.name) + } + return JsonPrimitive(value) + } + + @Throws(JsonParseException::class) + override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Effect { + val value = json.asInt + return when (typeOfT) { + MilitaryReinforcements::class.java -> MilitaryReinforcements(value) + GoldIncrease::class.java -> GoldIncrease(value) + RawPointsIncrease::class.java -> RawPointsIncrease(value) + else -> throw IllegalArgumentException("Unknown numeric effet " + typeOfT.typeName) + } + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializer.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializer.kt new file mode 100644 index 00000000..578f816b --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializer.kt @@ -0,0 +1,51 @@ +package org.luxons.sevenwonders.game.data.serializers + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.google.gson.JsonParseException +import com.google.gson.JsonPrimitive +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer +import org.luxons.sevenwonders.game.effects.ProductionIncrease +import org.luxons.sevenwonders.game.resources.Production +import java.lang.reflect.Type + +class ProductionIncreaseSerializer : JsonSerializer<ProductionIncrease>, JsonDeserializer<ProductionIncrease> { + + override fun serialize( + productionIncrease: ProductionIncrease, + typeOfSrc: Type, + context: JsonSerializationContext + ): JsonElement { + val production = productionIncrease.production + val json = context.serialize(production) + return if (!json.isJsonNull && !productionIncrease.isSellable) { JsonPrimitive("(${json.asString})")} else json + } + + @Throws(JsonParseException::class) + override fun deserialize( + json: JsonElement, + typeOfT: Type, + context: JsonDeserializationContext + ): ProductionIncrease { + var json = json + val productionIncrease = ProductionIncrease() + + var resourcesStr = json.asString + val isSellable = !resourcesStr.startsWith("(") + if (!isSellable) { + resourcesStr = unwrapBrackets(resourcesStr) + json = JsonPrimitive(resourcesStr) + } + productionIncrease.isSellable = isSellable + + val production = context.deserialize<Production>(json, Production::class.java) + productionIncrease.production = production + return productionIncrease + } + + private fun unwrapBrackets(str: String): String { + return str.substring(1, str.length - 1) + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.kt new file mode 100644 index 00000000..538fdbb4 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.kt @@ -0,0 +1,58 @@ +package org.luxons.sevenwonders.game.data.serializers + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.google.gson.JsonNull +import com.google.gson.JsonParseException +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer +import org.luxons.sevenwonders.game.resources.Production +import org.luxons.sevenwonders.game.resources.ResourceType +import org.luxons.sevenwonders.game.resources.Resources +import java.lang.reflect.Type + +class ProductionSerializer : JsonSerializer<Production>, JsonDeserializer<Production> { + + override fun serialize(production: Production, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { + val fixedResources = production.fixedResources + val choices = production.alternativeResources + return when { + fixedResources.isEmpty -> serializeAsChoice(choices, context) + choices.isEmpty() -> serializeAsResources(fixedResources, context) + else -> throw IllegalArgumentException("Cannot serialize a production with mixed fixed resources and choices") + } + } + + private fun serializeAsChoice(choices: Set<Set<ResourceType>>, context: JsonSerializationContext): JsonElement { + if (choices.isEmpty()) { + return JsonNull.INSTANCE + } + if (choices.size > 1) { + throw IllegalArgumentException("Cannot serialize a production with more than one choice") + } + val str = choices.flatMap { it }.map { it.symbol }.joinToString("/") + return context.serialize(str) + } + + private fun serializeAsResources(fixedResources: Resources, context: JsonSerializationContext): JsonElement { + return context.serialize(fixedResources) + } + + @Throws(JsonParseException::class) + override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Production { + val resourcesStr = json.asString + val production = Production() + if (resourcesStr.contains("/")) { + production.addChoice(*createChoice(resourcesStr)) + } else { + val fixedResources = context.deserialize<Resources>(json, Resources::class.java) + production.addAll(fixedResources) + } + return production + } + + private fun createChoice(choiceStr: String): Array<ResourceType> { + return choiceStr.split("/").map { ResourceType.fromSymbol(it) }.toTypedArray() + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourceTypeSerializer.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourceTypeSerializer.kt new file mode 100644 index 00000000..1de9334a --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourceTypeSerializer.kt @@ -0,0 +1,29 @@ +package org.luxons.sevenwonders.game.data.serializers + +import java.lang.reflect.Type + +import org.luxons.sevenwonders.game.resources.ResourceType + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.google.gson.JsonParseException +import com.google.gson.JsonPrimitive +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer + +internal class ResourceTypeSerializer : JsonSerializer<ResourceType>, JsonDeserializer<ResourceType> { + + override fun serialize(type: ResourceType, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { + return JsonPrimitive(type.symbol!!) + } + + @Throws(JsonParseException::class) + override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ResourceType { + val str = json.asString + if (str.isEmpty()) { + throw IllegalArgumentException("Empty string is not a valid resource type") + } + return ResourceType.fromSymbol(str[0]) + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourceTypesSerializer.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourceTypesSerializer.kt new file mode 100644 index 00000000..9ba21043 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourceTypesSerializer.kt @@ -0,0 +1,39 @@ +package org.luxons.sevenwonders.game.data.serializers + +import java.lang.reflect.Type + +import org.luxons.sevenwonders.game.resources.ResourceType + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.google.gson.JsonParseException +import com.google.gson.JsonPrimitive +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer + +internal class ResourceTypesSerializer : JsonSerializer<List<ResourceType>>, JsonDeserializer<List<ResourceType>> { + + override fun serialize( + resources: List<ResourceType>, + typeOfSrc: Type, + context: JsonSerializationContext + ): JsonElement { + val s = resources.map { it.symbol }.joinToString("") + return JsonPrimitive(s) + } + + @Throws(JsonParseException::class) + override fun deserialize( + json: JsonElement, + typeOfT: Type, + context: JsonDeserializationContext + ): List<ResourceType> { + val s = json.asString + val resources = ArrayList<ResourceType>() + for (c in s.toCharArray()) { + resources.add(ResourceType.fromSymbol(c)) + } + return resources + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.kt new file mode 100644 index 00000000..2baf7a35 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.kt @@ -0,0 +1,34 @@ +package org.luxons.sevenwonders.game.data.serializers + +import java.lang.reflect.Type +import java.util.stream.Collectors + +import org.luxons.sevenwonders.game.resources.ResourceType +import org.luxons.sevenwonders.game.resources.Resources + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.google.gson.JsonNull +import com.google.gson.JsonParseException +import com.google.gson.JsonPrimitive +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer + +internal class ResourcesSerializer : JsonSerializer<Resources>, JsonDeserializer<Resources> { + + override fun serialize(resources: Resources, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { + val s = resources.asList().map { it.symbol }.joinToString("") + return if (s.isEmpty()) JsonNull.INSTANCE else JsonPrimitive(s) + } + + @Throws(JsonParseException::class) + override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Resources { + val s = json.asString + val resources = Resources() + for (c in s.toCharArray()) { + resources.add(ResourceType.fromSymbol(c), 1) + } + return resources + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ScienceProgressSerializer.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ScienceProgressSerializer.kt new file mode 100644 index 00000000..ed383d63 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ScienceProgressSerializer.kt @@ -0,0 +1,57 @@ +package org.luxons.sevenwonders.game.data.serializers + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.google.gson.JsonNull +import com.google.gson.JsonParseException +import com.google.gson.JsonPrimitive +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer +import org.luxons.sevenwonders.game.boards.Science +import org.luxons.sevenwonders.game.boards.ScienceType +import org.luxons.sevenwonders.game.effects.ScienceProgress +import java.lang.reflect.Type + +internal class ScienceProgressSerializer : JsonSerializer<ScienceProgress>, JsonDeserializer<ScienceProgress> { + + override fun serialize( + scienceProgress: ScienceProgress, + typeOfSrc: Type, + context: JsonSerializationContext + ): JsonElement { + val science = scienceProgress.science + + if (science.size() > 1) { + throw UnsupportedOperationException("Cannot serialize science containing more than one element") + } + + for (type in ScienceType.values()) { + val quantity = science.getQuantity(type) + if (quantity == 1) { + return context.serialize(type) + } + } + + return if (science.jokers == 1) JsonPrimitive("any") else JsonNull.INSTANCE + } + + @Throws(JsonParseException::class) + override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ScienceProgress { + val s = json.asString + val scienceProgress = ScienceProgress() + val science = Science() + if ("any" == s) { + science.addJoker(1) + } else { + science.add(deserializeScienceType(json, context), 1) + } + scienceProgress.science = science + return scienceProgress + } + + private fun deserializeScienceType(json: JsonElement, context: JsonDeserializationContext): ScienceType { + return context.deserialize<ScienceType>(json, ScienceType::class.java) + ?: throw IllegalArgumentException("Invalid science type " + json.asString) + } +} diff --git a/game-engine/src/test/java/org/luxons/sevenwonders/game/data/definitions/WonderSidePickMethodTest.java b/game-engine/src/test/java/org/luxons/sevenwonders/game/data/definitions/WonderSidePickMethodTest.java index 0b7de3d6..f45ad4ea 100644 --- a/game-engine/src/test/java/org/luxons/sevenwonders/game/data/definitions/WonderSidePickMethodTest.java +++ b/game-engine/src/test/java/org/luxons/sevenwonders/game/data/definitions/WonderSidePickMethodTest.java @@ -8,6 +8,8 @@ import org.junit.experimental.theories.DataPoints; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; import org.junit.runner.RunWith; +import org.luxons.sevenwonders.game.data.WonderSide; +import org.luxons.sevenwonders.game.data.WonderSidePickMethod; import static org.junit.Assert.assertEquals; |