276 lines
11 KiB
Java
276 lines
11 KiB
Java
package com.bernard.greposimu.engine.game;
|
||
|
||
import java.util.List;
|
||
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.GameConfig;
|
||
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.TerrestrialUnit;
|
||
import com.bernard.greposimu.model.game.units.Unit;
|
||
|
||
public class Fight {
|
||
|
||
public FightResult simulateFight(GameConfig gc, OffContext off, DefContext def) {
|
||
FightStats offStats = computeOffStats(gc, off);
|
||
FightStats defStats = computeDefStats(gc, def);
|
||
|
||
// Combat Naval
|
||
if(offStats.getShip() > defStats.getShip()) {
|
||
// Off wins ship
|
||
} else {
|
||
|
||
}
|
||
//TODO simulateFight
|
||
throw new UnsupportedOperationException("Simulator not created");
|
||
}
|
||
|
||
|
||
public static FightStats computeDefStats(GameConfig gc, DefContext def) {
|
||
|
||
FightStats everyoneStatsBonus = FightStats.zero();
|
||
Map<Unit,FightStats> unitsBonuses;
|
||
FightStats cityBaseStats;
|
||
|
||
// Heroes
|
||
unitsBonuses = Heroes.heroFightBonuses(gc, def.getHero(), def.getHeroLevel(), false);
|
||
|
||
// Tower & wall
|
||
if(def.hasTrojanDefense()) {
|
||
cityBaseStats = Buildings.cityBaseStats(def.getWallLevel()+1);
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, Buildings.wallBonus(def.getWallLevel()+1));
|
||
} else {
|
||
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));
|
||
|
||
// Researches
|
||
if(def.hasDivineSelection())
|
||
for(Unit u : gc.getUnits())
|
||
if(u.isMythological())
|
||
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.1)));
|
||
if(def.hasPhalanx())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(0.1));
|
||
if(def.hasRam())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.naval(0.1));
|
||
|
||
// Counsellors
|
||
if(def.hasPriest())
|
||
for(Unit u : gc.getUnits())
|
||
if(u.isMythological())
|
||
unitsBonuses.put(u, FightStats.add(unitsBonuses.getOrDefault(u, FightStats.zero()), FightStats.cst(0.2)));
|
||
if(def.hasCommander())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(0.2));
|
||
if(def.hasCaptain())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.naval(0.2));
|
||
|
||
// Powers
|
||
if(def.hasMyrmidionAttack())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(-0.1));
|
||
if(def.hasDefenseBoost())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.05));
|
||
if(def.hasDefensePenalty())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(-0.1));
|
||
if(def.hasLongtermDefenseBoost())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.05));
|
||
if(def.hasRareDefenseBoost())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.05));
|
||
if(def.hasEpicDefenseBoost())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.1));
|
||
if(def.getOlympicTorchGrepolympiaSummerLevel()!=0)
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.05*def.getOlympicTorchGrepolympiaSummerLevel()));
|
||
if(def.getSoteriasShrineLevel()!=0)
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(+0.007*def.getSoteriasShrineLevel()));
|
||
if(def.hasNarcissism())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.terrestre(-0.1));
|
||
|
||
// Night Bonus
|
||
if(def.isNightBonus())
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.cst(1.0));
|
||
|
||
// Units
|
||
FightStats total = cityBaseStats.clone();
|
||
for(Unit u : gc.getUnits()) {
|
||
// total = total + ucount * ((1+bonus+bonus) * ustats)
|
||
total = FightStats.add(total,
|
||
FightStats.prod(def.unitCount(u),
|
||
FightStats.mul(
|
||
FightStats.add(FightStats.one(),everyoneStatsBonus,unitsBonuses.getOrDefault(u, FightStats.zero()))
|
||
, makeDefStats(u))
|
||
));
|
||
}
|
||
|
||
// 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;
|
||
}
|
||
|
||
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 FightStats computeOffStats(GameConfig gc, OffContext off) {
|
||
|
||
FightStats everyoneStatsBonus = FightStats.zero();
|
||
Map<Unit,FightStats> unitsBonuses;
|
||
|
||
// Heroes
|
||
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
|
||
));
|
||
}
|
||
|
||
// Bonuses
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.cst(off.getLuck()/100.0));
|
||
everyoneStatsBonus = FightStats.add(everyoneStatsBonus, FightStats.cst(-(100.0-off.getMorale())/100.0));
|
||
|
||
|
||
return total;
|
||
}
|
||
|
||
public static FightStats makeOffStats(Unit u) {
|
||
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) {
|
||
return gc.getUnits().stream().toList();
|
||
}
|
||
public static List<Unit> relevantOffUnits(GameConfig gc) {
|
||
return gc.getUnits().stream().toList();
|
||
}
|
||
|
||
|
||
|
||
|
||
public static class FightResult {
|
||
|
||
Map<String, Integer> def_losses;
|
||
Map<String, Integer> att_losses;
|
||
int wall_loss;
|
||
int att_battle_points;
|
||
int def_battle_points;
|
||
|
||
}
|
||
|
||
}
|