276 lines
11 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}