Added offencive frontend
This commit is contained in:
parent
8454e3a711
commit
6e2f916927
@ -2,13 +2,11 @@ package com.bernard.greposimu;
|
|||||||
|
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.AbstractSet;
|
import java.util.AbstractSet;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import com.bernard.greposimu.model.game.Identified;
|
import com.bernard.greposimu.model.game.Identified;
|
||||||
|
|
||||||
@ -82,4 +80,9 @@ public class Utils {
|
|||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <E> E randFromSet(Random r, Set<E> set) {
|
||||||
|
E el = set.stream().sorted().skip(r.nextInt(set.size())).findFirst().get();
|
||||||
|
return el;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,6 @@ public class JSONReader {
|
|||||||
JSONObject powersJ = json.getJSONObject("powers");
|
JSONObject powersJ = json.getJSONObject("powers");
|
||||||
Set<Power> powers = new HashSet<>();
|
Set<Power> powers = new HashSet<>();
|
||||||
for(String p : powersJ.keySet()) {
|
for(String p : powersJ.keySet()) {
|
||||||
System.out.println("Power "+p);
|
|
||||||
JSONObject power = powersJ.getJSONObject(p);
|
JSONObject power = powersJ.getJSONObject(p);
|
||||||
JSONObject metadefaults = power.isNull("meta_defaults")?null:power.getJSONObject("meta_defaults");
|
JSONObject metadefaults = power.isNull("meta_defaults")?null:power.getJSONObject("meta_defaults");
|
||||||
if(power.isNull("god_id") || power.getString("god_id").isEmpty()) {
|
if(power.isNull("god_id") || power.getString("god_id").isEmpty()) {
|
||||||
@ -61,7 +60,6 @@ public class JSONReader {
|
|||||||
.orElseGet(() -> power.optJSONObject("description"))
|
.orElseGet(() -> power.optJSONObject("description"))
|
||||||
).getJSONObject(dependentKind).keySet();
|
).getJSONObject(dependentKind).keySet();
|
||||||
for(String kind : kinds){
|
for(String kind : kinds){
|
||||||
System.out.println("kind "+kind);
|
|
||||||
powers.add(new MultitypePower(
|
powers.add(new MultitypePower(
|
||||||
power.getString("id")+":"+kind,
|
power.getString("id")+":"+kind,
|
||||||
Optional.ofNullable(power.optString("name")).orElseGet(() -> power.getJSONObject("name").getJSONObject(dependentKind).getString(kind)),
|
Optional.ofNullable(power.optString("name")).orElseGet(() -> power.getJSONObject("name").getJSONObject(dependentKind).getString(kind)),
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.bernard.greposimu.controller;
|
||||||
|
|
||||||
|
public class Randomizer {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import java.io.IOException;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
@ -11,13 +12,16 @@ import org.springframework.ui.Model;
|
|||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
import com.bernard.greposimu.GrepoSimuApplication;
|
import com.bernard.greposimu.GrepoSimuApplication;
|
||||||
import com.bernard.greposimu.Utils;
|
import com.bernard.greposimu.Utils;
|
||||||
import com.bernard.greposimu.engine.game.Fight;
|
import com.bernard.greposimu.engine.game.Fight;
|
||||||
import com.bernard.greposimu.model.DefContext;
|
import com.bernard.greposimu.model.DefContext;
|
||||||
import com.bernard.greposimu.model.FightStats;
|
import com.bernard.greposimu.model.FightStats;
|
||||||
|
import com.bernard.greposimu.model.OffContext;
|
||||||
import com.bernard.greposimu.model.game.GameConfig;
|
import com.bernard.greposimu.model.game.GameConfig;
|
||||||
|
import com.bernard.greposimu.model.game.God;
|
||||||
import com.bernard.greposimu.model.game.units.Unit;
|
import com.bernard.greposimu.model.game.units.Unit;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
@ -26,91 +30,249 @@ import com.fasterxml.jackson.databind.SerializationFeature;
|
|||||||
public class SimulatorController {
|
public class SimulatorController {
|
||||||
|
|
||||||
@GetMapping("/simulator")
|
@GetMapping("/simulator")
|
||||||
public String simulator(Model model) throws IOException {
|
public String simulator(Model model, @RequestParam boolean random) throws IOException {
|
||||||
GameConfig gc = GrepoSimuApplication.GREPOLIS_GC;
|
GameConfig gc = GrepoSimuApplication.GREPOLIS_GC;
|
||||||
model.addAttribute("heroes", gc.getHeroes());
|
model.addAttribute("heroes", gc.getHeroes());
|
||||||
model.addAttribute("defUnits", Fight.relevantDefUnits(gc));
|
model.addAttribute("defUnits", Fight.relevantDefUnits(gc));
|
||||||
model.addAttribute("defCounsellors",Fight.relevantDefCounsellors(gc));
|
model.addAttribute("defCounsellors",DefContext.COUNSELLORS);
|
||||||
model.addAttribute("defResearches",Fight.relevantDefResearches(gc));
|
model.addAttribute("defResearches",DefContext.RESEARCHES);
|
||||||
model.addAttribute("defPowers",Fight.relevantDefPowers(gc));
|
model.addAttribute("defPowers",DefContext.POWERS);
|
||||||
model.addAttribute("ctx",new DefSimulatorParams());
|
model.addAttribute("offUnits", Fight.relevantOffUnits(gc));
|
||||||
|
model.addAttribute("offCounsellors",OffContext.COUNSELLORS);
|
||||||
|
model.addAttribute("offResearches",OffContext.RESEARCHES);
|
||||||
|
model.addAttribute("offPowers",OffContext.POWERS);
|
||||||
|
SimulatorParams params = new SimulatorParams();
|
||||||
|
if(random)
|
||||||
|
params.randomize(new Random(), gc);
|
||||||
|
model.addAttribute("ctx",params);
|
||||||
return "simulator";
|
return "simulator";
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/simulate")
|
@PostMapping("/simulate")
|
||||||
@GetMapping("/simulate")
|
@GetMapping("/simulate")
|
||||||
public String simulate(@ModelAttribute DefSimulatorParams defParams, Model model) throws IOException {
|
public String simulate(@ModelAttribute SimulatorParams params, Model model) throws IOException {
|
||||||
if(defParams == null)
|
if(params == null)
|
||||||
defParams = new DefSimulatorParams();
|
params = new SimulatorParams();
|
||||||
GameConfig gc = GrepoSimuApplication.GREPOLIS_GC;
|
GameConfig gc = GrepoSimuApplication.GREPOLIS_GC;
|
||||||
DefContext defCtx = defParams.asDefContext(gc);
|
DefContext defCtx = params.asDefContext(gc);
|
||||||
|
OffContext offCtx = params.asOffContext(gc);
|
||||||
FightStats cityStats = Fight.computeDefStats(gc,defCtx);
|
FightStats defStats = Fight.computeDefStats(gc,defCtx);
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
FightStats offStats = Fight.computeOffStats(gc,offCtx);
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||||
|
|
||||||
model.addAttribute("content",cityStats.toString()+"\n"+mapper.writerWithDefaultPrettyPrinter().writeValueAsString(defCtx));
|
model.addAttribute("content",
|
||||||
|
defStats.toString()+"\n"+
|
||||||
|
offStats.toString()+"\n"+
|
||||||
|
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(defCtx)+"\n"+
|
||||||
|
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(offCtx)
|
||||||
|
);
|
||||||
return "debug";
|
return "debug";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DefSimulatorParams {
|
public static class SimulatorParams {
|
||||||
|
|
||||||
// unitID -> number of units
|
// unitID -> number of units
|
||||||
public Map<String, Integer> units = new HashMap<>();
|
public Map<String, Integer> defUnits = new HashMap<>();
|
||||||
|
public Map<String, Integer> offUnits = new HashMap<>();
|
||||||
public String hero = "";
|
|
||||||
public int heroLevel = 0;
|
public String defHero = "";
|
||||||
|
public int defHeroLevel = 0;
|
||||||
|
public String offHero = "";
|
||||||
|
public int offHeroLevel = 0;
|
||||||
|
|
||||||
public int wallLevel = 0;
|
public int wallLevel = 0;
|
||||||
public boolean hasTower = false;
|
public boolean hasTower = false;
|
||||||
|
|
||||||
public Set<String> powers = new HashSet<>();
|
public Set<String> defPowers = new HashSet<>();
|
||||||
public Set<String> researches = new HashSet<>();
|
public Set<String> offPowers = new HashSet<>();
|
||||||
|
public Set<String> defResearches = new HashSet<>();
|
||||||
public Set<String> counsellors = new HashSet<>();
|
public Set<String> offResearches = new HashSet<>();
|
||||||
|
public Set<String> defCounsellors = new HashSet<>();
|
||||||
|
public Set<String> offCounsellors = new HashSet<>();
|
||||||
|
|
||||||
public boolean nightBonus = false;
|
public boolean nightBonus = false;
|
||||||
|
|
||||||
|
int luck, moral;
|
||||||
|
|
||||||
|
int olympicSwordGrepolympiaSummerLevel = 1;
|
||||||
|
int offOlympicSensesGrepolympiaSummerLevel = 1;
|
||||||
|
int aresRageLevel = 1;
|
||||||
|
int aresArmyFurySpent = 0;
|
||||||
|
int bloodlustFurySpent = 0;
|
||||||
|
|
||||||
|
int defOlympicSensesGrepolympiaSummerLevel = 1;
|
||||||
|
int olympicTorchGrepolympiaSummerLevel = 1;
|
||||||
|
int soteriasShrineLevel = 1;
|
||||||
|
|
||||||
|
boolean strategyBreach = false;
|
||||||
|
boolean allianceModifier = false;
|
||||||
|
|
||||||
public DefContext asDefContext(GameConfig gc) {
|
public DefContext asDefContext(GameConfig gc) {
|
||||||
Map<Unit,Integer> unitsU = new HashMap<>(units.size());
|
Map<Unit,Integer> unitsU = new HashMap<>(defUnits.size());
|
||||||
for(String u : units.keySet())
|
for(String u : defUnits.keySet())
|
||||||
unitsU.put(gc.getUnit(u), units.get(u));
|
unitsU.put(gc.getUnit(u), defUnits.get(u));
|
||||||
return new DefContext(
|
return new DefContext(
|
||||||
unitsU,
|
unitsU,
|
||||||
gc.getHero(hero),
|
gc.getHero(defHero),
|
||||||
heroLevel,
|
defHeroLevel,
|
||||||
wallLevel,
|
wallLevel,
|
||||||
hasTower,
|
hasTower,
|
||||||
powers,
|
defPowers,
|
||||||
1, 1, 1,
|
defOlympicSensesGrepolympiaSummerLevel, olympicTorchGrepolympiaSummerLevel, soteriasShrineLevel,
|
||||||
researches,
|
defResearches,
|
||||||
counsellors,
|
defCounsellors,
|
||||||
nightBonus
|
nightBonus
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Integer> getUnits() {
|
public static Object random() {
|
||||||
return units;
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUnits(Map<String, Integer> units) {
|
public OffContext asOffContext(GameConfig gc) {
|
||||||
this.units = units;
|
Map<Unit,Integer> unitsU = new HashMap<>(offUnits.size());
|
||||||
|
for(String u : offUnits.keySet())
|
||||||
|
unitsU.put(gc.getUnit(u), offUnits.get(u));
|
||||||
|
return new OffContext(
|
||||||
|
unitsU,
|
||||||
|
gc.getHero(defHero),
|
||||||
|
defHeroLevel,
|
||||||
|
luck, moral, defPowers,
|
||||||
|
olympicSwordGrepolympiaSummerLevel, offOlympicSensesGrepolympiaSummerLevel, aresRageLevel, aresArmyFurySpent, bloodlustFurySpent, defResearches,
|
||||||
|
defCounsellors, allianceModifier, allianceModifier
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void randomize(Random r,GameConfig gc) {
|
||||||
|
|
||||||
|
offUnits = new HashMap<>();
|
||||||
|
God g = null;
|
||||||
|
if(r.nextDouble()<0.8)
|
||||||
|
g = Utils.randFromSet(r, gc.getGods());
|
||||||
|
for(Unit u : Fight.relevantOffUnits(gc))
|
||||||
|
if(u.getGod() == null || u.getGod().equals(g))
|
||||||
|
if(r.nextDouble() < 0.7)
|
||||||
|
offUnits.put(u.getId(), (int) ((r.nextExponential()*50+10)/Math.max(u.getPopulation(),1)));
|
||||||
|
defUnits = new HashMap<>();
|
||||||
|
g = null;
|
||||||
|
if(r.nextDouble()<0.8)
|
||||||
|
g = Utils.randFromSet(r, gc.getGods());
|
||||||
|
for(Unit u : Fight.relevantDefUnits(gc))
|
||||||
|
if(u.getGod() == null || u.getGod().equals(g))
|
||||||
|
if(r.nextDouble() < 0.7)
|
||||||
|
defUnits.put(u.getId(), (int) ((r.nextExponential()*50+10)/Math.max(u.getPopulation(),1)));
|
||||||
|
|
||||||
|
offHero = null;
|
||||||
|
offHeroLevel = 0;
|
||||||
|
if(r.nextDouble()<.7) {
|
||||||
|
offHero = Utils.randFromSet(r, gc.getHeroes()).getId();
|
||||||
|
offHeroLevel = r.nextInt(1, 21);
|
||||||
|
}
|
||||||
|
defHero = null;
|
||||||
|
defHeroLevel = 0;
|
||||||
|
if(r.nextDouble()<.7) {
|
||||||
|
defHero = Utils.randFromSet(r, gc.getHeroes()).getId();
|
||||||
|
defHeroLevel = r.nextInt(1, 21);
|
||||||
|
}
|
||||||
|
|
||||||
|
wallLevel = r.nextInt(0, 26);
|
||||||
|
hasTower = (wallLevel>20) && (r.nextDouble()<0.2);
|
||||||
|
|
||||||
|
luck = (int) (Math.tanh(r.nextGaussian())*20);
|
||||||
|
moral = 100;
|
||||||
|
if(r.nextDouble()<.7)
|
||||||
|
moral = (int) Math.max(100-(r.nextExponential()*20),0);
|
||||||
|
|
||||||
|
offPowers = new HashSet<>();
|
||||||
|
defPowers = new HashSet<>();
|
||||||
|
for(String p : OffContext.POWERS) {
|
||||||
|
if(r.nextDouble()<0.05)
|
||||||
|
offPowers.add(p);
|
||||||
|
if(r.nextDouble()<0.05)
|
||||||
|
defPowers.add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
olympicSwordGrepolympiaSummerLevel = r.nextInt(1, 5);
|
||||||
|
offOlympicSensesGrepolympiaSummerLevel = r.nextInt(1, 5);
|
||||||
|
aresRageLevel = r.nextInt(1, 11);
|
||||||
|
aresArmyFurySpent = r.nextInt(1, 5000);
|
||||||
|
bloodlustFurySpent = r.nextInt(1, 5000);
|
||||||
|
defOlympicSensesGrepolympiaSummerLevel = r.nextInt(1, 5);
|
||||||
|
olympicTorchGrepolympiaSummerLevel = r.nextInt(1, 5);
|
||||||
|
soteriasShrineLevel = r.nextInt(1, 11);
|
||||||
|
|
||||||
|
offResearches = new HashSet<>();
|
||||||
|
defResearches = new HashSet<>();
|
||||||
|
for(String p : OffContext.RESEARCHES) {
|
||||||
|
if(r.nextDouble()<0.20)
|
||||||
|
offResearches.add(p);
|
||||||
|
if(r.nextDouble()<0.20)
|
||||||
|
defResearches.add(p);
|
||||||
|
}
|
||||||
|
offCounsellors = new HashSet<>();
|
||||||
|
defCounsellors = new HashSet<>();
|
||||||
|
for(String p : OffContext.COUNSELLORS) {
|
||||||
|
if(r.nextDouble()<0.05)
|
||||||
|
offCounsellors.add(p);
|
||||||
|
if(r.nextDouble()<0.05)
|
||||||
|
defCounsellors.add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
strategyBreach = (r.nextDouble()<0.02);
|
||||||
|
allianceModifier = (r.nextDouble()<0.001);
|
||||||
|
nightBonus = (r.nextDouble()<0.02);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHero() {
|
|
||||||
return hero;
|
public Map<String, Integer> getDefUnits() {
|
||||||
|
return defUnits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHero(String hero) {
|
public void setDefUnits(Map<String, Integer> defUnits) {
|
||||||
this.hero = hero;
|
this.defUnits = defUnits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHeroLevel() {
|
public Map<String, Integer> getOffUnits() {
|
||||||
return heroLevel;
|
return offUnits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeroLevel(int heroLevel) {
|
public void setOffUnits(Map<String, Integer> offUnits) {
|
||||||
this.heroLevel = heroLevel;
|
this.offUnits = offUnits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefHero() {
|
||||||
|
return defHero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefHero(String defHero) {
|
||||||
|
this.defHero = defHero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDefHeroLevel() {
|
||||||
|
return defHeroLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefHeroLevel(int defHeroLevel) {
|
||||||
|
this.defHeroLevel = defHeroLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffHero() {
|
||||||
|
return offHero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffHero(String offHero) {
|
||||||
|
this.offHero = offHero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOffHeroLevel() {
|
||||||
|
return offHeroLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffHeroLevel(int offHeroLevel) {
|
||||||
|
this.offHeroLevel = offHeroLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWallLevel() {
|
public int getWallLevel() {
|
||||||
@ -129,22 +291,98 @@ public static class DefSimulatorParams {
|
|||||||
this.hasTower = hasTower;
|
this.hasTower = hasTower;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getPowers() {
|
public Set<String> getDefPowers() {
|
||||||
return powers;
|
return defPowers;
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String,Boolean> getPowersAsMap() {
|
|
||||||
return Utils.setToMap(powers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String,Boolean> getResearchesAsMap() {
|
public void setDefPowers(Set<String> defPowers) {
|
||||||
return Utils.setToMap(researches);
|
this.defPowers = defPowers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String,Boolean> getCounsellorsAsMap() {
|
public Set<String> getOffPowers() {
|
||||||
return Utils.setToMap(counsellors);
|
return offPowers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setOffPowers(Set<String> offPowers) {
|
||||||
|
this.offPowers = offPowers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getDefResearches() {
|
||||||
|
return defResearches;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefResearches(Set<String> defResearches) {
|
||||||
|
this.defResearches = defResearches;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getOffResearches() {
|
||||||
|
return offResearches;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffResearches(Set<String> offResearches) {
|
||||||
|
this.offResearches = offResearches;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getDefCounsellors() {
|
||||||
|
return defCounsellors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefCounsellors(Set<String> defCounsellors) {
|
||||||
|
this.defCounsellors = defCounsellors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getOffCounsellors() {
|
||||||
|
return offCounsellors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffCounsellors(Set<String> offCounsellors) {
|
||||||
|
this.offCounsellors = offCounsellors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLuck() {
|
||||||
|
return luck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLuck(int luck) {
|
||||||
|
this.luck = luck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMoral() {
|
||||||
|
return moral;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMoral(int moral) {
|
||||||
|
this.moral = moral;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStrategyBreach() {
|
||||||
|
return strategyBreach;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrategyBreach(boolean strategyBreach) {
|
||||||
|
this.strategyBreach = strategyBreach;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllianceModifier() {
|
||||||
|
return allianceModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllianceModifier(boolean allianceModifier) {
|
||||||
|
this.allianceModifier = allianceModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Boolean> getDefPowersAsMap() {
|
||||||
|
return Utils.setToMap(defPowers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Boolean> getDefResearchesAsMap() {
|
||||||
|
return Utils.setToMap(defResearches);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Boolean> getDefCounsellorsAsMap() {
|
||||||
|
return Utils.setToMap(defCounsellors);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isNightBonus() {
|
public boolean isNightBonus() {
|
||||||
return nightBonus;
|
return nightBonus;
|
||||||
}
|
}
|
||||||
@ -153,6 +391,5 @@ public static class DefSimulatorParams {
|
|||||||
this.nightBonus = nightBonus;
|
this.nightBonus = nightBonus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import com.bernard.greposimu.model.FightStats;
|
|||||||
import com.bernard.greposimu.model.OffContext;
|
import com.bernard.greposimu.model.OffContext;
|
||||||
import com.bernard.greposimu.model.game.GameConfig;
|
import com.bernard.greposimu.model.game.GameConfig;
|
||||||
import com.bernard.greposimu.model.game.researches.Research;
|
import com.bernard.greposimu.model.game.researches.Research;
|
||||||
|
import com.bernard.greposimu.model.game.units.FightType;
|
||||||
import com.bernard.greposimu.model.game.units.NavalUnit;
|
import com.bernard.greposimu.model.game.units.NavalUnit;
|
||||||
import com.bernard.greposimu.model.game.units.TerrestrialUnit;
|
import com.bernard.greposimu.model.game.units.TerrestrialUnit;
|
||||||
import com.bernard.greposimu.model.game.units.Unit;
|
import com.bernard.greposimu.model.game.units.Unit;
|
||||||
@ -41,18 +42,14 @@ public class Fight {
|
|||||||
if(u.isMythological())
|
if(u.isMythological())
|
||||||
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.1)));
|
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.1)));
|
||||||
if(def.hasPhalanx())
|
if(def.hasPhalanx())
|
||||||
for(Unit u : gc.getUnits())
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(0.1));
|
||||||
if(u.isGround())
|
|
||||||
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.1)));
|
|
||||||
if(def.hasRam())
|
if(def.hasRam())
|
||||||
for(Unit u : gc.getUnits())
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.naval(0.1));
|
||||||
if(u.isNaval())
|
|
||||||
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.1)));
|
|
||||||
|
|
||||||
// Counsellors
|
// Counsellors
|
||||||
if(def.hasPriest())
|
if(def.hasPriest())
|
||||||
for(Unit u : gc.getUnits())
|
for(Unit u : gc.getUnits())
|
||||||
if(u.isGround())
|
if(u.isMythological())
|
||||||
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.2)));
|
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.2)));
|
||||||
if(def.hasCommander())
|
if(def.hasCommander())
|
||||||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(0.2));
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(0.2));
|
||||||
@ -75,7 +72,7 @@ public class Fight {
|
|||||||
if(def.getOlympicTorchGrepolympiaSummerLevel()!=0)
|
if(def.getOlympicTorchGrepolympiaSummerLevel()!=0)
|
||||||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.05*def.getOlympicTorchGrepolympiaSummerLevel()));
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.05*def.getOlympicTorchGrepolympiaSummerLevel()));
|
||||||
if(def.getSoteriasShrineLevel()!=0)
|
if(def.getSoteriasShrineLevel()!=0)
|
||||||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.007*def.getOlympicTorchGrepolympiaSummerLevel()));
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.007*def.getSoteriasShrineLevel()));
|
||||||
if(def.hasNarcissism())
|
if(def.hasNarcissism())
|
||||||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(-0.1));
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(-0.1));
|
||||||
|
|
||||||
@ -95,6 +92,16 @@ public class Fight {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HeroStat
|
||||||
|
if(def.getHero() != null) {
|
||||||
|
total = FightStats.add(total, new FightStats(
|
||||||
|
def.getHero().getHackDef() * (1.0+0.1*def.getHeroLevel()),
|
||||||
|
def.getHero().getPierceDef() * (1.0+0.1*def.getHeroLevel()),
|
||||||
|
def.getHero().getDistanceDef() * (1.0+0.1*def.getHeroLevel()),
|
||||||
|
0.0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,27 +116,127 @@ public class Fight {
|
|||||||
throw new UnsupportedOperationException("I don't know how to manage units of type "+u.getClass().getName());
|
throw new UnsupportedOperationException("I don't know how to manage units of type "+u.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> relevantDefPowers(GameConfig gd) {
|
public static FightStats computeOffStats(GameConfig gc, OffContext off) {
|
||||||
return List.of("acumen", "divine_senses", "myrmidion_attack", "trojan_defense", "defense_boost",
|
|
||||||
"defense_penalty", "longterm_defense_boost", "assassins_acumen", "rare_defense_boost",
|
FightStats everyoneStatsBonus = FightStats.zero();
|
||||||
"epic_defense_boost", "olympic_torch.grepolympia_summer", "olympic_senses.grepolympia_summer", "missions_power_4.missions_dionysia",
|
Map<Unit,FightStats> unitsBonuses;
|
||||||
"divine_battle_strategy_rare", "divine_battle_strategy_epic", "naval_battle_strategy_rare",
|
|
||||||
"naval_battle_strategy_epic", "land_battle_strategy_rare", "land_battle_strategy_epic",
|
// Heroes
|
||||||
"soterias_shrine.not_cast","narcissism");
|
unitsBonuses = Heroes.heroFightBonuses(gc, off.getHero(), off.getHeroLevel(), false);
|
||||||
|
|
||||||
|
// Researches
|
||||||
|
if(off.hasDivineSelection())
|
||||||
|
for(Unit u : gc.getUnits())
|
||||||
|
if(u.isMythological())
|
||||||
|
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.1)));
|
||||||
|
if(off.hasPhalanx())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(0.1));
|
||||||
|
if(off.hasRam())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.naval(0.1));
|
||||||
|
|
||||||
|
|
||||||
|
// Counsellors
|
||||||
|
if(off.hasPriest())
|
||||||
|
for(Unit u : gc.getUnits())
|
||||||
|
if(u.isMythological())
|
||||||
|
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.2)));
|
||||||
|
if(off.hasCommander())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(0.2));
|
||||||
|
if(off.hasCaptain())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.naval(0.2));
|
||||||
|
|
||||||
|
// Powers
|
||||||
|
if(off.hasMyrmidionAttack())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.1));
|
||||||
|
if(off.hasAttackBoost())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.1));
|
||||||
|
if(off.hasAttackPenalty())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(-0.1));
|
||||||
|
if(off.hasLongtermAttackBoost())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.1));
|
||||||
|
if(off.hasLuxurious_residence())
|
||||||
|
;//XXX Unimplemented
|
||||||
|
if(off.hasAttack_ship_attack_boost_small())
|
||||||
|
unitsBonuses.put(gc.getUnit("attack_ship"), FightStats.add(unitsBonuses.getOrDefault(gc.getUnit("attack_ship"), FightStats.zero()), FightStats.cst(0.1)));
|
||||||
|
if(off.hasAttack_ship_attack_boost_medium())
|
||||||
|
unitsBonuses.put(gc.getUnit("attack_ship"), FightStats.add(unitsBonuses.getOrDefault(gc.getUnit("attack_ship"), FightStats.zero()), FightStats.cst(0.2)));
|
||||||
|
if(off.hasAttack_ship_attack_boost_large())
|
||||||
|
unitsBonuses.put(gc.getUnit("attack_ship"), FightStats.add(unitsBonuses.getOrDefault(gc.getUnit("attack_ship"), FightStats.zero()), FightStats.cst(0.3)));
|
||||||
|
if(off.hasRareAttackBoost())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.1));
|
||||||
|
if(off.hasEpicAttackBoost())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.2));
|
||||||
|
if(off.getOlympicSwordGrepolympiaSummerLevel()!=0)
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.05*off.getOlympicSwordGrepolympiaSummerLevel()));
|
||||||
|
if(off.getAresRageLevel()!=0)
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.01*off.getAresRageLevel()));
|
||||||
|
if(off.getBloodlust()!=0)
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(0.05+0.01*Math.floorDiv(off.getBloodlust(),200)));
|
||||||
|
if(off.hasFairWind())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.naval(0.1));
|
||||||
|
if(off.hasDesire())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(-0.1));
|
||||||
|
if(off.hasStrengthOfHeroes())
|
||||||
|
//XXX check if working
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(0.1));
|
||||||
|
if(off.hasEffortOfTheHuntress())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.ofType(FightType.DISTANCE,0.15));
|
||||||
|
|
||||||
|
if(off.hasStrategyBreach())
|
||||||
|
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.naval(-0.5));
|
||||||
|
|
||||||
|
|
||||||
|
// Units
|
||||||
|
FightStats total = FightStats.zero();
|
||||||
|
for(Unit u : gc.getUnits()) {
|
||||||
|
// total = total + ucount * ((1+bonusA+bonusB) * ustats)
|
||||||
|
total = FightStats.add(total,
|
||||||
|
FightStats.prod(off.unitCount(u),
|
||||||
|
FightStats.mul(
|
||||||
|
FightStats.add(FightStats.one(),everyoneStatsBonus,unitsBonuses.getOrDefault(u, FightStats.zero()))
|
||||||
|
, makeOffStats(u))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if(off.getAresArmyFurySpent()!=0)
|
||||||
|
// Ading aresarmy/25 spartiates
|
||||||
|
total = FightStats.add(total,
|
||||||
|
FightStats.prod(Math.floorDiv(off.getAresArmyFurySpent(), 25),
|
||||||
|
FightStats.mul(
|
||||||
|
FightStats.add(FightStats.one(),everyoneStatsBonus,unitsBonuses.getOrDefault(gc.getUnit("spartoi"), FightStats.zero()))
|
||||||
|
, makeOffStats(gc.getUnit("spartoi")))
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// HeroStat
|
||||||
|
if(off.getHero() != null) {
|
||||||
|
total = FightStats.add(total, new FightStats(
|
||||||
|
off.getHero().getHackDef() * (1.0+0.1*off.getHeroLevel()),
|
||||||
|
off.getHero().getPierceDef() * (1.0+0.1*off.getHeroLevel()),
|
||||||
|
off.getHero().getDistanceDef() * (1.0+0.1*off.getHeroLevel()),
|
||||||
|
0.0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
}
|
}
|
||||||
public static List<Research> relevantDefResearches(GameConfig gd) {
|
|
||||||
return List.of("divine_selection","phalanx","ram")
|
public static FightStats makeOffStats(Unit u) {
|
||||||
.stream().map(gd::getResearch).toList();
|
if(u instanceof TerrestrialUnit) {
|
||||||
|
TerrestrialUnit tu = (TerrestrialUnit)u;
|
||||||
|
return FightStats.ofType(tu.getAttackType(), tu.getAttack());
|
||||||
|
}else if(u instanceof NavalUnit) {
|
||||||
|
NavalUnit nu = (NavalUnit)u;
|
||||||
|
return new FightStats(0.0, 0.0, 0.0, nu.getAttack());
|
||||||
|
}
|
||||||
|
throw new UnsupportedOperationException("I don't know how to manage units of type "+u.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Unit> relevantDefUnits(GameConfig gc) {
|
public static List<Unit> relevantDefUnits(GameConfig gc) {
|
||||||
return gc.getUnits().stream().toList();
|
return gc.getUnits().stream().toList();
|
||||||
}
|
}
|
||||||
public static List<String> relevantDefCounsellors(GameConfig data) {
|
public static List<Unit> relevantOffUnits(GameConfig gc) {
|
||||||
return List.of("priest","commander","captain");
|
return gc.getUnits().stream().toList();
|
||||||
}
|
|
||||||
public FightStats computeOffStats(DefContext off) {
|
|
||||||
//TODO computeOffStats
|
|
||||||
throw new UnsupportedOperationException("Simulator not created");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FightResult simulateFight(OffContext off, DefContext def) {
|
public FightResult simulateFight(OffContext off, DefContext def) {
|
||||||
|
|||||||
@ -1,21 +1,22 @@
|
|||||||
package com.bernard.greposimu.model;
|
package com.bernard.greposimu.model;
|
||||||
|
|
||||||
import java.util.AbstractMap;
|
import java.util.List;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.bernard.greposimu.model.game.GameConfig;
|
|
||||||
import com.bernard.greposimu.model.game.units.Hero;
|
import com.bernard.greposimu.model.game.units.Hero;
|
||||||
import com.bernard.greposimu.model.game.units.Unit;
|
import com.bernard.greposimu.model.game.units.Unit;
|
||||||
|
|
||||||
public class DefContext {
|
public class DefContext {
|
||||||
|
|
||||||
// UNITS
|
// UNITS
|
||||||
Map<Unit, Integer> units;
|
// Units unrelated to the attacker
|
||||||
|
Map<Unit, Integer> otherUnits;
|
||||||
|
// Units owned by allies of the attacker
|
||||||
|
Map<Unit, Integer> alliedUnits;
|
||||||
|
// Units owned by the attacher
|
||||||
|
Map<Unit, Integer> selfUnits;
|
||||||
|
|
||||||
// HEROS
|
// HEROS
|
||||||
Hero hero = null;
|
Hero hero = null;
|
||||||
@ -81,8 +82,16 @@ public class DefContext {
|
|||||||
boolean nightBonus = false;
|
boolean nightBonus = false;
|
||||||
|
|
||||||
public DefContext(Map<Unit, Integer> units, Hero hero, int heroLevel, int wallLevel, boolean hasTower,
|
public DefContext(Map<Unit, Integer> units, Hero hero, int heroLevel, int wallLevel, boolean hasTower,
|
||||||
|
Set<String> powers, int soteriasShrinePowerLevel, int olympicTorchGrepolympiaSummerLevel, int olympicSensesGrepolympiaSummerLevel,
|
||||||
|
Set<String> researches, Set<String> counsellors, boolean nightBonus) {
|
||||||
|
this(units,Map.of(),Map.of(),hero,heroLevel,wallLevel,hasTower,powers,soteriasShrinePowerLevel,olympicTorchGrepolympiaSummerLevel,olympicSensesGrepolympiaSummerLevel,researches,counsellors,nightBonus);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefContext(Map<Unit, Integer> otherUnits, Map<Unit, Integer> alliedUnits, Map<Unit, Integer> selfUnits, Hero hero, int heroLevel, int wallLevel, boolean hasTower,
|
||||||
Set<String> powers, int soteriasShrinePowerLevel, int olympicTorchGrepolympiaSummerLevel, int olympicSensesGrepolympiaSummerLevel, Set<String> researches, Set<String> counsellors, boolean nightBonus) {
|
Set<String> powers, int soteriasShrinePowerLevel, int olympicTorchGrepolympiaSummerLevel, int olympicSensesGrepolympiaSummerLevel, Set<String> researches, Set<String> counsellors, boolean nightBonus) {
|
||||||
this.units = units;
|
this.otherUnits = otherUnits;
|
||||||
|
this.alliedUnits = alliedUnits;
|
||||||
|
this.selfUnits = selfUnits;
|
||||||
this.hero = hero;
|
this.hero = hero;
|
||||||
this.heroLevel = heroLevel;
|
this.heroLevel = heroLevel;
|
||||||
this.wallLevel = wallLevel;
|
this.wallLevel = wallLevel;
|
||||||
@ -96,7 +105,7 @@ public class DefContext {
|
|||||||
if(powers.contains("longterm_defense_boost"))this.longtermDefenseBoost = true;
|
if(powers.contains("longterm_defense_boost"))this.longtermDefenseBoost = true;
|
||||||
if(powers.contains("assassins_acumen"))this.assassinsAcumen = true;
|
if(powers.contains("assassins_acumen"))this.assassinsAcumen = true;
|
||||||
if(powers.contains("rare_defense_boost"))this.rareDefenseBoost = true;
|
if(powers.contains("rare_defense_boost"))this.rareDefenseBoost = true;
|
||||||
if(powers.contains("epic_defense_boost"))this.defenseBoost = true;
|
if(powers.contains("epic_defense_boost"))this.epicDefenseBoost = true;
|
||||||
if(powers.contains("olympic_torch"))this.olympicTorchGrepolympiaSummerLevel = olympicTorchGrepolympiaSummerLevel;
|
if(powers.contains("olympic_torch"))this.olympicTorchGrepolympiaSummerLevel = olympicTorchGrepolympiaSummerLevel;
|
||||||
if(powers.contains("olympic_senses"))this.olympicSensesGrepolympiaSummerLevel = olympicSensesGrepolympiaSummerLevel;
|
if(powers.contains("olympic_senses"))this.olympicSensesGrepolympiaSummerLevel = olympicSensesGrepolympiaSummerLevel;
|
||||||
if(powers.contains("missions_power_4"))this.missionsPower4 = true;
|
if(powers.contains("missions_power_4"))this.missionsPower4 = true;
|
||||||
@ -117,11 +126,11 @@ public class DefContext {
|
|||||||
this.nightBonus = nightBonus;
|
this.nightBonus = nightBonus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Unit, Integer> getUnits() {
|
|
||||||
return units;
|
|
||||||
}
|
|
||||||
public int unitCount(Unit u) {
|
public int unitCount(Unit u) {
|
||||||
return Optional.ofNullable(units.getOrDefault(u,0)).orElse(0);
|
return
|
||||||
|
Optional.ofNullable(otherUnits.getOrDefault(u,0)).orElse(0) +
|
||||||
|
Optional.ofNullable(alliedUnits.getOrDefault(u,0)).orElse(0) +
|
||||||
|
Optional.ofNullable(selfUnits.getOrDefault(u,0)).orElse(0);
|
||||||
}
|
}
|
||||||
public Hero getHero() {
|
public Hero getHero() {
|
||||||
return hero;
|
return hero;
|
||||||
@ -247,4 +256,11 @@ public class DefContext {
|
|||||||
return narcissism;
|
return narcissism;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final List<String> POWERS = 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", "olympic_senses", "missions_power_4", "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", "narcissism");
|
||||||
|
public static final List<String> RESEARCHES = List.of("divine_selection","phalanx","ram");
|
||||||
|
public static final List<String> COUNSELLORS = List.of("priest","commander","captain");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package com.bernard.greposimu.model;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.bernard.greposimu.model.game.units.FightType;
|
||||||
|
|
||||||
public class FightStats implements Cloneable{
|
public class FightStats implements Cloneable{
|
||||||
public double hack;
|
public double hack;
|
||||||
public double pierce;
|
public double pierce;
|
||||||
@ -15,6 +17,19 @@ public class FightStats implements Cloneable{
|
|||||||
this.ship = ship;
|
this.ship = ship;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final FightStats ofType(FightType type, double value) {
|
||||||
|
switch(type) {
|
||||||
|
case HACK:
|
||||||
|
return new FightStats(value, 0.0, 0.0, 0.0);
|
||||||
|
case PIERCE:
|
||||||
|
return new FightStats(0.0, value, 0.0, 0.0);
|
||||||
|
case DISTANCE:
|
||||||
|
return new FightStats(0.0, 0.0, value, 0.0);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static final FightStats zero() {
|
public static final FightStats zero() {
|
||||||
return new FightStats(0, 0, 0, 0);
|
return new FightStats(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,288 @@
|
|||||||
package com.bernard.greposimu.model;
|
package com.bernard.greposimu.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.bernard.greposimu.model.game.units.Hero;
|
||||||
|
import com.bernard.greposimu.model.game.units.Unit;
|
||||||
|
|
||||||
public class OffContext {
|
public class OffContext {
|
||||||
// unitID -> number of units
|
|
||||||
public Map<String, Integer> units;
|
|
||||||
|
|
||||||
public String heros;
|
Map<Unit, Integer> units;
|
||||||
public int herosLevel;
|
|
||||||
|
|
||||||
public int luck;
|
Hero hero;
|
||||||
public int morale;
|
int heroLevel;
|
||||||
|
|
||||||
public Set<String> powers;
|
int luck;
|
||||||
public Set<String> researches;
|
int moral;
|
||||||
|
|
||||||
public Set<String> counsellors;
|
// RESEARCHES
|
||||||
|
boolean divineSelection= false, phalanx = false, ram=false, combatExperience=false;
|
||||||
|
|
||||||
|
// COUNSELLORS
|
||||||
|
boolean commander= false;
|
||||||
|
boolean priest = false;
|
||||||
|
boolean captain = false;
|
||||||
|
|
||||||
|
// EFFECTS
|
||||||
|
// PC x2
|
||||||
|
boolean acumen = false;
|
||||||
|
// PC x4
|
||||||
|
boolean divineSenses= false;
|
||||||
|
// Attq +10%, Def -10%
|
||||||
|
boolean myrmidionAttack= false;
|
||||||
|
// Attq +10%
|
||||||
|
boolean attackBoost= false;
|
||||||
|
// Attq -10%
|
||||||
|
boolean attackPenalty= false;
|
||||||
|
// Attq +10%
|
||||||
|
boolean longtermAttackBoost = false;
|
||||||
|
//XXX implement this :/
|
||||||
|
boolean luxuriousResidence = false;
|
||||||
|
// BF attq +10%
|
||||||
|
boolean attack_ship_attack_boost_small = false;
|
||||||
|
// BF attq +20%
|
||||||
|
boolean attack_ship_attack_boost_medium = false;
|
||||||
|
// BF attq +30%
|
||||||
|
boolean attack_ship_attack_boost_large = false;
|
||||||
|
// PC +50%
|
||||||
|
boolean assassinsAcumen= false;
|
||||||
|
// Attq +10%
|
||||||
|
boolean rareAttackBoost= false;
|
||||||
|
// Attq +20%
|
||||||
|
boolean epicAttackBoost= false;
|
||||||
|
// Attq +5%*level
|
||||||
|
int olympicSwordGrepolympiaSummerLevel = 0;
|
||||||
|
// PC+10%*level
|
||||||
|
int olympicSensesGrepolympiaSummerLevel = 0;
|
||||||
|
// +50% PC
|
||||||
|
boolean missionsPower4= false;
|
||||||
|
// PC+50% (sauf BC, transport)
|
||||||
|
boolean divineBattleStrategyRare= false;
|
||||||
|
// PC+100% (sauf BC, transport)
|
||||||
|
boolean divineBattleStrategyEpic= false;
|
||||||
|
// PC+50% against naval (sauf BC,transports)
|
||||||
|
boolean navalBattleStrategyRare= false;
|
||||||
|
// PC+100% against naval (sauf BC, transport)
|
||||||
|
boolean navalBattleStrategyEpic= false;
|
||||||
|
// PC+50% against terrestres
|
||||||
|
boolean landBattleStrategyRare= false;
|
||||||
|
// PC+100% against terrestre
|
||||||
|
boolean landBattleStrategyEpic= false;
|
||||||
|
// Attq +1%*level
|
||||||
|
int aresRageLevel = 0;
|
||||||
|
|
||||||
|
// SPELLS
|
||||||
|
// Add one sparte for every 25 fury used
|
||||||
|
int aresArmyFurySpent = 0;
|
||||||
|
// Attq +5% +(1% for each 200 fury spent)
|
||||||
|
// PC + 1% for each 100 fury spent
|
||||||
|
int bloodlustFurySpent = 0;
|
||||||
|
// Attq naval +10%
|
||||||
|
boolean fairWind = false;
|
||||||
|
// Attq -10%
|
||||||
|
boolean desire = false;
|
||||||
|
// Terr + aer +10% attq
|
||||||
|
boolean strengthOfHeroes = false;
|
||||||
|
// Attq distance +15%
|
||||||
|
boolean effortOfTheHuntress = false;
|
||||||
|
|
||||||
|
boolean strategyBreach = false;
|
||||||
|
boolean allianceModifier = false;
|
||||||
|
|
||||||
|
|
||||||
|
public OffContext(Map<Unit, Integer> units, Hero hero, int heroLevel, int luck, int moral,
|
||||||
|
Set<String> powers, int olympicSwordGrepolympiaSummerLevel, int olympicSensesGrepolympiaSummerLevel,
|
||||||
|
int aresRageLevel, int aresArmyFurySpent, int bloodlustFurySpent, Set<String> researches, Set<String> counsellors,
|
||||||
|
boolean strategyBreach, boolean allianceModifier) {
|
||||||
|
this.units = units;
|
||||||
|
this.hero = hero;
|
||||||
|
this.heroLevel = heroLevel;
|
||||||
|
this.luck = luck;
|
||||||
|
this.moral = moral;
|
||||||
|
|
||||||
|
if(powers.contains("acumen"))this.acumen = true;
|
||||||
|
if(powers.contains("divine_senses"))this.divineSenses = true;
|
||||||
|
if(powers.contains("myrmidion_attack"))this.myrmidionAttack = true;
|
||||||
|
if(powers.contains("attack_boost"))this.attackBoost = true;
|
||||||
|
if(powers.contains("attack_penalty"))this.attackPenalty = true;
|
||||||
|
if(powers.contains("longterm_attack_boost"))this.longtermAttackBoost = true;
|
||||||
|
if(powers.contains("attack_ship_attack_boost_small"))this.attack_ship_attack_boost_small = true;
|
||||||
|
if(powers.contains("attack_ship_attack_boost_medium"))this.attack_ship_attack_boost_medium = true;
|
||||||
|
if(powers.contains("attack_ship_attack_boost_large"))this.attack_ship_attack_boost_large = true;
|
||||||
|
if(powers.contains("assassins_acumen"))this.assassinsAcumen = true;
|
||||||
|
if(powers.contains("rare_attack_boost"))this.rareAttackBoost = true;
|
||||||
|
if(powers.contains("epic_attack_boost"))this.epicAttackBoost = true;
|
||||||
|
if(powers.contains("olympic_sword"))this.olympicSwordGrepolympiaSummerLevel = olympicSwordGrepolympiaSummerLevel;
|
||||||
|
if(powers.contains("olympic_senses"))this.olympicSensesGrepolympiaSummerLevel = olympicSensesGrepolympiaSummerLevel;
|
||||||
|
if(powers.contains("missions_power_4"))this.missionsPower4 = true;
|
||||||
|
if(powers.contains("divine_battle_strategy_rare"))this.divineBattleStrategyRare = true;
|
||||||
|
if(powers.contains("divine_battle_strategy_epic"))this.divineBattleStrategyEpic = true;
|
||||||
|
if(powers.contains("naval_battle_strategy_rare"))this.navalBattleStrategyRare = true;
|
||||||
|
if(powers.contains("naval_battle_strategy_epic"))this.navalBattleStrategyEpic = true;
|
||||||
|
if(powers.contains("land_battle_strategy_rare"))this.landBattleStrategyRare = true;
|
||||||
|
if(powers.contains("land_battle_strategy_epic"))this.landBattleStrategyEpic = true;
|
||||||
|
if(powers.contains("ares_rage"))this.aresRageLevel = aresRageLevel;
|
||||||
|
if(powers.contains("ares_army"))this.aresArmyFurySpent = aresArmyFurySpent;
|
||||||
|
if(powers.contains("bloodlust"))this.bloodlustFurySpent = bloodlustFurySpent;
|
||||||
|
if(powers.contains("fair_wind"))this.fairWind = true;
|
||||||
|
if(powers.contains("desire"))this.desire = true;
|
||||||
|
if(powers.contains("effort_of_the_huntress"))this.effortOfTheHuntress = true;
|
||||||
|
if(powers.contains("strength_of_heroes"))this.strengthOfHeroes = true;
|
||||||
|
if(researches.contains("divine_selection"))this.divineSelection = true;
|
||||||
|
if(researches.contains("phalanx"))this.phalanx = true;
|
||||||
|
if(researches.contains("ram"))this.ram = true;
|
||||||
|
if(researches.contains("combat_experience"))this.combatExperience = true;
|
||||||
|
if(counsellors.contains("commander"))this.commander = true;
|
||||||
|
if(counsellors.contains("priest"))this.priest = true;
|
||||||
|
if(counsellors.contains("captain"))this.captain = true;
|
||||||
|
this.strategyBreach = strategyBreach;
|
||||||
|
this.allianceModifier = allianceModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int unitCount(Unit u) {
|
||||||
|
return Optional.ofNullable(units.getOrDefault(u,0)).orElse(0);
|
||||||
|
}
|
||||||
|
public Map<Unit, Integer> getUnits() {
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
public Hero getHero() {
|
||||||
|
return hero;
|
||||||
|
}
|
||||||
|
public int getHeroLevel() {
|
||||||
|
return heroLevel;
|
||||||
|
}
|
||||||
|
public int getLuck() {
|
||||||
|
return luck;
|
||||||
|
}
|
||||||
|
public int getMorale() {
|
||||||
|
return moral;
|
||||||
|
}
|
||||||
|
public boolean hasDivineSelection() {
|
||||||
|
return divineSelection;
|
||||||
|
}
|
||||||
|
public boolean hasPhalanx() {
|
||||||
|
return phalanx;
|
||||||
|
}
|
||||||
|
public boolean hasRam() {
|
||||||
|
return ram;
|
||||||
|
}
|
||||||
|
public boolean hasCombatExperience() {
|
||||||
|
return combatExperience;
|
||||||
|
}
|
||||||
|
public boolean hasCommander() {
|
||||||
|
return commander;
|
||||||
|
}
|
||||||
|
public boolean hasPriest() {
|
||||||
|
return priest;
|
||||||
|
}
|
||||||
|
public boolean hasCaptain() {
|
||||||
|
return captain;
|
||||||
|
}
|
||||||
|
public boolean hasAcumen() {
|
||||||
|
return acumen;
|
||||||
|
}
|
||||||
|
public boolean hasDivineSenses() {
|
||||||
|
return divineSenses;
|
||||||
|
}
|
||||||
|
public boolean hasMyrmidionAttack() {
|
||||||
|
return myrmidionAttack;
|
||||||
|
}
|
||||||
|
public boolean hasAttackBoost() {
|
||||||
|
return attackBoost;
|
||||||
|
}
|
||||||
|
public boolean hasAttackPenalty() {
|
||||||
|
return attackPenalty;
|
||||||
|
}
|
||||||
|
public boolean hasLongtermAttackBoost() {
|
||||||
|
return longtermAttackBoost;
|
||||||
|
}
|
||||||
|
public boolean hasLuxurious_residence() {
|
||||||
|
return luxuriousResidence;
|
||||||
|
}
|
||||||
|
public boolean hasAttack_ship_attack_boost_small() {
|
||||||
|
return attack_ship_attack_boost_small;
|
||||||
|
}
|
||||||
|
public boolean hasAttack_ship_attack_boost_medium() {
|
||||||
|
return attack_ship_attack_boost_medium;
|
||||||
|
}
|
||||||
|
public boolean hasAttack_ship_attack_boost_large() {
|
||||||
|
return attack_ship_attack_boost_large;
|
||||||
|
}
|
||||||
|
public boolean hasAssassinsAcumen() {
|
||||||
|
return assassinsAcumen;
|
||||||
|
}
|
||||||
|
public boolean hasRareAttackBoost() {
|
||||||
|
return rareAttackBoost;
|
||||||
|
}
|
||||||
|
public boolean hasEpicAttackBoost() {
|
||||||
|
return epicAttackBoost;
|
||||||
|
}
|
||||||
|
public int getOlympicSwordGrepolympiaSummerLevel() {
|
||||||
|
return olympicSwordGrepolympiaSummerLevel;
|
||||||
|
}
|
||||||
|
public int getOlympicSensesGrepolympiaSummerLevel() {
|
||||||
|
return olympicSensesGrepolympiaSummerLevel;
|
||||||
|
}
|
||||||
|
public boolean hasMhassionsPower4() {
|
||||||
|
return missionsPower4;
|
||||||
|
}
|
||||||
|
public boolean hasDivineBattleStrategyRare() {
|
||||||
|
return divineBattleStrategyRare;
|
||||||
|
}
|
||||||
|
public boolean hasDivineBattleStrategyEpic() {
|
||||||
|
return divineBattleStrategyEpic;
|
||||||
|
}
|
||||||
|
public boolean hasNavalBattleStrategyRare() {
|
||||||
|
return navalBattleStrategyRare;
|
||||||
|
}
|
||||||
|
public boolean hasNavalBattleStrategyEpic() {
|
||||||
|
return navalBattleStrategyEpic;
|
||||||
|
}
|
||||||
|
public boolean hasLandBattleStrategyRare() {
|
||||||
|
return landBattleStrategyRare;
|
||||||
|
}
|
||||||
|
public boolean hasLandBattleStrategyEpic() {
|
||||||
|
return landBattleStrategyEpic;
|
||||||
|
}
|
||||||
|
public int getAresRageLevel() {
|
||||||
|
return aresRageLevel;
|
||||||
|
}
|
||||||
|
public int getAresArmyFurySpent() {
|
||||||
|
return aresArmyFurySpent;
|
||||||
|
}
|
||||||
|
public int getBloodlust() {
|
||||||
|
return bloodlustFurySpent;
|
||||||
|
}
|
||||||
|
public boolean hasFairWind() {
|
||||||
|
return fairWind;
|
||||||
|
}
|
||||||
|
public boolean hasDesire() {
|
||||||
|
return desire;
|
||||||
|
}
|
||||||
|
public boolean hasStrengthOfHeroes() {
|
||||||
|
return strengthOfHeroes;
|
||||||
|
}
|
||||||
|
public boolean hasEffortOfTheHuntress() {
|
||||||
|
return effortOfTheHuntress;
|
||||||
|
}
|
||||||
|
public boolean hasStrategyBreach() {
|
||||||
|
return strategyBreach;
|
||||||
|
}
|
||||||
|
public boolean hasAllianceModifier() {
|
||||||
|
return allianceModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final List<String> POWERS = List.of("acumen", "divine_senses", "myrmidion_attack", "attack_boost",
|
||||||
|
"attack_penalty", "longterm_attack_boost", "attack_ship_attack_boost_small",
|
||||||
|
"attack_ship_attack_boost_medium", "attack_ship_attack_boost_large", "assassins_acumen",
|
||||||
|
"rare_attack_boost", "epic_attack_boost", "olympic_sword", "olympic_senses", "missions_power_4",
|
||||||
|
"divine_battle_strategy_rare", "divine_battle_strategy_epic", "naval_battle_strategy_rare",
|
||||||
|
"naval_battle_strategy_epic", "land_battle_strategy_rare", "land_battle_strategy_epic", "ares_rage",
|
||||||
|
"ares_army", "bloodlust", "fair_wind", "desire", "effort_of_the_huntress", "strength_of_heroes");
|
||||||
|
public static final List<String> RESEARCHES = List.of("divine_selection","phalanx","ram","combat_experience");
|
||||||
|
public static final List<String> COUNSELLORS = List.of("priest","commander","captain");
|
||||||
|
|
||||||
public boolean strategy_breach;
|
|
||||||
public boolean alliance_modifier;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,10 @@ public class GameConfig {
|
|||||||
this.researches = researches;
|
this.researches = researches;
|
||||||
this.powers = powers;
|
this.powers = powers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<God> getGods() {
|
||||||
|
return gods;
|
||||||
|
}
|
||||||
|
|
||||||
public Set<Unit> getUnits() {
|
public Set<Unit> getUnits() {
|
||||||
return Collections.unmodifiableSet(this.units);
|
return Collections.unmodifiableSet(this.units);
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package com.bernard.greposimu.model.game;
|
package com.bernard.greposimu.model.game;
|
||||||
|
|
||||||
public class God implements Identified{
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class God implements Identified,Comparable<God>{
|
||||||
|
|
||||||
String id;
|
String id;
|
||||||
String name;
|
String name;
|
||||||
@ -18,5 +20,33 @@ public class God implements Identified{
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(God o) {
|
||||||
|
return this.getId().compareTo(o.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
God other = (God) obj;
|
||||||
|
return Objects.equals(id, other.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "God [id=" + id + ", name=" + name + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
package com.bernard.greposimu.model.game.units;
|
package com.bernard.greposimu.model.game.units;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.bernard.greposimu.model.game.God;
|
|
||||||
import com.bernard.greposimu.model.game.Identified;
|
import com.bernard.greposimu.model.game.Identified;
|
||||||
import com.bernard.greposimu.model.game.Resources;
|
|
||||||
|
|
||||||
public class Hero extends TerrestrialUnit{
|
public class Hero extends TerrestrialUnit implements Comparable<Hero>{
|
||||||
|
|
||||||
// Zero population
|
// Zero population
|
||||||
// Non mythological
|
// Non mythological
|
||||||
@ -76,6 +75,34 @@ public class Hero extends TerrestrialUnit{
|
|||||||
return powerValuePerLevel;
|
return powerValuePerLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Hero o) {
|
||||||
|
return this.getId().compareTo(o.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Hero other = (Hero) obj;
|
||||||
|
return Objects.equals(id, other.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Hero [category=" + category + ", cost=" + cost + ", shortDescription=" + shortDescription
|
||||||
|
+ ", powerBaseValue=" + powerBaseValue + ", powerValuePerLevel=" + powerValuePerLevel + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
missions_power_4.missions_dionysia.disabled.png
|
||||||
@ -0,0 +1 @@
|
|||||||
|
missions_power_4.missions_dionysia.hover.png
|
||||||
1
src/main/resources/static/images/powers/missions_power_4.png
Symbolic link
1
src/main/resources/static/images/powers/missions_power_4.png
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
missions_power_4.missions_dionysia.png
|
||||||
@ -85,6 +85,17 @@ span.fixed50px {
|
|||||||
border: 0px;
|
border: 0px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
.container {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.columns {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formcol {
|
||||||
|
flex: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -92,95 +103,147 @@ span.fixed50px {
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
<form action="#" th:object="${ctx}" method="post" id="simuform" >
|
<form action="#" th:object="${ctx}" method="post" id="simuform" >
|
||||||
|
<div class="columns">
|
||||||
<fieldset id="herosFields">
|
<fieldset class="formcol">
|
||||||
<legend>Héros</legend>
|
<legend>Attaque</legend>
|
||||||
<select name="heros" id="heros" th:field="*{hero}">
|
<fieldset id="herosFields">
|
||||||
<option value="none">Aucun</option>
|
<legend>Héros</legend>
|
||||||
<option th:each="hero : ${heroes}" th:value="${hero.id}"><span th:text="${hero.name}"/></option>
|
<select name="offHeros" id="offHeros" th:field="*{offHero}">
|
||||||
</select>
|
<option value="none">Aucun</option>
|
||||||
|
<option th:each="hero : ${heroes}" th:value="${hero.id}"><span th:text="${hero.name}"/></option>
|
||||||
<label for="heroLevelSlider">Niveau du héros: (<span id="heroLevelSliderInfo" class="fixed50px"></span>)</label>
|
</select>
|
||||||
<input type="range" min="1" max="20" value="1" class="slider" id="heroLevelSlider" th:field="*{heroLevel}">
|
|
||||||
|
<label for="offHeroLevelSlider">Niveau du héros: (<span id="offHeroLevelSliderInfo" class="fixed50px"></span>)</label>
|
||||||
<script>
|
<input type="range" min="1" max="20" value="1" class="slider" id="offHeroLevelSlider" th:field="*{offHeroLevel}">
|
||||||
var heroSlider = document.getElementById("heroLevelSlider");
|
|
||||||
var heroOutput = document.getElementById("heroLevelSliderInfo");
|
<script>
|
||||||
heroOutput.innerHTML = "lvl. "+heroSlider.value;
|
var offHeroSlider = document.getElementById("offHeroLevelSlider");
|
||||||
// Update the current slider value (each time you drag the slider handle)
|
var offHeroOutput = document.getElementById("offHeroLevelSliderInfo");
|
||||||
heroSlider.oninput = function() {
|
offHeroOutput.innerHTML = "lvl. "+offHeroSlider.value;
|
||||||
heroOutput.innerHTML = "lvl. "+this.value;
|
// Update the current slider value (each time you drag the slider handle)
|
||||||
}
|
offHeroSlider.oninput = function() {
|
||||||
</script>
|
offHeroOutput.innerHTML = "lvl. "+this.value;
|
||||||
</fieldset>
|
}
|
||||||
<fieldset>
|
</script>
|
||||||
<legend>Unités</legend>
|
</fieldset>
|
||||||
<table cellspacing="0" cellpadding="0">
|
<fieldset id="unitesFS">
|
||||||
<tr>
|
<legend>Unités</legend>
|
||||||
<td th:each="unite : ${defUnits}" class="squareContainer">
|
<div th:each="unite : ${defUnits}" class="container">
|
||||||
<img class="squareImage" th:for="'unite-'+${unite.id}" th:src="@{/images/units/{uname}.png(uname=${unite.id})}"/>
|
<img class="squareImage" th:for="'unite-'+${unite.id}" th:src="@{/images/units/{uname}.png(uname=${unite.id})}"/>
|
||||||
<input type="number" class="squareNumber" th:id="'unite-'+${unite.id}" th:field="*{units[__${unite.id}__]}"/>
|
<br/>
|
||||||
</td>
|
<input type="number" class="squareNumber" th:id="'unite-'+${unite.id}" th:field="*{offUnits[__${unite.id}__]}"/>
|
||||||
</tr>
|
</div>
|
||||||
</table>
|
</fieldset>
|
||||||
</fieldset>
|
<fieldset>
|
||||||
<fieldset>
|
<legend>Pouvoirs</legend>
|
||||||
<legend>Batiments</legend>
|
<div th:each="power : ${offPowers}" class="container">
|
||||||
<label for="hasTower">Tour :</label>
|
|
||||||
<input type="checkbox" id="hasTower" th:field="*{hasTower}"/><br/>
|
|
||||||
|
|
||||||
<label for="wallLevelSlider">Niveau des remparts: (<span id="wallLevelSliderInfo" class="fixed50px"></span>)</label>
|
|
||||||
<input type="range" min="0" max="25" value="1" class="slider" id="wallLevelSlider" th:field="*{wallLevel}">
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var wallSlider = document.getElementById("wallLevelSlider");
|
|
||||||
var wallOutput = document.getElementById("wallLevelSliderInfo");
|
|
||||||
wallOutput.innerHTML = "lvl. "+wallSlider.value;
|
|
||||||
// Update the current slider value (each time you drag the slider handle)
|
|
||||||
wallSlider.oninput = function() {
|
|
||||||
wallOutput.innerHTML = "lvl. "+this.value;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
<legend>Pouvoirs</legend>
|
|
||||||
<table cellspacing="0" cellpadding="0">
|
|
||||||
<tr>
|
|
||||||
<td th:each="power : ${defPowers}" class="squareContainer">
|
|
||||||
<img class="squareImage" th:for="'power-'+${power}" th:src="@{/images/powers/{pname}.png(pname=${power})}"/>
|
<img class="squareImage" th:for="'power-'+${power}" th:src="@{/images/powers/{pname}.png(pname=${power})}"/>
|
||||||
<input type="checkbox" th:id="'power-'+${power}" th:field="*{powersAsMap[__${power}__]}" th:value="true"/>
|
<input type="checkbox" th:id="'power-'+${power}" th:field="*{defPowersAsMap[__${power}__]}" th:value="true"/>
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
</fieldset>
|
||||||
</table>
|
<fieldset>
|
||||||
</fieldset>
|
<legend>Recherches</legend>
|
||||||
<fieldset>
|
<div th:each="research : ${offResearches}" class="container">
|
||||||
<legend>Recherches</legend>
|
<img class="squareImage" th:for="'research-'+${research}" th:src="@{/images/researches/{rname}.png(rname=${research})}"/>
|
||||||
<table cellspacing="0" cellpadding="0">
|
<input type="checkbox" th:id="'research-'+${research}" th:field="*{defResearchesAsMap[__${research}__]}" th:value="true"/>
|
||||||
<tr>
|
</div>
|
||||||
<td th:each="research : ${defResearches}" class="squareContainer">
|
</fieldset>
|
||||||
<img class="squareImage" th:for="'research-'+${research.id}" th:src="@{/images/researches/{rname}.png(rname=${research.id})}"/>
|
<fieldset>
|
||||||
<input type="checkbox" th:id="'research-'+${research.id}" th:field="*{researchesAsMap[__${research.id}__]}" th:value="true"/>
|
<legend>Conseillers</legend>
|
||||||
</td>
|
<div th:each="counsellor : ${offCounsellors}" class="container">
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
<legend>Conseillers</legend>
|
|
||||||
<table cellspacing="0" cellpadding="0">
|
|
||||||
<tr>
|
|
||||||
<td th:each="counsellor : ${defCounsellors}" class="squareContainer">
|
|
||||||
<img class="squareImage" th:for="'counsellor-'+${counsellor}" th:src="@{/images/counsellors/{cname}.png(cname=${counsellor})}"/>
|
<img class="squareImage" th:for="'counsellor-'+${counsellor}" th:src="@{/images/counsellors/{cname}.png(cname=${counsellor})}"/>
|
||||||
<input type="checkbox" th:id="'counsellor-'+${counsellor}" th:field="*{counsellorsAsMap[__${counsellor}__]}" th:value="true"/>
|
<input type="checkbox" th:id="'counsellor-'+${counsellor}" th:field="*{defCounsellorsAsMap[__${counsellor}__]}" th:value="true"/>
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
</fieldset>
|
||||||
</table>
|
<fieldset>
|
||||||
</fieldset>
|
<legend>Paramètres</legend>
|
||||||
<fieldset>
|
|
||||||
<legend>Bonus de jeu</legend>
|
<label for="moralInput">Moral:</label>
|
||||||
<label for="nightBonus">Bonus de nuit :</label>
|
<input type="number" min="0" max="100" value="1" id="moralInput" th:field="*{moral}">
|
||||||
<input type="checkbox" id="nightBonus" th:field="*{nightBonus}" th:value="true"/><br/>
|
<label for="luckInput">Chance:</label>
|
||||||
</fieldset>
|
<input type="number" min="-20" max="20" value="1" id="luckInput" th:field="*{luck}">
|
||||||
|
<label for="breachInput">Percée:</label>
|
||||||
|
<input type="checkbox" id="breachInput" th:field="*{strategyBreach}">
|
||||||
|
<label for="allianceInput">Alliance:</label>
|
||||||
|
<input type="checkbox" id="allianceInput" th:field="*{allianceModifier}">
|
||||||
|
</fieldset>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="formcol">
|
||||||
|
<legend>Défense</legend>
|
||||||
|
<fieldset id="herosFields">
|
||||||
|
<legend>Héros</legend>
|
||||||
|
<select name="defHeros" id="defHeros" th:field="*{defHero}">
|
||||||
|
<option value="none">Aucun</option>
|
||||||
|
<option th:each="hero : ${heroes}" th:value="${hero.id}"><span th:text="${hero.name}"/></option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label for="heroLevelSlider">Niveau du héros: (<span id="heroLevelSliderInfo" class="fixed50px"></span>)</label>
|
||||||
|
<input type="range" min="1" max="20" value="1" class="slider" id="heroLevelSlider" th:field="*{defHeroLevel}">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var heroSlider = document.getElementById("heroLevelSlider");
|
||||||
|
var heroOutput = document.getElementById("heroLevelSliderInfo");
|
||||||
|
heroOutput.innerHTML = "lvl. "+heroSlider.value;
|
||||||
|
// Update the current slider value (each time you drag the slider handle)
|
||||||
|
heroSlider.oninput = function() {
|
||||||
|
heroOutput.innerHTML = "lvl. "+this.value;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset id="unitesFS">
|
||||||
|
<legend>Unités</legend>
|
||||||
|
<div th:each="unite : ${defUnits}" class="container">
|
||||||
|
<img class="squareImage" th:for="'unite-'+${unite.id}" th:src="@{/images/units/{uname}.png(uname=${unite.id})}"/>
|
||||||
|
<br/>
|
||||||
|
<input type="number" class="squareNumber" th:id="'unite-'+${unite.id}" th:field="*{defUnits[__${unite.id}__]}"/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Batiments</legend>
|
||||||
|
<label for="hasTower">Tour :</label>
|
||||||
|
<input type="checkbox" id="hasTower" th:field="*{hasTower}"/><br/>
|
||||||
|
|
||||||
|
<label for="wallLevelSlider">Niveau des remparts: (<span id="wallLevelSliderInfo" class="fixed50px"></span>)</label>
|
||||||
|
<input type="range" min="0" max="25" value="1" class="slider" id="wallLevelSlider" th:field="*{wallLevel}">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var wallSlider = document.getElementById("wallLevelSlider");
|
||||||
|
var wallOutput = document.getElementById("wallLevelSliderInfo");
|
||||||
|
wallOutput.innerHTML = "lvl. "+wallSlider.value;
|
||||||
|
// Update the current slider value (each time you drag the slider handle)
|
||||||
|
wallSlider.oninput = function() {
|
||||||
|
wallOutput.innerHTML = "lvl. "+this.value;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Pouvoirs</legend>
|
||||||
|
<div th:each="power : ${defPowers}" class="container">
|
||||||
|
<img class="squareImage" th:for="'power-'+${power}" th:src="@{/images/powers/{pname}.png(pname=${power})}"/>
|
||||||
|
<input type="checkbox" th:id="'power-'+${power}" th:field="*{defPowersAsMap[__${power}__]}" th:value="true"/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Recherches</legend>
|
||||||
|
<div th:each="research : ${defResearches}" class="container">
|
||||||
|
<img class="squareImage" th:for="'research-'+${research}" th:src="@{/images/researches/{rname}.png(rname=${research})}"/>
|
||||||
|
<input type="checkbox" th:id="'research-'+${research}" th:field="*{defResearchesAsMap[__${research}__]}" th:value="true"/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Conseillers</legend>
|
||||||
|
<div th:each="counsellor : ${defCounsellors}" class="container">
|
||||||
|
<img class="squareImage" th:for="'counsellor-'+${counsellor}" th:src="@{/images/counsellors/{cname}.png(cname=${counsellor})}"/>
|
||||||
|
<input type="checkbox" th:id="'counsellor-'+${counsellor}" th:field="*{defCounsellorsAsMap[__${counsellor}__]}" th:value="true"/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Bonus de jeu</legend>
|
||||||
|
<label for="nightBonus">Bonus de nuit :</label>
|
||||||
|
<input type="checkbox" id="nightBonus" th:field="*{nightBonus}" th:value="true"/><br/>
|
||||||
|
</fieldset>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
<button type="button" id="compute">Calculer</button>
|
<button type="button" id="compute">Calculer</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user