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 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 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 relevantDefUnits(GameConfig gc) { return gc.getUnits().stream().toList(); } public static List relevantOffUnits(GameConfig gc) { return gc.getUnits().stream().toList(); } public static class FightResult { Map def_losses; Map att_losses; int wall_loss; int att_battle_points; int def_battle_points; } }