From a266b8d096961f470b337e35709e147bc3f8364f Mon Sep 17 00:00:00 2001 From: 1brucben <1benjbruce@gmail.com> Date: Tue, 6 May 2025 17:40:54 +0200 Subject: [PATCH] update defaultconfig file --- src/core/configuration/DefaultConfig.ts | 190 +++++++++++++----------- 1 file changed, 106 insertions(+), 84 deletions(-) diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 226a893cd..c90f4f910 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -56,7 +56,11 @@ export abstract class DefaultServerConfig implements ServerConfig { r2SecretKey(): string { return process.env.R2_SECRET_KEY; } - abstract r2Bucket(): string; + + r2Bucket(): string { + return process.env.R2_BUCKET; + } + adminHeader(): string { return "x-admin-key"; } @@ -196,13 +200,13 @@ export class DefaultConfig implements Config { } cityPopulationIncrease(): number { - return 250_000; + return 500_000; } falloutDefenseModifier(falloutRatio: number): number { // falloutRatio is between 0 and 1 // So defense modifier is between [5, 2.5] - return 5 - falloutRatio * 2; + return 3 - falloutRatio * 2; } SAMCooldown(): number { return 75; @@ -212,17 +216,19 @@ export class DefaultConfig implements Config { } defensePostRange(): number { - return 30; + return 40; } defensePostDefenseBonus(): number { - return 5; + return 4; } numPlayerTeams(): number { return this._gameConfig.numPlayerTeams ?? 0; } + spawnNPCs(): boolean { return !this._gameConfig.disableNPCs; } + disableNukes(): boolean { return this._gameConfig.disableNukes; } @@ -242,12 +248,7 @@ export class DefaultConfig implements Config { return 10000 + 150 * Math.pow(dist, 1.1); } tradeShipSpawnRate(numberOfPorts: number): number { - if (numberOfPorts <= 3) return 18; - if (numberOfPorts <= 5) return 25; - if (numberOfPorts <= 8) return 35; - if (numberOfPorts <= 10) return 40; - if (numberOfPorts <= 12) return 45; - return 50; + return Math.round(10 * Math.pow(numberOfPorts, 0.5)); } unitInfo(type: UnitType): UnitInfo { @@ -274,7 +275,7 @@ export class DefaultConfig implements Config { return { cost: () => 0, territoryBound: false, - damage: 250, + damage: 200, }; case UnitType.SAMMissile: return { @@ -439,26 +440,25 @@ export class DefaultConfig implements Config { defenderTroopLoss: number; tilesPerTickUsed: number; } { - let mag = 0; - let speed = 0; + const terrainModifiers = { + [TerrainType.Plains]: { mag: 0.85, speed: 0.75 }, + [TerrainType.Highland]: { mag: 1, speed: 1 }, + [TerrainType.Mountain]: { mag: 1.2, speed: 1.4 }, + } as const; + const type = gm.terrainType(tileToConquer); - switch (type) { - case TerrainType.Plains: - mag = 85; - speed = 16.5; - break; - case TerrainType.Highland: - mag = 100; - speed = 20; - break; - case TerrainType.Mountain: - mag = 120; - speed = 25; - break; - default: - throw new Error(`terrain type ${type} not supported`); + const mod = terrainModifiers[type]; + if (!mod) { + throw new Error(`terrain type ${type} not supported`); } - if (defender.isPlayer()) { + let mag = mod.mag; + let speed = mod.speed; + + const attackerType = attacker.type(); + const defenderIsPlayer = defender.isPlayer(); + const defenderType = defenderIsPlayer ? defender.type() : null; + + if (defenderIsPlayer) { for (const dp of gm.nearbyUnits( tileToConquer, gm.config().defensePostRange(), @@ -478,55 +478,51 @@ export class DefaultConfig implements Config { speed *= this.falloutDefenseModifier(falloutRatio); } - if (attacker.isPlayer() && defender.isPlayer()) { + if (attacker.isPlayer() && defenderIsPlayer) { + if (attackerType == PlayerType.Human && defenderType == PlayerType.Bot) { + mag *= 0.8; + } if ( - attacker.type() == PlayerType.Human && - defender.type() == PlayerType.Bot + attackerType == PlayerType.FakeHuman && + defenderType == PlayerType.Bot ) { mag *= 0.8; } if ( - attacker.type() == PlayerType.FakeHuman && - defender.type() == PlayerType.Bot + attackerType == PlayerType.Human && + defenderType == PlayerType.FakeHuman ) { - mag *= 0.8; + //mag *= 0.9; + //speed *= 0.9; } } - - let largeLossModifier = 1; - if (attacker.numTilesOwned() > 100_000) { - largeLossModifier = Math.sqrt(100_000 / attacker.numTilesOwned()); + if (attackerType == PlayerType.Bot) { + speed *= 4; // slow bot attacks } - let largeSpeedMalus = 1; - if (attacker.numTilesOwned() > 75_000) { - // sqrt is only exponent 1/2 which doesn't slow enough huge players - largeSpeedMalus = (75_000 / attacker.numTilesOwned()) ** 0.6; - } - - if (defender.isPlayer()) { + if (defenderIsPlayer) { + const defenderTroops = defender.troops(); + const defenderTiles = defender.numTilesOwned(); + const defenderdensity = defenderTroops / defenderTiles; + const attackratio = defenderTroops / attackTroops; return { attackerTroopLoss: - within(defender.troops() / attackTroops, 0.6, 2) * - mag * - 0.8 * - largeLossModifier * - (defender.isTraitor() ? this.traitorDefenseDebuff() : 1), - defenderTroopLoss: defender.troops() / defender.numTilesOwned(), + mag * 10 + + defenderdensity * + mag * + (defender.isTraitor() ? this.traitorDefenseDebuff() : 1), + defenderTroopLoss: defenderdensity, tilesPerTickUsed: - within(defender.troops() / (5 * attackTroops), 0.2, 1.5) * + 27 * + within(defenderdensity, 3, 100) ** 0.2 * + (10_000 / attackTroops) ** 0.1 * speed * - largeSpeedMalus, + within(attackratio, 0.3, 20) ** 0.3, }; } else { return { - attackerTroopLoss: - attacker.type() == PlayerType.Bot ? mag / 10 : mag / 5, + attackerTroopLoss: attackerType == PlayerType.Bot ? mag * 10 : mag * 10, defenderTroopLoss: 0, - tilesPerTickUsed: within( - (2000 * Math.max(10, speed)) / attackTroops, - 5, - 100, - ), + tilesPerTickUsed: 30 * speed, // * (10_000 / attackTroops) ** 0.5, }; } } @@ -538,13 +534,9 @@ export class DefaultConfig implements Config { numAdjacentTilesWithEnemy: number, ): number { if (defender.isPlayer()) { - return ( - within(((5 * attackTroops) / defender.troops()) * 2, 0.01, 0.5) * - numAdjacentTilesWithEnemy * - 3 - ); + return 10 * numAdjacentTilesWithEnemy; } else { - return numAdjacentTilesWithEnemy * 2; + return 12 * numAdjacentTilesWithEnemy; } } @@ -574,18 +566,18 @@ export class DefaultConfig implements Config { startManpower(playerInfo: PlayerInfo): number { if (playerInfo.playerType == PlayerType.Bot) { - return 10_000; + return 6_000; } if (playerInfo.playerType == PlayerType.FakeHuman) { switch (this._gameConfig.difficulty) { case Difficulty.Easy: - return 2_500 * (playerInfo?.nation?.strength ?? 1); + return 2_500 + 1000 * (playerInfo?.nation?.strength ?? 1); case Difficulty.Medium: - return 5_000 * (playerInfo?.nation?.strength ?? 1); + return 6_000 + 2000 * (playerInfo?.nation?.strength ?? 1); case Difficulty.Hard: - return 20_000 * (playerInfo?.nation?.strength ?? 1); + return 20_000 + 4000 * (playerInfo?.nation?.strength ?? 1); case Difficulty.Impossible: - return 50_000 * (playerInfo?.nation?.strength ?? 1); + return 50_000 + 8000 * (playerInfo?.nation?.strength ?? 1); } } return this.infiniteTroops() ? 1_000_000 : 25_000; @@ -595,11 +587,11 @@ export class DefaultConfig implements Config { const maxPop = player.type() == PlayerType.Human && this.infiniteTroops() ? 1_000_000_000 - : 2 * (Math.pow(player.numTilesOwned(), 0.6) * 1000 + 50000) + + : 1 * (player.numTilesOwned() * 30 + 50000) + player.units(UnitType.City).length * this.cityPopulationIncrease(); if (player.type() == PlayerType.Bot) { - return maxPop / 2; + return maxPop / 3; } if (player.type() == PlayerType.Human) { @@ -608,11 +600,11 @@ export class DefaultConfig implements Config { switch (this._gameConfig.difficulty) { case Difficulty.Easy: - return maxPop * 0.5; + return maxPop * 0.4; case Difficulty.Medium: - return maxPop * 1; + return maxPop * 0.7; case Difficulty.Hard: - return maxPop * 1.5; + return maxPop * 1; case Difficulty.Impossible: return maxPop * 2; } @@ -621,9 +613,15 @@ export class DefaultConfig implements Config { populationIncreaseRate(player: Player): number { const max = this.maxPopulation(player); - let toAdd = 10 + Math.pow(player.population(), 0.73) / 4; + let toAdd = + 10 + + (1400 / max + 1 / 125) * (0.8 * player.troops() + 1.2 * player.workers()); + const adjustedPop = + typeof player.adjustedPopulation === "function" + ? player.adjustedPopulation() + : player.population(); - const ratio = 1 - player.population() / max; + const ratio = 1 - adjustedPop / max; toAdd *= ratio; if (player.type() == PlayerType.Bot) { @@ -651,11 +649,35 @@ export class DefaultConfig implements Config { } goldAdditionRate(player: Player): number { - return Math.sqrt(player.workers() * player.numTilesOwned()) / 200; + const numCities = player.units(UnitType.City).length; + const baseCityPopulation = numCities * this.cityPopulationIncrease(); + + const totalWorkers = player.workers() ?? 0; + const totalPopulation = player.population() ?? 0; + const maxPopulation = this.maxPopulation(player) ?? 0; + const numTiles = player.numTilesOwned() ?? 0; + + if (totalWorkers <= 0 || totalPopulation <= 0 || maxPopulation <= 0) { + return 0; + } + + const populationRatio = totalPopulation / maxPopulation; + const adjustedCityPopulation = baseCityPopulation * populationRatio; + + const cityWorkers = + (adjustedCityPopulation * totalWorkers) / totalPopulation; + const ruralWorkers = totalWorkers - cityWorkers; + + const cityGold = cityWorkers / 2000; + const tileGold = (ruralWorkers ** 0.5 * numTiles ** 0.5) / 600; + + const totalGold = 6 * (cityGold + tileGold) ** 0.8; + + return Number.isFinite(totalGold) ? totalGold : 0; } troopAdjustmentRate(player: Player): number { - const maxDiff = this.maxPopulation(player) / 1000; + const maxDiff = this.maxPopulation(player) / 500; const target = player.population() * player.targetTroopRatio(); const diff = target - player.troops(); if (Math.abs(diff) < maxDiff) { @@ -686,7 +708,7 @@ export class DefaultConfig implements Config { // Humans can be population, soldiers attacking, soldiers in boat etc. nukeDeathFactor(humans: number, tilesOwned: number): number { - return (5 * humans) / Math.max(1, tilesOwned); + return (2 * humans) / Math.max(1, tilesOwned); } structureMinDist(): number { @@ -711,7 +733,7 @@ export class DefaultConfig implements Config { } defensePostShellAttackRate(): number { - return 100; + return 120; } safeFromPiratesCooldownMax(): number {