package com.galvarez.ttw.model.data; import static java.lang.Math.abs; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Properties; import java.util.Random; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Json; import com.galvarez.ttw.model.map.MapGenerator; import com.galvarez.ttw.utils.BooleanValue; import com.galvarez.ttw.utils.EnumValue; public final class SessionSettings implements Cloneable { /** List different colors that are easy to recognize on-screen. */ public static final List<Color> COLORS = Arrays.asList(Color.RED, Color.GREEN, Color.BLUE, Color.PURPLE, Color.YELLOW, Color.TEAL, Color.WHITE, Color.BLACK, Color.GRAY, Color.PINK, Color.LIGHT_GRAY, Color.ORANGE, Color.MAGENTA, Color.DARK_GRAY, Color.CYAN, Color.OLIVE, Color.MAROON, Color.NAVY); private final Map<String, Culture> cultures; private final Map<String, Discovery> discoveries; public final List<Empire> empires = new ArrayList<>(); public final Properties map; public final EnumValue<MapGenerator.Generator> mapType; public final BooleanValue startWithDiplomacy = new BooleanValue(false); public SessionSettings() { // init map parameters mapType = new EnumValue<>(MapGenerator.Generator.ISLAND); map = mapType.get().algo.getDefaultValues(); // load cultures from data file Json json = new Json(); this.cultures = cultures(json).stream().collect(toMap(Culture::getName, c -> c)); this.discoveries = discoveries(json).stream().collect(toMap(Discovery::getName, c -> c)); // generate some default empires boolean ai = false; for (Culture culture : cultures.values()) { empires.add(new Empire(guessColor(), culture, ai)); ai = true; } } public SessionSettings(SessionSettings settings) { // load cultures and discoveries from data file Json json = new Json(); this.cultures = cultures(json).stream().collect(toMap(Culture::getName, c -> c)); this.discoveries = discoveries(json).stream().collect(toMap(Discovery::getName, c -> c)); // copy map creation options this.map = new Properties(); this.map.putAll(settings.map); this.mapType = new EnumValue<>(MapGenerator.Generator.ISLAND); this.mapType.set(settings.mapType.get()); this.startWithDiplomacy.set(settings.startWithDiplomacy.get()); // copy empires using new cultures (as they have a city iterator) for (Empire empire : settings.empires) this.empires.add(new Empire(empire.color, cultures.get(empire.culture.name), empire.isComputerControlled())); } private static List<Culture> cultures(Json json) { json.setSerializer(Culture.class, Culture.SER); List<Culture> cultures = new ArrayList<>(); for (FileHandle f : files("data/cultures/", "antiquity.json")) cultures.addAll(Arrays.asList(json.fromJson(Culture[].class, f))); return cultures; } private static List<Discovery> discoveries(Json json) { // TODO add ideas from http://doodlegod.wikia.com/wiki/Doodle_Devil // TODO add ideas from http://doodlegod.wikia.com/wiki/Doodle_God_2 // TODO The mythic discoveries could be used as 'totem' animals json.setSerializer(Discovery.class, Discovery.SER); List<Discovery> discoveries = new ArrayList<>(); for (FileHandle f : files("data/discoveries/", "nature.json", "prehistory.json", "antiquity.json", "classic.json")) discoveries.addAll(Arrays.asList(json.fromJson(Discovery[].class, f))); return discoveries; } private static Iterable<FileHandle> files(String dir, String ... files) { return Arrays.stream(files).map(f -> Gdx.files.internal(dir + f)).collect(toList()); } public Map<String, Discovery> getDiscoveries() { return discoveries; } public Collection<Culture> getCultures() { return Collections.unmodifiableCollection(cultures.values()); } public Culture getCulture(String name) { return cultures.get(name); } public Color guessColor() { List<Color> usedColors = empires.stream().map(Empire::getColor).collect(toList()); Optional<Color> color = COLORS.stream().filter(c -> !usedColors.contains(c)).findFirst(); if (color.isPresent()) return color.get(); else { // must use an existing color return COLORS.get(new Random().nextInt(COLORS.size())); } } private final Random rand = new Random(); public Culture guessCulture() { Map<Culture, Integer> usedCultures = cultures.values().stream().distinct() .collect(toMap(c -> c, c -> (int) empires.stream().filter(e -> e.culture == c).count())); List<Culture> list = cultures .values() .stream() .sorted( (c1, c2) -> -Integer.compare(c1.cities.size - usedCultures.get(c1), c2.cities.size - usedCultures.get(c2))) .limit(3).collect(toList()); if (list.isEmpty()) throw new IllegalStateException("No remaining culture!"); return list.get(abs(rand.nextInt() % list.size())); } }