Compare commits

...

2 Commits

Author SHA1 Message Date
f9bc9e4fa5
Added research, removed old code 2024-07-07 03:47:04 +02:00
a08c6e1c64
More OOP classes 2024-07-06 02:48:35 +02:00
40 changed files with 952 additions and 1699 deletions

View File

@ -28,6 +28,8 @@ dependencies {
implementation 'org.yaml:snakeyaml:2.2'
implementation 'org.ojalgo:ojalgo:54.0.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.1'
implementation 'org.json:json:20240303'
}
tasks.named('test') {

View File

@ -4,117 +4,28 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import com.bernard.greposimu.engine.Registerar;
import com.bernard.greposimu.engine.game.Buildings;
import com.bernard.greposimu.engine.json.MapJsonDeserializer;
import com.bernard.greposimu.model.Dieu;
import com.bernard.greposimu.model.Heros;
import com.bernard.greposimu.model.OffDefStats;
import com.bernard.greposimu.model.game.GameData;
import com.bernard.greposimu.model.game.Power;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.json.JSONObject;
import com.bernard.greposimu.model.game.GameConfig;
public class GrepoSimu {
public static GameData readGameData() throws IOException {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
public static GameConfig makeGameData() throws IOException {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
try (InputStream is = classLoader.getResourceAsStream("gamedata.json")) {
if (is == null) return null;
try (InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr)) {
// Reading the file
String json = reader.lines().collect(Collectors.joining(System.lineSeparator()));
// De-serialize to an object
JsonFactory jsonFactory = JsonFactory.builder()
.enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION)
.build();
SimpleModule module = new SimpleModule();
module.addDeserializer(Map.class, new MapJsonDeserializer());
ObjectMapper mapper = new ObjectMapper(jsonFactory);
mapper.registerModule(module);
GameData data = mapper.readValue(json, GameData.class);
JSONObject obj = new JSONObject(json);
// Adapting power map
Map<String,Power> pmap = new HashMap<>();
for(String id : data.powers.keySet()) {
Set<String> types = data.powers.get(id).getTypes();
if(types.isEmpty()) {
pmap.put(id, new Power(data.powers.get(id)));
} else {
for(String type : types) {
pmap.put(id+"."+type, new Power(data.powers.get(id), type));
}
}
}
data.powers = pmap;
System.out.println(data.powers.get("effort_of_the_huntress"));
return data;
return new GameConfig(obj);
}
}
}
public static void main(String[] args) {
for(int i=0;i<26;i++)
System.out.println(i+"->"+Buildings.wallBonus(i));
}
public static void mainZ(String[] args) {
Registerar.regiter();
System.out.println(Registerar.unites.size());
OffDefStats scoring = new OffDefStats(0, 0, 0, 1.0, 0,0,0,0);
for(Heros h : withNull(Registerar.heros)) {
if(h!= null && h.getNom()!="Agamemnon")continue;
for(int l = 1;l<=20&&h!=null;l+=10-(l%10)) {
for(Dieu d : withNull(Arrays.asList(Dieu.values()))) {
//System.out.println("Héros: "+((c.h==null)?"aucun":("%s (lvl %d)".formatted(h.getNom(),l)))+" - Dieu: "+((d==null)?"aucun":d.getNom()));
//up.print(h, l, 1000);
}
}
}
}
public static final <T> Iterable<T> withNull(Iterable<T> itrble) {
return (Iterable<T>) new Iterable<T>() {
@Override
public Iterator<T> iterator() {
Iterator<T> it = itrble.iterator();
return new Iterator<T>() {
boolean pastNull = false;
@Override
public boolean hasNext() {
return !pastNull || it.hasNext();
}
@Override
public T next() {
if(pastNull)
return it.next();
else {
pastNull = true;
return null;
}
}
};
};
};
}
}

View File

@ -1,15 +1,19 @@
package com.bernard.greposimu;
import java.io.IOException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.bernard.greposimu.engine.Registerar;
import com.bernard.greposimu.model.game.GameConfig;
@SpringBootApplication
public class GrepoSimuApplication {
public static void main(String[] args) {
Registerar.regiter();
public static GameConfig GREPOLIS_GC;
public static void main(String[] args) throws IOException {
GREPOLIS_GC = GrepoSimu.makeGameData();
SpringApplication.run(GrepoSimuApplication.class, args);
}

View File

@ -1,14 +0,0 @@
/*package com.bernard.greposimu;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(GrepoSimuApplication.class);
}
}
*/

View File

@ -6,6 +6,8 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.bernard.greposimu.model.game.Identified;
public class Utils {
public static final double poly5(double a0, double a1, double a2, double a3, double a4, double a5, double x) {
@ -18,6 +20,10 @@ public class Utils {
a5 * x * x * x * x * x;
}
public static final <T extends Identified> T getIdentified(Set<T> set, String id) {
return set.stream().filter(x -> x.getId().equals(id)).findAny().orElse(null);
}
public static final <T> Map<T,Boolean> setToMap(Set<T> set){
return new AbstractMap<T,Boolean>() {
@ -65,5 +71,4 @@ public class Utils {
};
}
}

View File

@ -0,0 +1,19 @@
package com.bernard.greposimu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.bernard.greposimu.GrepoSimuApplication;
@Controller
public class GameDataController {
@GetMapping("/gamedata")
public String gamedata(Model model) {
System.out.println("Reading game data");
model.addAttribute("content",GrepoSimuApplication.GREPOLIS_GC);
return "debug";
}
}

View File

@ -1,291 +0,0 @@
package com.bernard.greposimu.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import com.bernard.greposimu.GrepoSimu;
import com.bernard.greposimu.engine.Optimizer;
import com.bernard.greposimu.engine.Optimizer.UnitesProportions;
import com.bernard.greposimu.engine.Registerar;
import com.bernard.greposimu.engine.game.Fight;
import com.bernard.greposimu.engine.game.Game;
import com.bernard.greposimu.model.DefContext;
import com.bernard.greposimu.model.Dieu;
import com.bernard.greposimu.model.FightStats;
import com.bernard.greposimu.model.Heros;
import com.bernard.greposimu.model.OffDefStats;
import com.bernard.greposimu.model.Unite;
import com.bernard.greposimu.model.game.GameData;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@Controller
public class GrepoSimuController {
@GetMapping("/gamedata")
public String gamedata(Model model) {
System.out.println("Reading game data");
GameData data;
try {
data = GrepoSimu.readGameData();
model.addAttribute("content",data.toString());
} catch (IOException e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
model.addAttribute("content",writer.toString());
}
return "debug";
}
@GetMapping("/simulator")
public String simulator(Model model) throws IOException {
GameData data = GrepoSimu.readGameData();
model.addAttribute("heroes", data.heroes.values());
model.addAttribute("defUnits", Fight.relevantDefUnits(data));
model.addAttribute("defCounsellors",Fight.relevantDefCounsellors(data));
model.addAttribute("defResearches",Fight.relevantDefResearch(data));
model.addAttribute("defPowers",Fight.relevantDefPowers(data));
model.addAttribute("defCtx",new DefContext());
return "simulator";
}
@PostMapping("/simulate")
@GetMapping("/simulate")
public String simulate(@ModelAttribute DefContext defCtx, Model model) throws IOException {
if(defCtx == null)
defCtx = new DefContext();
GameData data = GrepoSimu.readGameData();
Game g = new Game(data);
FightStats cityStats = g.fight.computeDefStats(defCtx);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
model.addAttribute("content",cityStats.toString()+"\n"+mapper.writerWithDefaultPrettyPrinter().writeValueAsString(defCtx));
return "debug";
}
@GetMapping("/optimizer")
public String greeting(Model model) {
model.addAttribute("heros", Registerar.heros);
// Liste des unités
Map<String,List<Unite>> godUnites = Registerar.unites.stream()
.filter(u -> u.getDieu() != null)
.collect(Collectors.groupingBy(u -> u.getDieu().getPname()));
List<Unite> otherUnites = Registerar.unites.stream()
.filter(u -> u.getDieu() == null)
.collect(Collectors.toList());
System.out.println(godUnites);
model.addAttribute("otherunites", otherUnites);
model.addAttribute("godunites", godUnites);
model.addAttribute("dieux", Arrays.stream(Dieu.values()).map(Dieu::getPname).collect(Collectors.toList()));
model.addAttribute("optinput", new OptimizerInput());
return "optimizer";
}
@PostMapping("/optimizer")
public String greetingSubmit(@ModelAttribute OptimizerInput optinput, Model model) {
Optimizer.Contexte ctx = new Optimizer.Contexte();
ctx.h = Registerar.getHeros(optinput.heros);
ctx.level = optinput.herosLvl;
ctx.scoring = optinput.getOffDefStats();
ctx.d = null;
Set<Unite> unites = Registerar.unites.stream().filter(u -> optinput.unites.get(u.getPname())).collect(Collectors.toSet());
Map<String,OptimizerOutput> outputs = new HashMap<>();
outputs.put("none", new OptimizerOutput(Optimizer.optimize(ctx,unites), ctx.h, ctx.level, optinput.population));
for(Dieu d : Dieu.values()) {
ctx.d = d;
outputs.put(d.getPname(), new OptimizerOutput(Optimizer.optimize(ctx,unites), ctx.h, ctx.level, optinput.population));
}
model.addAttribute("dieux", Arrays.stream(Dieu.values()).map(Dieu::getPname).collect(Collectors.toList()));
model.addAttribute("outputs", outputs);
model.addAttribute("requestedPop",optinput.population);
return "optimizerResult";
}
public static class OptimizerInput {
public String heros = Registerar.heros.stream().map(Heros::getPname).min(Comparator.comparing(Function.identity())).get();
public int herosLvl = 1;
public double att_hack_proportion = 0.0;
public double att_pierce_proportion = 0.0;
public double att_distance_proportion = 0.0;
public double ship_attack_proportion = 0.0;
public double def_hack_proportion = 1.0;
public double def_pierce_proportion = 1.0;
public double def_distance_proportion = 1.0;
public double ship_defense_proportion = 1.0;
public int population = 1000;
public Map<String,Boolean> unites = Registerar.unites.stream().collect(Collectors.toMap(Unite::getPname, u -> true));
public String getHeros() {
return heros;
}
public void setHeros(String heros) {
this.heros = heros;
}
public int getHerosLvl() {
return herosLvl;
}
public void setHerosLvl(int herosLvl) {
this.herosLvl = herosLvl;
}
public double getAtt_hack_proportion() {
return att_hack_proportion;
}
public void setAtt_hack_proportion(double att_hack_proportion) {
this.att_hack_proportion = att_hack_proportion;
}
public double getAtt_pierce_proportion() {
return att_pierce_proportion;
}
public void setAtt_pierce_proportion(double att_pierce_proportion) {
this.att_pierce_proportion = att_pierce_proportion;
}
public double getAtt_distance_proportion() {
return att_distance_proportion;
}
public void setAtt_distance_proportion(double att_distance_proportion) {
this.att_distance_proportion = att_distance_proportion;
}
public double getShip_attack_proportion() {
return ship_attack_proportion;
}
public void setShip_attack_proportion(double ship_attack_proportion) {
this.ship_attack_proportion = ship_attack_proportion;
}
public double getDef_hack_proportion() {
return def_hack_proportion;
}
public void setDef_hack_proportion(double def_hack_proportion) {
this.def_hack_proportion = def_hack_proportion;
}
public double getDef_pierce_proportion() {
return def_pierce_proportion;
}
public void setDef_pierce_proportion(double def_pierce_proportion) {
this.def_pierce_proportion = def_pierce_proportion;
}
public double getDef_distance_proportion() {
return def_distance_proportion;
}
public void setDef_distance_proportion(double def_distance_proportion) {
this.def_distance_proportion = def_distance_proportion;
}
public double getShip_defense_proportion() {
return ship_defense_proportion;
}
public void setShip_defense_proportion(double ship_defense_proportion) {
this.ship_defense_proportion = ship_defense_proportion;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
public Map<String, Boolean> getUnites() {
return unites;
}
public void setUnites(Map<String, Boolean> unites) {
this.unites = unites;
}
public OffDefStats getOffDefStats() {
return new OffDefStats(att_hack_proportion, att_pierce_proportion, att_distance_proportion, ship_attack_proportion, def_hack_proportion, def_pierce_proportion, def_distance_proportion, ship_defense_proportion);
}
@Override
public String toString() {
return "OptimizerInput [heros=" + heros + ", herosLvl=" + herosLvl + ", att_hack_proportion="
+ att_hack_proportion + ", att_pierce_proportion=" + att_pierce_proportion
+ ", att_distance_proportion=" + att_distance_proportion + ", ship_attack_proportion="
+ ship_attack_proportion + ", def_hack_proportion=" + def_hack_proportion
+ ", def_pierce_proportion=" + def_pierce_proportion + ", def_distance_proportion="
+ def_distance_proportion + ", ship_defense_proportion=" + ship_defense_proportion + ", population="
+ population + ", unites=" + unites + "]";
}
}
public static class OptimizerOutput {
OffDefStats total;
int totalpop;
List<Unite> unites;
Map<Unite,Integer> ucounts;
public OptimizerOutput(UnitesProportions data, Heros h, int level, int pop) {
this.ucounts = new HashMap<>(data.getData().size());
for(Unite u : data.getData().keySet())
this.ucounts.put(u, (int) Math.floor((data.getData().get(u) * pop) / u.getPopulation()));
this.unites = Registerar.unites.stream().filter(u -> ucounts.containsKey(u)).toList();
this.totalpop = this.ucounts.entrySet().stream().mapToInt(e -> e.getKey().getPopulation() * e.getValue()).sum();
this.total = this.ucounts.entrySet().stream()
.map(e -> ((h==null)?e.getKey().getStats():h.applyToUnit(e.getKey(), level)).times(e.getValue()))
.reduce(OffDefStats.zero,(a,b) -> a.plus(b));
}
public OffDefStats getTotal() {
return total;
}
public int getTotalpop() {
return totalpop;
}
public Map<Unite, Integer> getUcounts() {
return ucounts;
}
public List<Unite> getUnites() {
return unites;
}
}
}

View File

@ -0,0 +1,157 @@
package com.bernard.greposimu.controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import com.bernard.greposimu.GrepoSimuApplication;
import com.bernard.greposimu.Utils;
import com.bernard.greposimu.engine.game.Fight;
import com.bernard.greposimu.model.DefContext;
import com.bernard.greposimu.model.FightStats;
import com.bernard.greposimu.model.game.GameConfig;
import com.bernard.greposimu.model.game.units.Unit;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@Controller
public class SimulatorController {
@GetMapping("/simulator")
public String simulator(Model model) throws IOException {
GameConfig gc = GrepoSimuApplication.GREPOLIS_GC;
model.addAttribute("heroes", gc.getHeroes());
model.addAttribute("defUnits", Fight.relevantDefUnits(gc));
model.addAttribute("defCounsellors",Fight.relevantDefCounsellors(gc));
model.addAttribute("defResearches",Fight.relevantDefResearch(gc));
model.addAttribute("defPowers",Fight.relevantDefPowers(gc));
model.addAttribute("ctx",new DefSimulatorParams());
return "simulator";
}
@PostMapping("/simulate")
@GetMapping("/simulate")
public String simulate(@ModelAttribute DefSimulatorParams defParams, Model model) throws IOException {
if(defParams == null)
defParams = new DefSimulatorParams();
GameConfig gc = GrepoSimuApplication.GREPOLIS_GC;
DefContext defCtx = defParams.asDefContext(gc);
FightStats cityStats = Fight.computeDefStats(gc,defCtx);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
model.addAttribute("content",cityStats.toString()+"\n"+mapper.writerWithDefaultPrettyPrinter().writeValueAsString(defCtx));
return "debug";
}
public static class DefSimulatorParams {
// unitID -> number of units
public Map<String, Integer> units = new HashMap<>();
public String hero = "";
public int heroLevel = 0;
public int wallLevel = 0;
public boolean hasTower = false;
public Set<String> powers = new HashSet<>();
public Set<String> researches = new HashSet<>();
public Set<String> counsellors = new HashSet<>();
public boolean nightBonus = false;
public DefContext asDefContext(GameConfig gc) {
Map<Unit,Integer> unitsU = new HashMap<>(units.size());
for(String u : units.keySet())
unitsU.put(gc.getUnit(u), units.get(u));
return new DefContext(
unitsU,
gc.getHero(hero),
heroLevel,
wallLevel,
hasTower,
powers,
researches,
counsellors,
nightBonus
);
}
public Map<String, Integer> getUnits() {
return units;
}
public void setUnits(Map<String, Integer> units) {
this.units = units;
}
public String getHero() {
return hero;
}
public void setHero(String hero) {
this.hero = hero;
}
public int getHeroLevel() {
return heroLevel;
}
public void setHeroLevel(int heroLevel) {
this.heroLevel = heroLevel;
}
public int getWallLevel() {
return wallLevel;
}
public void setWallLevel(int wallLevel) {
this.wallLevel = wallLevel;
}
public boolean isHasTower() {
return hasTower;
}
public void setHasTower(boolean hasTower) {
this.hasTower = hasTower;
}
public Set<String> getPowers() {
return powers;
}
public Map<String,Boolean> getPowersAsMap() {
return Utils.setToMap(powers);
}
public Map<String,Boolean> getResearchesAsMap() {
return Utils.setToMap(researches);
}
public Map<String,Boolean> getCounsellorsAsMap() {
return Utils.setToMap(counsellors);
}
public boolean isNightBonus() {
return nightBonus;
}
public void setNightBonus(boolean nightBonus) {
this.nightBonus = nightBonus;
}
}
}

View File

@ -1,116 +0,0 @@
package com.bernard.greposimu.engine;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.ojalgo.optimisation.Expression;
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.Optimisation;
import org.ojalgo.optimisation.Optimisation.Result;
import org.ojalgo.optimisation.Variable;
import com.bernard.greposimu.model.Dieu;
import com.bernard.greposimu.model.Heros;
import com.bernard.greposimu.model.OffDefStats;
import com.bernard.greposimu.model.Unite;
public class Optimizer {
public static UnitesProportions optimize(Contexte c,Set<Unite> uniteList) {
// Computing the stats of the unités in this context
Map<Unite,OffDefStats> stats = uniteList.stream()
.filter(u -> u.getDieu() == null || u.getDieu().equals(c.d))
.collect(Collectors.toMap(
Function.identity(),
u -> (OffDefStats)((c.h==null)?u.getStats():c.h.applyToUnit(u, c.level)).div(u.getPopulation())
));
// Clean list of unités
List<Unite> unites = stats.keySet().stream().sorted((u,v) -> u.getNom().compareTo(v.getNom())).toList();
// Création du modèle
ExpressionsBasedModel model = new ExpressionsBasedModel();
// Variable à optimiser
Variable y = model.addVariable("y").weight(1.0);
// Création des variables correspondant aux proportions, elles ne sont pas «optimisées» (weight 0.0) et sont positives
List<Variable> varz = new ArrayList<>(unites.size());
for(Unite u : unites) {
Variable xi = model.addVariable(u.getNom()).weight(0.0);
model.addExpression().lower(0.0).set(xi, 1.0); // 0 <= x_i
varz.add(xi);
}
// Les proportions doivent être maximalement 1 (en pratique, 1, parce que croissante)
Expression esum = model.addExpression().upper(1.0);
// y doit se comparer à chaque somme suivant ce que le scoring précise
Expression eAttqCont = model.addExpression().lower(0.0).set(y, -c.scoring.getAttqCont()); // y <= sum(a_1_i * x_i)
Expression eAttqBlan = model.addExpression().lower(0.0).set(y, -c.scoring.getAttqBlan()); // y <= sum(a_1_i * x_i)
Expression eAttqJet = model.addExpression().lower(0.0).set(y, -c.scoring.getAttqJet() ); // y <= sum(a_1_i * x_i)
Expression eAttqNav = model.addExpression().lower(0.0).set(y, -c.scoring.getAttqNav() ); // y <= sum(a_1_i * x_i)
Expression eDefCont = model.addExpression().lower(0.0).set(y, -c.scoring.getDefCont() ); // y <= sum(a_1_i * x_i)
Expression eDefBlan = model.addExpression().lower(0.0).set(y, -c.scoring.getDefBlan() ); // y <= sum(a_1_i * x_i)
Expression eDefJet = model.addExpression().lower(0.0).set(y, -c.scoring.getDefJet() ); // y <= sum(a_1_i * x_i)
Expression eDefNav = model.addExpression().lower(0.0).set(y, -c.scoring.getDefNav() ); // y <= sum(a_1_i * x_i)
for(int i=0;i<varz.size();i++) {
esum.set(varz.get(i), 1.0);
eAttqCont.set(varz.get(i), stats.get(unites.get(i)).getAttqCont());
eAttqBlan.set(varz.get(i), stats.get(unites.get(i)).getAttqBlan());
eAttqJet .set(varz.get(i), stats.get(unites.get(i)).getAttqJet());
eAttqNav .set(varz.get(i), stats.get(unites.get(i)).getAttqNav());
eDefCont .set(varz.get(i), stats.get(unites.get(i)).getDefCont());
eDefBlan .set(varz.get(i), stats.get(unites.get(i)).getDefBlan());
eDefJet .set(varz.get(i), stats.get(unites.get(i)).getDefJet());
eDefNav .set(varz.get(i), stats.get(unites.get(i)).getDefNav());
}
Result r = model.maximise(); // maximize y
return new UnitesProportions(unites, r);
}
public static class UnitesProportions {
Map<Unite,Double> data;
public UnitesProportions(List<Unite> unites, Optimisation.Result result) {
this.data = new HashMap<>();
for(int i=0;i<unites.size();i++) {
double val = result.doubleValue(1+i);
if(val>=0.0001) {
this.data.put(unites.get(i), val);
}
}
}
public void print(Heros h, int level, int pop) {
Map<Unite,Integer> ucounts = new HashMap<>(data.size());
for(Unite u : data.keySet())
ucounts.put(u, (int) Math.floor((data.get(u) * pop) / u.getPopulation()));
int totalpop = ucounts.entrySet().stream().mapToInt(e -> e.getKey().getPopulation() * e.getValue()).sum();
OffDefStats t = ucounts.entrySet().stream()
.map(e -> h.applyToUnit(e.getKey(), level).times(e.getValue()))
.reduce(OffDefStats.zero,(a,b) -> a.plus(b));
System.out.println("Population totale de %d".formatted(totalpop));
for(Unite u : data.keySet())
System.out.println("|-- %d %s (%.1f%% de la population)".formatted(ucounts.get(u),u.getNom(),data.get(u)*100));
System.out.println("--- Attaque (%d,%d,%d,%d) Défense (%d,%d,%d,%d)".formatted(
(int)t.getAttqCont(),(int)t.getAttqBlan(),(int)t.getAttqJet(),(int)t.getAttqNav(),(int)t.getDefCont(),(int)t.getDefBlan(),(int)t.getDefJet(),(int)t.getDefNav()
));
}
public Map<Unite, Double> getData() {
return data;
}
}
public static class Contexte {
public Dieu d;
public Heros h;
public int level;
public OffDefStats scoring;
}
}

View File

@ -1,114 +0,0 @@
package com.bernard.greposimu.engine;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.bernard.greposimu.model.Dieu;
import com.bernard.greposimu.model.Heros;
import com.bernard.greposimu.model.OffDefStats;
import com.bernard.greposimu.model.Unite;
public class Registerar {
public static List<Unite> unites;
public static List<Heros> heros;
public static Heros getHeros(String pname) {
return heros.stream().filter(h -> h.getPname().equals(pname)).findAny().orElse(null);
}
public static List<Unite> getUnites(Dieu dieu) {
return unites.stream().filter(u -> u.getDieu() == null || u.getDieu().equals(dieu)).collect(Collectors.toList());
}
public static void addHeros(
String nom,
String pname,
Set<String> appliedToNames,
boolean appTerrestre,
boolean appNavale,
boolean appMythique,
double attqContZero,
double attqContPlus,
double attqBlanZero,
double attqBlanPlus,
double attqJetZero,
double attqJetPlus,
double attqNavZero,
double attqNavPlus,
double defContZero,
double defContPlus,
double defBlanZero,
double defBlanPlus,
double defJetZero,
double defJetPlus,
double defNavZero,
double defNavPlus) {
heros.add(new Heros(
nom, pname, appliedToNames, appTerrestre, appNavale, appMythique,
new OffDefStats(attqContZero, attqBlanZero, attqJetZero, attqNavZero, defContZero, defBlanZero, defJetZero, defNavZero),
new OffDefStats(attqContPlus, attqBlanPlus, attqJetPlus, attqNavPlus, defContPlus, defBlanPlus, defJetPlus, defNavPlus)
));
}
public static void addUnite(String nom, String pname, int population, int speed, int butin, double attqCont, double attqBlan, double attqJet, double attqNav, double defCont, double defBlan,
double defJet, double defNav, boolean terrestre, boolean navale,
boolean mythique, Dieu dieu) {
unites.add(new Unite(
nom, pname, population, speed, butin,
new OffDefStats(attqCont, attqBlan, attqJet, attqNav, defCont, defBlan, defJet, defNav),
terrestre, navale, mythique, dieu
));
}
public static void regiter() {
unites = new ArrayList<Unite>();
addUnite("Combattant à l'épée","sword",1,8,16,5.0,0.0,0.0,0.0,14.0,8.0,30.0,0.0,true,false,false,null);
addUnite("Frondeur","slinger",1,14,8,0.0,0.0,23.0,0.0,7.0,8.0,2.0,0.0,true,false,false,null);
addUnite("Archer","archer",1,12,24,0.0,0.0,8.0,0.0,7.0,25.0,13.0,0.0,true,false,false,null);
addUnite("Hoplite","hoplite",1,6,8,0.0,16.0,0.0,0.0,18.0,12.0,7.0,0.0,true,false,false,null);
addUnite("Cavalier","rider",3,22,72,60.0,0.0,0.0,0.0,18.0,1.0,24.0,0.0,true,false,false,null);
addUnite("Char","chariot",4,18,64,0.0,56.0,0.0,0.0,76.0,16.0,56.0,0.0,true,false,false,null);
addUnite("Catapulte","catapult",15,2,400,0.0,0.0,100.0,0.0,30.0,30.0,30.0,0.0,true,false,false,null);
addUnite("Envoyé divin","godsent",3,16,5,45.0,0.0,0.0,0.0,40.0,40.0,40.0,0.0,true,false,true,null);
addUnite("Centaure","centaur",12,18,200,0.0,0.0,134.0,0.0,195.0,585.0,80.0,0.0,true,false,true,Dieu.ATHENA);
addUnite("Cerbère","cerberus",30,4,240,210.0,0.0,0.0,0.0,825.0,300.0,1575.0,0.0,true,false,true,Dieu.HADES);
addUnite("Cyclope","zyklop",40,8,320,0.0,0.0,1035.0,0.0,1050.0,10.0,1450.0,0.0,true,false,true,Dieu.POSEIDON);
addUnite("Érinye","fury",55,10,440,0.0,0.0,1700.0,0.0,460.0,460.0,595.0,0.0,true,false,true,Dieu.HADES);
addUnite("Méduse","medusa",18,6,400,0.0,425.0,0.0,0.0,480.0,345.0,290.0,0.0,true,false,true,Dieu.HERA);
addUnite("Minotaure","minotaur",30,10,480,650.0,0.0,0.0,0.0,750.0,330.0,640.0,0.0,true,false,true,Dieu.ZEUS);
addUnite("Sanglier","calydonian_boar",20,16,240,0.0,180.0,0.0,0.0,700.0,700.0,100.0,0.0,true,false,true,Dieu.ARTEMIS);
addUnite("Satyre","satyr",16,136,335,0.0,385.0,0.0,0.0,55.0,105.0,170.0,0.0,true,false,true,Dieu.APHRODITE);
addUnite("Sparte","spartoi",10,16,275,205.0,0.0,0.0,0.0,100.0,100.0,150.0,0.0,true,false,true,Dieu.ARES);
addUnite("Harpie","harpy",14,28,340,295.0,0.0,0.0,0.0,105.0,70.0,1.0,0.0,true,false,true,Dieu.HERA);
addUnite("Manticore","manticore",45,22,360,0.0,1010.0,0.0,0.0,170.0,225.0,505.0,0.0,true,false,true,Dieu.ZEUS);
addUnite("Pégase","pegasus",20,35,160,0.0,100.0,0.0,0.0,750.0,275.0,275.0,0.0,true,false,true,Dieu.ATHENA);
addUnite("Griffon","griffin",35,18,350,900.0,0.0,0.0,0.0,320.0,330.0,100.0,0.0,true,false,true,Dieu.ARTEMIS);
addUnite("Ladon","ladon",85,40,1000,0.0,0.0,1195.0,0.0,478.0,390.0,420.0,0.0,true,false,true,Dieu.ARES);
addUnite("Birème","bireme",8,15,0,0.0,0.0,0.0,24.0,0.0,0.0,0.0,160.0,false,true,false,null);
addUnite("Bateau-feu","attack_ship",10,13,0,0.0,0.0,0.0,200.0,0.0,0.0,0.0,60.0,false,true,false,null);
addUnite("Trière","trireme",16,15,0,0.0,0.0,0.0,250.0,0.0,0.0,0.0,250.0,false,true,false,null);
addUnite("Hydre","sea_monster",50,8,0,0.0,0.0,0.0,1310.0,0.0,0.0,0.0,1400.0,false,false,true,Dieu.POSEIDON);
addUnite("Sirène","siren",16,22,0,0.0,0.0,0.0,180.0,0.0,0.0,0.0,170.0,false,false,true,Dieu.APHRODITE);
//addUnite("Ladon (max)","ladon",85000,40,1000,0.0,0.0,2988.0,0.0,478.0,390.0,420.0,0.0,true,false,true,Dieu.ARES);
heros = new ArrayList<Heros>();
addHeros("Agamemnon","agamemnon",Set.of("hoplite","archer"),false,false,false,0.100,0.010,0.100,0.010,0.100,0.010,0.000,0.000,0.100,0.010,0.100,0.010,0.100,0.010,0.000,0.000);
addHeros("Ajax","ajax",Set.of("hoplites"),false,false,false,0.150,0.015,0.150,0.015,0.150,0.015,0.000,0.000,0.150,0.015,0.150,0.015,0.150,0.015,0.000,0.000);
addHeros("Alexandrios","alexandrios",Set.of("archers"),false,false,false,0.150,0.010,0.150,0.010,0.150,0.010,0.000,0.000,0.150,0.010,0.150,0.010,0.150,0.010,0.000,0.000);
addHeros("Déimos","deimos",Set.of(),true,true,true,0.050,0.005,0.050,0.005,0.050,0.005,0.050,0.005,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000);
addHeros("Hector","hector",Set.of("sword","slinger"),false,false,false,0.100,0.010,0.100,0.010,0.100,0.010,0.000,0.000,0.100,0.010,0.100,0.010,0.100,0.010,0.000,0.000);
addHeros("Lysippe","lysippe",Set.of("rider"),false,false,false,0.150,0.010,0.150,0.010,0.150,0.010,0.000,0.000,0.150,0.010,0.150,0.010,0.150,0.010,0.000,0.000);
addHeros("Léonidas","leonidas",Set.of(),true,true,true,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.050,0.005,0.050,0.005,0.050,0.005,0.050,0.005);
addHeros("Mihalis","mihalis",Set.of(),true,false,false,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.100,0.010,0.100,0.010,0.000,0.000,0.000,0.000);
addHeros("Médée","medea",Set.of("slinger"),false,false,false,0.150,0.015,0.150,0.015,0.150,0.015,0.000,0.000,0.150,0.015,0.150,0.015,0.150,0.015,0.000,0.000);
addHeros("Mélousa","melousa",Set.of("chariot"),false,false,false,0.150,0.010,0.150,0.010,0.150,0.010,0.000,0.000,0.150,0.010,0.150,0.010,0.150,0.010,0.000,0.000);
addHeros("Pélops","pelops",Set.of("hoplite","chariot"),false,false,false,0.100,0.010,0.100,0.010,0.100,0.010,0.000,0.000,0.100,0.010,0.100,0.010,0.100,0.010,0.000,0.000);
addHeros("Thémistocle","themistokles",Set.of("godsent","rider"),false,false,false,0.100,0.010,0.100,0.010,0.100,0.010,0.000,0.000,0.100,0.010,0.100,0.010,0.100,0.010,0.000,0.000);
addHeros("Télémaque","telemachos",Set.of("sword"),false,false,false,0.150,0.015,0.150,0.015,0.150,0.015,0.000,0.000,0.150,0.015,0.150,0.015,0.150,0.015,0.000,0.000);
addHeros("Urephon","urephon",Set.of(),false,false,true,0.050,0.005,0.050,0.005,0.050,0.005,0.050,0.005,0.050,0.005,0.050,0.005,0.050,0.005,0.050,0.005);
addHeros("Zuretha","zuretha",Set.of(),false,true,false,0.000,0.000,0.000,0.000,0.000,0.000,0.050,0.005,0.000,0.000,0.000,0.000,0.000,0.000,0.050,0.005);
}
}

View File

@ -6,32 +6,28 @@ import java.util.Map;
import com.bernard.greposimu.model.DefContext;
import com.bernard.greposimu.model.FightStats;
import com.bernard.greposimu.model.OffContext;
import com.bernard.greposimu.model.game.GameData;
import com.bernard.greposimu.model.game.Power;
import com.bernard.greposimu.model.game.Research;
import com.bernard.greposimu.model.game.Unit;
import com.bernard.greposimu.model.game.GameConfig;
import com.bernard.greposimu.model.game.researches.Research;
import com.bernard.greposimu.model.game.units.NavalUnit;
import com.bernard.greposimu.model.game.units.TerrestrialUnit;
import com.bernard.greposimu.model.game.units.Unit;
public class Fight {
Game g;
public Fight(Game g) {
this.g = g;
}
public FightStats computeDefStats(DefContext def) {
public static FightStats computeDefStats(GameConfig gc, DefContext def) {
//TODO replace def getters with more complex getters (.getCounsellors.contains -> .hasCounsellor; .getUnits.get -> .getUnitCount)
FightStats everyoneStatsBonus = FightStats.zero();
Map<String,FightStats> unitsBonuses;
Map<Unit,FightStats> unitsBonuses;
FightStats cityBaseStats;
// Heroes
unitsBonuses = g.heroes.heroFightBonuses(def.hero, def.heroLevel, false);
unitsBonuses = Heroes.heroFightBonuses(gc, def.getHero(), def.getHeroLevel(), false);
// Tower & wall
cityBaseStats = Buildings.cityBaseStats(def.wallLevel);
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, Buildings.wallBonus(def.wallLevel));
if(def.hasTower)
cityBaseStats = Buildings.cityBaseStats(def.getWallLevel());
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, Buildings.wallBonus(def.getWallLevel()));
if(def.hasTower())
// Add 10% to all units
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.cst(0.1));
@ -40,70 +36,81 @@ public class Fight {
//TODO powers
// Researches
if(def.counsellors.contains("divine_selection"))
for(String uid : g.data.units.keySet())
if(g.data.units.get(uid).isMythological())
unitsBonuses.put(uid, FightStats.add(unitsBonuses.getOrDefault(uid, FightStats.zero()), FightStats.cst(0.1)));
if(def.counsellors.contains("phalanx"))
for(String uid : g.data.units.keySet())
if(g.data.units.get(uid).isGround())
unitsBonuses.put(uid, FightStats.add(unitsBonuses.getOrDefault(uid, FightStats.zero()), FightStats.cst(0.1)));
if(def.counsellors.contains("ram"))
for(String uid : g.data.units.keySet())
if(g.data.units.get(uid).isNaval())
unitsBonuses.put(uid, FightStats.add(unitsBonuses.getOrDefault(uid, FightStats.zero()), FightStats.cst(0.1)));
if(def.getCounsellors().contains("divine_selection"))
for(Unit u : gc.getUnits())
if(u.isMythological())
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.1)));
if(def.getCounsellors().contains("phalanx"))
for(Unit u : gc.getUnits())
if(u.isGround())
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.1)));
if(def.getCounsellors().contains("ram"))
for(Unit u : gc.getUnits())
if(u.isNaval())
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.1)));
// Counsellors
if(def.counsellors.contains("priest"))
for(String uid : g.data.units.keySet())
if(g.data.units.get(uid).isMythological())
unitsBonuses.put(uid, FightStats.add(unitsBonuses.getOrDefault(uid, FightStats.zero()), FightStats.cst(0.2)));
if(def.counsellors.contains("commander"))
for(String uid : g.data.units.keySet())
if(g.data.units.get(uid).isGround())
unitsBonuses.put(uid, FightStats.add(unitsBonuses.getOrDefault(uid, FightStats.zero()), FightStats.cst(0.2)));
if(def.counsellors.contains("captain"))
for(String uid : g.data.units.keySet())
if(g.data.units.get(uid).isNaval())
unitsBonuses.put(uid, FightStats.add(unitsBonuses.getOrDefault(uid, FightStats.zero()), FightStats.cst(0.2)));
if(def.getCounsellors().contains("priest"))
for(Unit u : gc.getUnits())
if(u.isMythological())
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.2)));
if(def.getCounsellors().contains("commander"))
for(Unit u : gc.getUnits())
if(u.isGround())
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.2)));
if(def.getCounsellors().contains("captain"))
for(Unit u : gc.getUnits())
if(u.isNaval())
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.2)));
// Night Bonus
if(def.nightBonus)
if(def.isNightBonus())
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.cst(1.0));
// Units
FightStats total = cityBaseStats.clone();
for(Unit u : g.data.units.values()) {
for(Unit u : gc.getUnits()) {
// total = total + ucount * ((1+bonus+bonus) * ustats)
if(def.units.containsKey(u.id) && def.units.get(u.id) != null)
if(def.getUnits().containsKey(u) && def.getUnits().get(u) != null)
total = FightStats.add(total,
FightStats.prod(def.units.get(u.id),
FightStats.prod(def.getUnits().get(u),
FightStats.mul(
FightStats.add(FightStats.one(),everyoneStatsBonus,unitsBonuses.getOrDefault(u.id, FightStats.zero()))
, u.getDefStats())
FightStats.add(FightStats.one(),everyoneStatsBonus,unitsBonuses.getOrDefault(u, FightStats.zero()))
, makeDefStats(u))
));
}
return total;
}
public static List<Power> relevantDefPowers(GameData gd) {
System.out.println(gd.powers);
return List.of("acumen", "divine_senses", "myrmidion_attack", "trojan_defense", "defense_boost",
public static FightStats makeDefStats(Unit u) {
if(u instanceof TerrestrialUnit) {
TerrestrialUnit tu = (TerrestrialUnit)u;
return new FightStats(tu.getHackDef(), tu.getPierceDef(), tu.getDistanceDef(), 0.0);
}else if(u instanceof NavalUnit) {
NavalUnit nu = (NavalUnit)u;
return new FightStats(0.0, 0.0, 0.0, nu.getDefense());
}
throw new UnsupportedOperationException("I don't know how to manage units of type "+u.getClass().getName());
}
public static List<Object> relevantDefPowers(GameConfig gd) {
return List.of();
/*List.of("acumen", "divine_senses", "myrmidion_attack", "trojan_defense", "defense_boost",
"defense_penalty", "longterm_defense_boost", "assassins_acumen", "rare_defense_boost",
"epic_defense_boost", "olympic_torch.grepolympia_summer", "olympic_senses.grepolympia_summer", "missions_power_4.missions_dionysia",
"divine_battle_strategy_rare", "divine_battle_strategy_epic", "naval_battle_strategy_rare",
"naval_battle_strategy_epic", "land_battle_strategy_rare", "land_battle_strategy_epic",
"soterias_shrine.not_cast").stream().map(gd.powers::get).map(p -> (Power)p).toList();
"soterias_shrine.not_cast").stream().map(gd.powers::get).map(p -> (Power)p).toList();*/
}
public static List<Research> relevantDefResearch(GameData gd) {
public static List<Research> relevantDefResearch(GameConfig gd) {
return List.of("divine_selection","phalanx","ram")
.stream().map(gd.researches::get).toList();
.stream().map(gd::getResearch).toList();
}
public static List<Unit> relevantDefUnits(GameData data) {
return data.units.values().stream().toList();
public static List<Unit> relevantDefUnits(GameConfig gc) {
return gc.getUnits().stream().toList();
}
public static List<String> relevantDefCounsellors(GameData data) {
public static List<String> relevantDefCounsellors(GameConfig data) {
return List.of("priest","commander","captain");
}
public FightStats computeOffStats(DefContext off) {

View File

@ -1,20 +1,14 @@
package com.bernard.greposimu.engine.game;
import com.bernard.greposimu.model.game.GameData;
import com.bernard.greposimu.model.game.GameConfig;
public class Game {
GameData data;
public Heroes heroes;
public Buildings buildings;
public Fight fight;
GameConfig data;
public Game(GameData data) {
public Game(GameConfig data) {
this.data = data;
this.heroes = new Heroes(this);
this.buildings = new Buildings(this);
this.fight = new Fight(this);
}
}

View File

@ -2,47 +2,33 @@ package com.bernard.greposimu.engine.game;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import com.bernard.greposimu.model.FightStats;
import com.bernard.greposimu.model.game.Hero;
import com.bernard.greposimu.model.game.GameConfig;
import com.bernard.greposimu.model.game.units.Hero;
import com.bernard.greposimu.model.game.units.Unit;
public class Heroes {
Game g;
public Heroes(Game g) {
this.g = g;
}
/**
* Compute the bonus applied to each unit
* @param hero The uid of the hero
* @param hero The hero object to consider
* @param level The level of the hero
* @param off true for the off stat, false for the def stat
* @return For each unit, the bonus that should be applied to it
*/
public Map<String,FightStats> heroFightBonuses(String hero, int level, boolean off){
Map<String,FightStats> bonuses = new HashMap<>();
public static Map<Unit, FightStats> heroFightBonuses(GameConfig gc, Hero hero, int level, boolean off){
if(hero == null)
return new HashMap<>();
double bonus = 0.0;
Hero heroD = g.data.heroes.get(hero);
if(heroD != null && heroD.description_args != null && heroD.description_args.containsKey("1")) {
Hero.DescriptionArgs args = heroD.description_args.get("1");
if(args.unit.equals("%"))
bonus = args.value + level * args.level_mod;
else
throw new UnsupportedOperationException("I don't know about unit "+args.unit);
}
Map<String,FightStats> bonuses = new HashMap<>();
double bonus = hero.getPowerBaseValue() + level * hero.getPowerValuePerLevel();
FightStats appliedBonus = null;
switch(hero) {
switch(hero.getId()) {
case "agamemnon":
appliedBonus = FightStats.terrestre(bonus);
bonuses.put("hoplite", appliedBonus);
@ -59,7 +45,7 @@ public class Heroes {
case "deimos":
appliedBonus = FightStats.cst(bonus);
if(off)
for(String uid : g.data.units.keySet())bonuses.put(uid,appliedBonus);
for(Unit u : gc.getUnits())bonuses.put(u.getId(),appliedBonus);
break;
case "hector":
appliedBonus = FightStats.terrestre(bonus);
@ -73,11 +59,11 @@ public class Heroes {
case "leonidas":
appliedBonus = FightStats.terrestre(bonus);
if(!off)
for(String uid : g.data.units.keySet())bonuses.put(uid,appliedBonus);
for(Unit u : gc.getUnits())bonuses.put(u.getId(),appliedBonus);
break;
case "mihalis":
appliedBonus = new FightStats(bonus, bonus, 0.0, 0.0);
for(String uid : g.data.units.keySet())bonuses.put(uid,appliedBonus);
for(Unit u : gc.getUnits())bonuses.put(u.getId(),appliedBonus);
break;
case "medea":
appliedBonus = FightStats.terrestre(bonus);
@ -103,17 +89,17 @@ public class Heroes {
break;
case "urephon":
appliedBonus = FightStats.terrestre(bonus);
for(String uid : g.data.units.keySet())if(g.data.units.get(uid).isMythological())bonuses.put(uid,appliedBonus);
for(Unit u : gc.getUnits())if(u.isMythological())bonuses.put(u.getId(),appliedBonus);
break;
case "zuretha":
appliedBonus = new FightStats(0.0, 0.0, 0.0, bonus);
for(String uid : g.data.units.keySet())bonuses.put(uid,appliedBonus);
for(Unit u : gc.getUnits())bonuses.put(u.getId(),appliedBonus);
break;
default:
// No buff
break;
}
return bonuses;
return bonuses.keySet().stream().collect(Collectors.toMap(k -> gc.getUnit(k), k -> bonuses.get(k)));
}
}

View File

@ -1,57 +0,0 @@
package com.bernard.greposimu.engine.json;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
public class MapJsonDeserializer extends StdDeserializer<Map<String,?>> implements ContextualDeserializer{
private static final long serialVersionUID = -888029778299077908L;
private JavaType type;
public MapJsonDeserializer() {
super(Object.class);
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException{
MapJsonDeserializer deserializer = new MapJsonDeserializer();
if(property != null)
deserializer.type = property.getType().containedType(1);
else
deserializer.type = ctxt.getContextualType();
return deserializer;
}
@Override
public Map<String,?> deserialize(JsonParser parser, DeserializationContext deserializationContext) throws IOException {
JsonNode node = parser.getCodec().readTree(parser);
if(node.isNull() || (node.isArray() && node.isEmpty()))
return new HashMap<>();
else if(node.isObject()) {
ObjectCodec codec = parser.getCodec();
Map<String,Object> output = new HashMap<>();
java.util.Iterator<Entry<String, JsonNode>> it = node.fields();
while(it.hasNext()) {
Entry<String, JsonNode> entry = it.next();
output.put(entry.getKey(), entry.getValue().traverse(codec).readValueAs(this.type.getRawClass()));
}
return output;
} else
throw MismatchedInputException.from(parser, Map.class, "JSON is neither an empty array nor a map");
}
}

View File

@ -1,110 +1,72 @@
package com.bernard.greposimu.model;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.bernard.greposimu.Utils;
import com.bernard.greposimu.model.game.units.Hero;
import com.bernard.greposimu.model.game.units.Unit;
public class DefContext {
// unitID -> number of units
public Map<String, Integer> units;
Map<Unit, Integer> units;
public String hero;
public int heroLevel;
Hero hero;
int heroLevel;
public int wallLevel;
public boolean hasTower;
int wallLevel;
boolean hasTower;
public Set<String> powers;
public Set<String> researches;
Set<String> powers;
Set<String> researches;
public Set<String> counsellors;
Set<String> counsellors;
public boolean nightBonus;
boolean nightBonus;
public DefContext() {
this.units = new HashMap<>();
this.hero = null;
this.heroLevel = 0;
this.wallLevel = 0;
this.hasTower = false;
this.powers = new HashSet<>();
this.researches = new HashSet<>();
this.counsellors = new HashSet<>();
this.nightBonus = false;
}
public Map<String, Integer> getUnits() {
public DefContext(Map<Unit, Integer> units, Hero hero, int heroLevel, int wallLevel, boolean hasTower,
Set<String> powers, Set<String> researches, Set<String> counsellors, boolean nightBonus) {
this.units = units;
this.hero = hero;
this.heroLevel = heroLevel;
this.wallLevel = wallLevel;
this.hasTower = hasTower;
this.powers = powers;
this.researches = researches;
this.counsellors = counsellors;
this.nightBonus = nightBonus;
}
public Map<Unit, Integer> getUnits() {
return units;
}
public String getHero() {
public Hero getHero() {
return hero;
}
public int getHeroLevel() {
return heroLevel;
}
public int getWallLevel() {
return wallLevel;
}
public boolean isHasTower() {
public boolean hasTower() {
return hasTower;
}
public Set<String> getPowers() {
return powers;
}
public Set<String> getResearches() {
return researches;
}
public Set<String> getCounsellors() {
return counsellors;
}
public Map<String, Boolean> getPowersAsMap() {
return Utils.setToMap(powers);
}
public Map<String, Boolean> getResearchesAsMap() {
return Utils.setToMap(researches);
}
public Map<String, Boolean> getCounsellorsAsMap() {
return Utils.setToMap(counsellors);
}
public boolean isNightBonus() {
return nightBonus;
}
public void setHero(String hero) {
this.hero = hero;
}
public void setHeroLevel(int heroLevel) {
this.heroLevel = heroLevel;
}
public void setWallLevel(int wallLevel) {
this.wallLevel = wallLevel;
}
public void setHasTower(boolean hasTower) {
this.hasTower = hasTower;
}
public void setNightBonus(boolean nightBonus) {
this.nightBonus = nightBonus;
}
@Override
public String toString() {

View File

@ -1,28 +0,0 @@
package com.bernard.greposimu.model;
public enum Dieu {
ZEUS("Zeus","zeus"),
POSEIDON("Poséidon","poseidon"),
HERA("Héra","hera"),
ATHENA("Athéna","athena"),
HADES("Hadès","hades"),
ARTEMIS("Artémis","artemis"),
APHRODITE("Aphrodite","aphrodite"),
ARES("Arès","ares");
String nom;
String pname;
Dieu(String nom,String pname){
this.nom = nom;
this.pname = pname;
}
public String getNom() {
return nom;
}
public String getPname() {
return pname;
}
}

View File

@ -1,87 +0,0 @@
package com.bernard.greposimu.model;
import java.util.Set;
public class Heros {
String nom;
String pname;
Set<String> appliedToNames;
boolean appTerrestre,appNavale,appMythique;
OffDefStats statsZero;
OffDefStats statsPlus;
public Heros(String nom, String pname, Set<String> appliedToNames, boolean appTerrestre, boolean appNavale, boolean appMythique,
OffDefStats statsZero, OffDefStats statsPlus) {
this.nom = nom;
this.pname = pname;
this.appliedToNames = appliedToNames;
this.appTerrestre = appTerrestre;
this.appNavale = appNavale;
this.appMythique = appMythique;
this.statsZero = statsZero;
this.statsPlus = statsPlus;
}
public OffDefStats applyToUnit(Unite unite,int level) {
if((appTerrestre && unite.terrestre) ||
(appNavale && unite.navale) ||
(appMythique && unite.mythique) ||
appliedToNames.contains(unite.pname)) {
return unite.stats.plus(unite.stats.prod(statsZero.plus(statsPlus.times(level))));
}
return unite.stats;
}
public String getNom() {
return nom;
}
public String getPname() {
return pname;
}
public Set<String> getAppliedToNames() {
return appliedToNames;
}
public boolean isAppTerrestre() {
return appTerrestre;
}
public boolean isAppNavale() {
return appNavale;
}
public boolean isAppMythique() {
return appMythique;
}
public OffDefStats getStatsZero() {
return statsZero;
}
public OffDefStats getStatsPlus() {
return statsPlus;
}
}

View File

@ -1,182 +0,0 @@
package com.bernard.greposimu.model;
public class OffDefStats {
double att_hack;
double att_pierce;
double att_distance;
double ship_attack;
double def_hack;
double def_pierce;
double def_distance;
double ship_defense;
public OffDefStats(double attqCont, double attqBlan, double attqJet, double attqNav, double defCont, double defBlan,
double defJet, double defNav) {
this.att_hack = attqCont;
this.att_pierce = attqBlan;
this.att_distance = attqJet;
this.ship_attack = attqNav;
this.def_hack = defCont;
this.def_pierce = defBlan;
this.def_distance = defJet;
this.ship_defense = defNav;
}
public static final OffDefStats zero = new OffDefStats(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
public OffDefStats plus(OffDefStats other) {
return new OffDefStats(
this.att_hack + other.att_hack,
this.att_pierce + other.att_pierce,
this.att_distance + other.att_distance ,
this.ship_attack + other.ship_attack ,
this.def_hack + other.def_hack ,
this.def_pierce + other.def_pierce ,
this.def_distance + other.def_distance ,
this.ship_defense + other.ship_defense
);
}
public OffDefStats prod(OffDefStats other) {
return new OffDefStats(
this.att_hack * other.att_hack,
this.att_pierce * other.att_pierce,
this.att_distance * other.att_distance ,
this.ship_attack * other.ship_attack ,
this.def_hack * other.def_hack ,
this.def_pierce * other.def_pierce ,
this.def_distance * other.def_distance ,
this.ship_defense * other.ship_defense
);
}
public OffDefStats times(int factor) {
return new OffDefStats(
this.att_hack * factor,
this.att_pierce * factor,
this.att_distance * factor,
this.ship_attack * factor,
this.def_hack * factor,
this.def_pierce * factor,
this.def_distance * factor,
this.ship_defense * factor
);
}
public OffDefStats div(int factor) {
return new OffDefStats(
this.att_hack / factor,
this.att_pierce / factor,
this.att_distance / factor,
this.ship_attack / factor,
this.def_hack / factor,
this.def_pierce / factor,
this.def_distance / factor,
this.ship_defense / factor
);
}
public double getAttqCont() {
return att_hack;
}
public void setAttqCont(double attqCont) {
this.att_hack = attqCont;
}
public double getAttqBlan() {
return att_pierce;
}
public void setAttqBlan(double attqBlan) {
this.att_pierce = attqBlan;
}
public double getAttqJet() {
return att_distance;
}
public void setAttqJet(double attqJet) {
this.att_distance = attqJet;
}
public double getAttqNav() {
return ship_attack;
}
public void setAttqNav(double attqNav) {
this.ship_attack = attqNav;
}
public double getDefCont() {
return def_hack;
}
public void setDefCont(double defCont) {
this.def_hack = defCont;
}
public double getDefBlan() {
return def_pierce;
}
public void setDefBlan(double defBlan) {
this.def_pierce = defBlan;
}
public double getDefJet() {
return def_distance;
}
public void setDefJet(double defJet) {
this.def_distance = defJet;
}
public double getDefNav() {
return ship_defense;
}
public void setDefNav(double defNav) {
this.ship_defense = defNav;
}
public double getAtt_hack() {
return att_hack;
}
public double getAtt_pierce() {
return att_pierce;
}
public double getAtt_distance() {
return att_distance;
}
public double getShip_attack() {
return ship_attack;
}
public double getDef_hack() {
return def_hack;
}
public double getDef_pierce() {
return def_pierce;
}
public double getDef_distance() {
return def_distance;
}
public double getShip_defense() {
return ship_defense;
}
public static OffDefStats getZero() {
return zero;
}
}

View File

@ -1,74 +0,0 @@
package com.bernard.greposimu.model;
public class Unite {
String nom;
String pname;
int population;
int speed;
int butin;
OffDefStats stats;
boolean terrestre,navale,mythique;
Dieu dieu;
public Unite(String nom, String pname, int population, int speed, int butin, OffDefStats stats, boolean terrestre, boolean navale,
boolean mythique, Dieu dieu) {
this.nom = nom;
this.pname = pname;
this.population = population;
this.speed = speed;
this.butin = butin;
this.stats = stats;
this.terrestre = terrestre;
this.navale = navale;
this.mythique = mythique;
this.dieu = dieu;
}
public String getNom() {
return nom;
}
public String getPname() {
return pname;
}
public int getPopulation() {
return population;
}
public int getSpeed() {
return speed;
}
public int getButin() {
return butin;
}
public OffDefStats getStats() {
return stats;
}
public boolean isTerrestre() {
return terrestre;
}
public boolean isNavale() {
return navale;
}
public boolean isMythique() {
return mythique;
}
public Dieu getDieu() {
return dieu;
}
}

View File

@ -1,53 +0,0 @@
package com.bernard.greposimu.model.game;
import java.util.List;
import java.util.Map;
public class Building {
public String id;
public String name;
public String controller;
public Object image;
public String description;
public Object level;
public int max_level;
public int min_level;
public Object requiredBuildings;
public String coordinates;
public Resources resources;
public int pop;
public double wood_factor;
public double stone_factor;
public double iron_factor;
public double pop_factor;
public Object hide_factor;
public int points;
public double points_factor;
public int build_time;
public double build_time_factor;
public double build_time_reduction;
public Object bolt_protected;
public List<Integer> image_levels;
public Map<String,Integer> dependencies;
public Map<Integer,Integer> fixed_building_times;
public Map<Integer, LeveledFactor> level_build_time_factors;
public boolean special;
public Object resourcesFor;
public List<Object> resourcesForLevelFixed;
public Map<Integer, Double> resourcesForLevelFactor;
public List<Object> resourcesForLevelReduceFactor;
public List<Object> offset_value_map;
public double catapult_factor;
public double catapult_power;
public double def_factor_per_level;
public double storage_factor;
public double storage_pow;
public double farm_pow;
public double farm_factor;
public double thermal_pow;
public static class LeveledFactor {
public int level;
public double factor;
}
}

View File

@ -0,0 +1,200 @@
package com.bernard.greposimu.model.game;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.json.JSONObject;
import com.bernard.greposimu.Utils;
import com.bernard.greposimu.model.game.researches.Research;
import com.bernard.greposimu.model.game.units.FightType;
import com.bernard.greposimu.model.game.units.Hero;
import com.bernard.greposimu.model.game.units.Hero.HeroCategory;
import com.bernard.greposimu.model.game.units.NavalUnit;
import com.bernard.greposimu.model.game.units.TerrestrialUnit;
import com.bernard.greposimu.model.game.units.TransportUnit;
import com.bernard.greposimu.model.game.units.Unit;
public class GameConfig {
Set<God> gods;
// Non-hero units
Set<Unit> units;
Set<Hero> heroes;
Set<Research> researches;
public Set<Unit> getUnits() {
return Collections.unmodifiableSet(this.units);
}
public Unit getUnit(String id) {
return Utils.getIdentified(this.units, id);
}
public Set<Hero> getHeroes() {
return Collections.unmodifiableSet(this.heroes);
}
public Hero getHero(String id) {
return Utils.getIdentified(this.heroes, id);
}
public Set<Research> getResearches() {
return Collections.unmodifiableSet(this.researches);
}
public Research getResearch(String id) {
return Utils.getIdentified(this.researches, id);
}
public GameConfig(JSONObject json) {
JSONObject godsJ = json.getJSONObject("gods");
this.gods = new HashSet<>();
for(String g : godsJ.keySet()) {
JSONObject godJ = godsJ.getJSONObject(g);
gods.add(new God(godJ.getString("id"), godJ.getString("name")));
}
JSONObject researchesJ = json.getJSONObject("researches");
this.researches = new HashSet<>();
for(String r : researchesJ.keySet()) {
JSONObject research = researchesJ.getJSONObject(r);
this.researches.add(new Research(
research.getString("id"),
research.getString("name"),
research.getString("description"),
research.isNull("research_dependencies")?Set.of():research.getJSONArray("research_dependencies").toList().stream().map(k -> this.getResearch((String)k)).collect(Collectors.toSet()),
research.isNull("building_dependencies")?Map.of():research.getJSONObject("building_dependencies").keySet().stream()
.collect(Collectors.toMap(Function.identity(), b -> research.getJSONObject("building_dependencies").getInt(b))),
research.isNull("resources")?null:new Resources(
research.getJSONObject("resources").getInt("wood"),
research.getJSONObject("resources").getInt("stone"),
research.getJSONObject("resources").getInt("iron")),
research.getInt("required_time"),
research.getInt("research_points")
));
}
JSONObject unitsJ = json.getJSONObject("units");
this.units = new HashSet<>();
for(String u : unitsJ.keySet()) {
JSONObject unit = unitsJ.getJSONObject(u);
if(unit.getBoolean("is_naval")) {
if(unit.getInt("capacity")>0) {
units.add(new TransportUnit(
unit.getString("id"),
unit.getString("name"),
unit.getString("description"),
unit.getInt("population"),
unit.getInt("speed"),
unit.getString("category").equals("mythological_ground") || unit.getString("category").equals("mythological_naval"),
unit.isNull("god_id")?null:gods.stream().filter(g -> g.getId().equals(unit.getString("god_id"))).findAny().orElse(null),
unit.isNull("resources")?null:new Resources(
unit.getJSONObject("resources").getInt("wood"),
unit.getJSONObject("resources").getInt("stone"),
unit.getJSONObject("resources").getInt("iron")),
unit.getInt("favor"),
unit.getInt("build_time"),
unit.isNull("research_dependencies")?Set.of():unit.getJSONArray("research_dependencies").toList().stream().map(k -> this.getResearch((String)k)).collect(Collectors.toSet()),
unit.isNull("building_dependencies")?Map.of():unit.getJSONObject("building_dependencies").keySet().stream()
.collect(Collectors.toMap(Function.identity(), b -> unit.getJSONObject("building_dependencies").getInt(b))),
unit.getInt("attack"),
unit.getInt("defense"),
unit.getInt("capacity")
));
} else {
units.add(new NavalUnit(
unit.getString("id"),
unit.getString("name"),
unit.getString("description"),
unit.getInt("population"),
unit.getInt("speed"),
unit.getString("category").equals("mythological_ground") || unit.getString("category").equals("mythological_naval"),
unit.isNull("god_id")?null:gods.stream().filter(g -> g.getId().equals(unit.getString("god_id"))).findAny().orElse(null),
unit.isNull("resources")?null:new Resources(
unit.getJSONObject("resources").getInt("wood"),
unit.getJSONObject("resources").getInt("stone"),
unit.getJSONObject("resources").getInt("iron")),
unit.getInt("favor"),
unit.getInt("build_time"),
unit.isNull("research_dependencies")?Set.of():unit.getJSONArray("research_dependencies").toList().stream().map(k -> this.getResearch((String)k)).collect(Collectors.toSet()),
unit.isNull("building_dependencies")?Map.of():unit.getJSONObject("building_dependencies").keySet().stream()
.collect(Collectors.toMap(Function.identity(), b -> unit.getJSONObject("building_dependencies").getInt(b))),
unit.getInt("attack"),
unit.getInt("defense")
));
}
} else {
FightType ft = null;
switch(unit.getString("attack_type")) {
case "pierce": ft = FightType.PIERCE;break;
case "hack": ft = FightType.HACK;break;
case "distance": ft = FightType.DISTANCE;break;
}
units.add(new TerrestrialUnit(
unit.getString("id"),
unit.getString("name"),
unit.getString("description"),
unit.getInt("population"),
unit.getInt("speed"),
unit.getString("category").equals("mythological_ground") || unit.getString("category").equals("mythological_naval"),
unit.isNull("god_id")?null:gods.stream().filter(g -> g.getId().equals(unit.getString("god_id"))).findAny().orElse(null),
unit.isNull("resources")?null:new Resources(
unit.getJSONObject("resources").getInt("wood"),
unit.getJSONObject("resources").getInt("stone"),
unit.getJSONObject("resources").getInt("iron")),
unit.getInt("favor"),
unit.getInt("build_time"),
unit.isNull("research_dependencies")?Set.of():unit.getJSONArray("research_dependencies").toList().stream().map(k -> this.getResearch((String)k)).collect(Collectors.toSet()),
unit.isNull("building_dependencies")?Map.of():unit.getJSONObject("building_dependencies").keySet().stream()
.collect(Collectors.toMap(Function.identity(), b -> unit.getJSONObject("building_dependencies").getInt(b))),
unit.getInt("attack"),
ft,
unit.getInt("def_pierce"),
unit.getInt("def_hack"),
unit.getInt("def_distance"),
(unit.has("booty"))?unit.getInt("booty"):0,
unit.getJSONArray("special_abilities").toList().stream().filter(o -> o.equals("flying")).findAny().isPresent()
));
}
}
JSONObject heroesJ = json.getJSONObject("heroes");
this.heroes = new HashSet<>();
for(String h : heroesJ.keySet()) {
JSONObject hero = heroesJ.getJSONObject(h);
FightType ft = null;
switch(hero.getString("attack_type")) {
case "pierce": ft = FightType.PIERCE;break;
case "hack": ft = FightType.HACK;break;
case "distance": ft = FightType.DISTANCE;break;
}
JSONObject descargs = hero.getJSONObject("description_args").getJSONObject("1");
this.heroes.add(new Hero(
hero.getString("id"),
hero.getString("name"),
hero.getString("description"),
hero.getInt("speed"),
hero.getInt("attack"),
ft,
hero.getInt("def_pierce"),
hero.getInt("def_hack"),
hero.getInt("def_distance"),
hero.getInt("booty"),
hero.getString("category").equals("war")?HeroCategory.WAR:HeroCategory.WISDOM,
hero.getInt("cost"),
hero.getString("short_description"),
descargs.getDouble("value"),
descargs.getDouble("level_mod")
));
}
}
}

View File

@ -1,37 +0,0 @@
package com.bernard.greposimu.model.game;
import java.io.StringWriter;
import java.util.Map;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.Yaml;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class GameData {
public Map<String,Unit> units;
public Map<String, ? extends JsonPower> powers;
public Map<String, God> gods;
public Map<String, Hero> heroes;
public Map<String, Research> researches;
public Map<String, Building> buildings;
@Override
public String toString() {
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(FlowStyle.BLOCK);
options.setPrettyFlow(true);
Yaml yaml = new Yaml(options);
StringWriter writer = new StringWriter();
yaml.dump(this, writer);
return writer.toString();
}
}

View File

@ -1,12 +1,22 @@
package com.bernard.greposimu.model.game;
import java.util.List;
public class God implements Identified{
public class God {
public String name;
public String id;
public List<Unit> units;
public List<String> powers;
public String topic;
public String description;
String id;
String name;
public God(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getId() {
return id;
}
public String getName() {
return name;
}
}

View File

@ -1,36 +0,0 @@
package com.bernard.greposimu.model.game;
import java.util.List;
import java.util.Map;
public class Hero {
public String id;
public String category;
public String name;
public String description;
public Map<String,DescriptionArgs> description_args;
public String short_description;
public int default_level;
public int cost;
public List<Object> award_requirements;
public boolean is_naval;
public boolean exclusive;
public boolean hidden;
public String attack_type;
public int attack;
public int def_hack;
public int def_pierce;
public int def_distance;
public int speed;
public int booty;
public List<Object> preconditions;
public int max_per_attack;
public int max_per_support;
public static class DescriptionArgs {
public double value;
public double level_mod;
public String unit;
}
}

View File

@ -0,0 +1,7 @@
package com.bernard.greposimu.model.game;
public interface Identified {
public String getId();
}

View File

@ -1,8 +0,0 @@
package com.bernard.greposimu.model.game;
public class Image {
public String mini;
public String small;
public String medium;
public String large;
}

View File

@ -1,115 +0,0 @@
package com.bernard.greposimu.model.game;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JsonPower {
public Object effect;
public Object name;
public Object description;
public int lifetime;
public String id;
public String short_effect;
public int favor;
public int fury_percentage_cost;
public String god_id;
public BigInteger temple_level_sum_dependency;
public List<String> targets;
public boolean only_own_towns;
public boolean boost;
public boolean is_fake_power;
public List<String> area_of_effect;
public boolean destructive;
public boolean negative;
public boolean extendible;
public String power_group;
public int power_group_level;
public List<String> seeds_to;
public Image images;
public List<String> effects;
public boolean is_valid_for_happenings;
public List<String> meta_fields;
public Object meta_defaults;
public boolean removed_on_target_loss;
public boolean needs_level;
public boolean requires_god;
public boolean ignores_democritus;
public boolean display_amount;
public boolean wasteable;
public boolean is_ritual;
public boolean recreate_on_restart;
public boolean transfer_to_casual_world;
public boolean is_onetime_power;
public boolean is_upgradable;
public boolean is_capped;
public List<String> compatible_powers;
public boolean no_lifetime;
public boolean passive;
@SuppressWarnings("unchecked")
public Set<String> getTypes() {
Set<String> types = new HashSet<>();
if(name instanceof Map) {
if(((Map<String,Map<String,String>>)name).containsKey("type"))
types.addAll(((Map<String,Map<String,String>>)name).get("type").keySet());
else
name = ((Map<String,Map<String,String>>)name).get("god").get("athena");
}
if(description instanceof Map)
types.addAll(((Map<String,Map<String,String>>)description).get("type").keySet());
if(effect instanceof Map)
types.addAll(((Map<String,Map<String,String>>)effect).get("type").keySet());
return types;
}
@Override
public String toString() {
return "JsonPower [effect=" + effect + ", lifetime=" + lifetime + ", id=" + id + ", name=" + name
+ ", description=" + description + ", short_effect=" + short_effect + ", favor=" + favor
+ ", fury_percentage_cost=" + fury_percentage_cost + ", god_id=" + god_id
+ ", temple_level_sum_dependency=" + temple_level_sum_dependency + ", targets=" + targets
+ ", only_own_towns=" + only_own_towns + ", boost=" + boost + ", is_fake_power=" + is_fake_power
+ ", area_of_effect=" + area_of_effect + ", destructive=" + destructive + ", negative=" + negative
+ ", extendible=" + extendible + ", power_group=" + power_group + ", power_group_level="
+ power_group_level + ", seeds_to=" + seeds_to + ", images=" + images + ", effects=" + effects
+ ", is_valid_for_happenings=" + is_valid_for_happenings + ", meta_fields=" + meta_fields
+ ", meta_defaults=" + meta_defaults + ", removed_on_target_loss=" + removed_on_target_loss
+ ", needs_level=" + needs_level + ", requires_god=" + requires_god + ", ignores_democritus="
+ ignores_democritus + ", display_amount=" + display_amount + ", wasteable=" + wasteable
+ ", is_ritual=" + is_ritual + ", recreate_on_restart=" + recreate_on_restart
+ ", transfer_to_casual_world=" + transfer_to_casual_world + ", is_onetime_power=" + is_onetime_power
+ ", is_upgradable=" + is_upgradable + ", is_capped=" + is_capped + ", compatible_powers="
+ compatible_powers + ", no_lifetime=" + no_lifetime + ", passive=" + passive + "]";
}
public Object getEffect() {
return effect;
}
public void setEffect(Object effect) {
this.effect = effect;
}
public Object getName() {
return name;
}
public void setName(Object name) {
this.name = name;
}
public Object getDescription() {
return description;
}
public void setDescription(Object description) {
this.description = description;
}
}

View File

@ -1,126 +0,0 @@
package com.bernard.greposimu.model.game;
import java.util.Map;
public class Power extends JsonPower {
public String effect;
public String name;
public String description;
@SuppressWarnings("unchecked")
public Power(JsonPower power, String type) {
this.effect = (power.effect instanceof String)?(String)power.effect:((Map<String,Map<String,String>>)power.effect).get("type").get(type);
this.lifetime = power.lifetime;
this.id = power.id+"."+type;
this.name = (power.name instanceof String)?(String)power.name:((Map<String,Map<String,String>>)power.name).get("type").get(type);
this.description = (power.description instanceof String)?(String)power.description:((Map<String,Map<String,String>>)power.description).get("type").get(type);
this.short_effect = power.short_effect;
this.favor = power.favor;
this.fury_percentage_cost = power.fury_percentage_cost;
this.god_id = power.god_id;
this.temple_level_sum_dependency = power.temple_level_sum_dependency;
this.targets = power.targets;
this.only_own_towns = power.only_own_towns;
this.boost = power.boost;
this.is_fake_power = power.is_fake_power;
this.area_of_effect = power.area_of_effect;
this.destructive = power.destructive;
this.negative = power.negative;
this.extendible = power.extendible;
this.power_group = power.power_group;
this.power_group_level = power.power_group_level;
this.seeds_to = power.seeds_to;
this.images = power.images;
this.effects = power.effects;
this.is_valid_for_happenings = power.is_valid_for_happenings;
this.meta_fields = power.meta_fields;
this.meta_defaults = power.meta_defaults;
this.removed_on_target_loss = power.removed_on_target_loss;
this.needs_level = power.needs_level;
this.requires_god = power.requires_god;
this.ignores_democritus = power.ignores_democritus;
this.display_amount = power.display_amount;
this.wasteable = power.wasteable;
this.is_ritual = power.is_ritual;
this.recreate_on_restart = power.recreate_on_restart;
this.transfer_to_casual_world = power.transfer_to_casual_world;
this.is_onetime_power = power.is_onetime_power;
this.is_upgradable = power.is_upgradable;
this.is_capped = power.is_capped;
this.compatible_powers = power.compatible_powers;
this.no_lifetime = power.no_lifetime;
this.passive = power.passive;
}
public Power(JsonPower power) {
this.effect = (String) power.effect;
this.lifetime = power.lifetime;
this.id = power.id;
this.name = (String) power.name;
this.description = (String) power.description;
this.short_effect = power.short_effect;
this.favor = power.favor;
this.fury_percentage_cost = power.fury_percentage_cost;
this.god_id = power.god_id;
this.temple_level_sum_dependency = power.temple_level_sum_dependency;
this.targets = power.targets;
this.only_own_towns = power.only_own_towns;
this.boost = power.boost;
this.is_fake_power = power.is_fake_power;
this.area_of_effect = power.area_of_effect;
this.destructive = power.destructive;
this.negative = power.negative;
this.extendible = power.extendible;
this.power_group = power.power_group;
this.power_group_level = power.power_group_level;
this.seeds_to = power.seeds_to;
this.images = power.images;
this.effects = power.effects;
this.is_valid_for_happenings = power.is_valid_for_happenings;
this.meta_fields = power.meta_fields;
this.meta_defaults = power.meta_defaults;
this.removed_on_target_loss = power.removed_on_target_loss;
this.needs_level = power.needs_level;
this.requires_god = power.requires_god;
this.ignores_democritus = power.ignores_democritus;
this.display_amount = power.display_amount;
this.wasteable = power.wasteable;
this.is_ritual = power.is_ritual;
this.recreate_on_restart = power.recreate_on_restart;
this.transfer_to_casual_world = power.transfer_to_casual_world;
this.is_onetime_power = power.is_onetime_power;
this.is_upgradable = power.is_upgradable;
this.is_capped = power.is_capped;
this.compatible_powers = power.compatible_powers;
this.no_lifetime = power.no_lifetime;
this.passive = power.passive;
}
public String getEffect() {
return effect;
}
public void setEffect(String effect) {
this.effect = effect;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@ -1,15 +0,0 @@
package com.bernard.greposimu.model.game;
import java.util.List;
import java.util.Map;
public class Research {
public String id;
public String name;
public String description;
public List<Object> research_dependencies;
public Map<String,Integer> building_dependencies;
public Resources resources;
public int required_time;
public int research_points;
}

View File

@ -1,7 +1,27 @@
package com.bernard.greposimu.model.game;
public class Resources {
public int wood;
public int stone;
public int iron;
int wood;
int stone;
int iron;
public Resources(int wood, int stone, int iron) {
this.wood = wood;
this.stone = stone;
this.iron = iron;
}
public int getWood() {
return wood;
}
public int getStone() {
return stone;
}
public int getIron() {
return iron;
}
}

View File

@ -1,70 +0,0 @@
package com.bernard.greposimu.model.game;
import java.util.List;
import java.util.Map;
import com.bernard.greposimu.model.FightStats;
public class Unit {
public String id;
public String name;
public String name_plural;
public int speed;
public int attack;
public String description;
public Resources resources;
public int favor;
public int population;
public int build_time;
public String god_id;
public List<String> research_dependencies;
public Map<String, Integer> building_dependencies;
public boolean is_naval;
public int max_per_attack;
public int max_per_support;
public String unit_function;
public String category;
public List<Object> special_abilities;
public String passive;
public boolean is_npc_unit_only;
public int def_hack;
public int def_pierce;
public int def_distance;
public int booty;
public Object infantry;
public boolean flying;
public String attack_type;
// Naval
public int defense;
public boolean transport;
public int capacity;
public FightStats getDefStats() {
return new FightStats(def_hack, def_pierce, def_distance, defense);
}
public FightStats getAttStats() {
switch(attack_type) {
case "hack":
return new FightStats(attack, 0.0, 0.0, 0.0);
case "pierce":
return new FightStats(0.0, attack, 0.0, 0.0);
case "distance":
return new FightStats(0.0, 0.0, attack, 0.0);
}
if(is_naval)
return new FightStats(0.0, 0.0, 0.0, attack);
throw new IllegalStateException("This unit has no known attack type, and is not a ship");
}
public boolean isMythological() {
return category.equals("mythological_ground") || category.equals("mythological_naval");
}
public boolean isGround() {
return category.equals("regular_ground") || category.equals("mythological_ground");
}
public boolean isNaval() {
return category.equals("regular_naval") || category.equals("mythological_naval");
}
}

View File

@ -0,0 +1,66 @@
package com.bernard.greposimu.model.game.researches;
import java.util.Map;
import java.util.Set;
import com.bernard.greposimu.model.game.Identified;
import com.bernard.greposimu.model.game.Resources;
public class Research implements Identified{
String id;
String name;
String description;
Set<Research> researchDependencies;
Map<String,Integer> building_dependencies;
Resources resources;
int required_time;
int research_points;
public Research(String id, String name, String description, Set<Research> researchDependencies,
Map<String, Integer> building_dependencies, Resources resources, int required_time, int research_points) {
this.id = id;
this.name = name;
this.description = description;
this.researchDependencies = researchDependencies;
this.building_dependencies = building_dependencies;
this.resources = resources;
this.required_time = required_time;
this.research_points = research_points;
}
@Override
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Set<Research> getResearchDependencies() {
return researchDependencies;
}
public Map<String, Integer> getBuilding_dependencies() {
return building_dependencies;
}
public Resources getResources() {
return resources;
}
public int getRequired_time() {
return required_time;
}
public int getResearch_points() {
return research_points;
}
}

View File

@ -0,0 +1,5 @@
package com.bernard.greposimu.model.game.units;
public enum FightType {
PIERCE,HACK,DISTANCE;
}

View File

@ -0,0 +1,81 @@
package com.bernard.greposimu.model.game.units;
import java.util.Map;
import java.util.Set;
import com.bernard.greposimu.model.game.God;
import com.bernard.greposimu.model.game.Identified;
import com.bernard.greposimu.model.game.Resources;
public class Hero extends TerrestrialUnit{
// Zero population
// Non mythological
// No building cost/time
// no research/building dependencies
// No flight
// Terrestrial
public Hero(String id, String name, String description, int speed,
int attack, FightType attackType, int pierceDef, int hackDef,
int distanceDef, int booty, HeroCategory category, int cost, String shortDescription, double powerBaseValue, double powerValuePerLevel) {
super(id, name, description, 0, speed, false, null, null, 0, 0,
Set.of(), Map.of(), attack, attackType, pierceDef, hackDef, distanceDef, booty, false);
this.category = category;
this.cost = cost;
this.shortDescription = shortDescription;
this.powerBaseValue = powerBaseValue;
this.powerValuePerLevel = powerValuePerLevel;
}
HeroCategory category;
int cost;
String shortDescription;
double powerBaseValue;
double powerValuePerLevel;
public static enum HeroCategory implements Identified{
WAR("war"),WISDOM("wisdom");
String id;
HeroCategory(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
}
public HeroCategory getCategory() {
return category;
}
public int getCost() {
return cost;
}
public String getShortDescription() {
return shortDescription;
}
public double getPowerBaseValue() {
return powerBaseValue;
}
public double getPowerValuePerLevel() {
return powerValuePerLevel;
}
}

View File

@ -0,0 +1,47 @@
package com.bernard.greposimu.model.game.units;
import java.util.Map;
import java.util.Set;
import com.bernard.greposimu.model.game.God;
import com.bernard.greposimu.model.game.Resources;
import com.bernard.greposimu.model.game.researches.Research;
public class NavalUnit extends Unit {
int attack;
int defense;
public NavalUnit(String id, String name, String description, int population, int speed, boolean mythological, God god,
Resources buildCost, int favorCost, int buildTime, Set<Research> research_dependencies,
Map<String, Integer> building_dependencies,int attack, int defense) {
this.id = id;
this.name = name;
this.description = description;
this.population = population;
this.speed = speed;
this.mythological = mythological;
this.god = god;
this.buildCost = buildCost;
this.favorCost = favorCost;
this.buildTime = buildTime;
this.research_dependencies = research_dependencies;
this.building_dependencies = building_dependencies;
this.attack = attack;
this.defense = defense;
}
public int getAttack() {
return attack;
}
public int getDefense() {
return defense;
}
@Override
public boolean isGround() {
return false;
}
}

View File

@ -0,0 +1,79 @@
package com.bernard.greposimu.model.game.units;
import java.util.Map;
import java.util.Set;
import com.bernard.greposimu.model.game.God;
import com.bernard.greposimu.model.game.Resources;
import com.bernard.greposimu.model.game.researches.Research;
public class TerrestrialUnit extends Unit{
int attack;
FightType attackType;
int pierceDef;
int hackDef;
int distanceDef;
int booty;
boolean flight;
public TerrestrialUnit(String id, String name, String description, int population, int speed, boolean mythological, God god,
Resources buildCost, int favorCost, int buildTime, Set<Research> research_dependencies,
Map<String, Integer> building_dependencies,int attack, FightType attackType, int pierceDef, int hackDef, int distanceDef, int booty,
boolean flight) {
this.id = id;
this.name = name;
this.description = description;
this.population = population;
this.speed = speed;
this.mythological = mythological;
this.god = god;
this.buildCost = buildCost;
this.favorCost = favorCost;
this.buildTime = buildTime;
this.research_dependencies = research_dependencies;
this.building_dependencies = building_dependencies;
this.attack = attack;
this.attackType = attackType;
this.pierceDef = pierceDef;
this.hackDef = hackDef;
this.distanceDef = distanceDef;
this.booty = booty;
this.flight = flight;
}
public int getAttack() {
return attack;
}
public FightType getAttackType() {
return attackType;
}
public int getPierceDef() {
return pierceDef;
}
public int getHackDef() {
return hackDef;
}
public int getDistanceDef() {
return distanceDef;
}
public int getBooty() {
return booty;
}
public boolean isFlight() {
return flight;
}
@Override
public boolean isGround() {
return true;
}
}

View File

@ -0,0 +1,20 @@
package com.bernard.greposimu.model.game.units;
import java.util.Map;
import java.util.Set;
import com.bernard.greposimu.model.game.God;
import com.bernard.greposimu.model.game.Resources;
import com.bernard.greposimu.model.game.researches.Research;
public class TransportUnit extends NavalUnit {
int capacity;
public TransportUnit(String id, String name, String description, int population, int speed, boolean mythological,
God god, Resources buildCost, int favorCost, int buildTime, Set<Research> research_dependencies,
Map<String, Integer> building_dependencies, int attack, int defense, int capacity) {
super(id, name, description, population, speed, mythological, god, buildCost, favorCost, buildTime,
research_dependencies, building_dependencies, attack, defense);
this.capacity = capacity;
}
}

View File

@ -0,0 +1,95 @@
package com.bernard.greposimu.model.game.units;
import java.util.Map;
import java.util.Set;
import com.bernard.greposimu.model.game.God;
import com.bernard.greposimu.model.game.Identified;
import com.bernard.greposimu.model.game.Resources;
import com.bernard.greposimu.model.game.researches.Research;
public abstract class Unit implements Identified{
String id;
String name;
String description;
int population;
int speed;
boolean mythological;
God god;
Resources buildCost;
int favorCost;
int buildTime;
Set<Research> research_dependencies;
Map<String, Integer> building_dependencies;
@Override
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public int getPopulation() {
return population;
}
public int getSpeed() {
return speed;
}
public boolean isMythological() {
return mythological;
}
public God getGod() {
return god;
}
public Resources getBuildCost() {
return buildCost;
}
public int getFavorCost() {
return favorCost;
}
public int getBuildTime() {
return buildTime;
}
public Set<Research> getResearch_dependencies() {
return research_dependencies;
}
public Map<String, Integer> getBuilding_dependencies() {
return building_dependencies;
}
public abstract boolean isGround();
public boolean isNaval() {
return !this.isGround();
}
}

View File

@ -91,7 +91,7 @@ span.fixed50px {
</head>
<body>
<form action="#" th:object="${defCtx}" method="post" id="simuform" >
<form action="#" th:object="${ctx}" method="post" id="simuform" >
<fieldset id="herosFields">
<legend>Héros</legend>

View File

@ -10,8 +10,7 @@ class GrepoSimuApplicationTests {
@Test
void loadGameData() throws IOException {
// System.out.println("Reading game data");
// System.out.println(GrepoSimu.readGameData());
System.out.println(GrepoSimu.makeGameData());
}
}