From 51c05f9d108d0cf0d70bd7febe808140716cba85 Mon Sep 17 00:00:00 2001 From: evanpelle Date: Fri, 16 Aug 2024 13:10:44 -0700 Subject: [PATCH] moved attack logic to config --- README.md | 1 - src/core/GameImpl.ts | 1 + src/core/configuration/Config.ts | 10 +++++++-- src/core/configuration/DefaultConfig.ts | 25 ++++++++++++++++++----- src/core/execution/AttackExecution.ts | 18 ++++++++-------- src/core/execution/BoatAttackExecution.ts | 8 +++++--- src/core/execution/BotExecution.ts | 6 ++++-- src/core/execution/Executor.ts | 4 +++- src/core/execution/SpawnExecution.ts | 2 +- 9 files changed, 51 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 882214ac2..6e5265569 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ To build the project, you will need to have Node.js and npm installed. You can d Before building the project, you will need to install the dependencies. You can do this by running the following command in the project directory: ```bash -git submodule update --init --recursive npm install ``` diff --git a/src/core/GameImpl.ts b/src/core/GameImpl.ts index dcb19082b..65b04de69 100644 --- a/src/core/GameImpl.ts +++ b/src/core/GameImpl.ts @@ -127,6 +127,7 @@ export class PlayerImpl implements MutablePlayer { } removeTroops(troops: number): void { this._troops -= troops + this._troops = Math.max(this._troops, 0) } isPlayer(): this is MutablePlayer {return true as const} diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index 6b3357b6a..4d1d00f54 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -1,7 +1,8 @@ -import {Player, PlayerID, PlayerInfo, TerrainType, TerrainTypes, TerraNullius} from "../Game"; +import {Player, PlayerID, PlayerInfo, TerrainType, TerrainTypes, TerraNullius, Tile} from "../Game"; import {Colord, colord} from "colord"; import {pastelTheme} from "./PastelTheme"; + export interface Config { theme(): Theme; player(): PlayerConfig @@ -13,7 +14,12 @@ export interface Config { export interface PlayerConfig { startTroops(playerInfo: PlayerInfo): number troopAdditionRate(player: Player): number - attackLogic(attack: Player, defender: Player | TerraNullius): number + attackTilesPerTick(attacker: Player, defender: Player | TerraNullius, numAdjacentTilesWithEnemy: number): number + attackLogic(attacker: Player, defender: Player | TerraNullius, tileToConquer: Tile): { + attackerTroopLoss: number, + defenderTroopLoss: number, + tilesPerTickUsed: number + } attackAmount(attacker: Player, defender: Player | TerraNullius): number boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number } diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 03e35cf5a..eb84639ed 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -1,4 +1,4 @@ -import {Player, PlayerInfo, TerraNullius} from "../Game"; +import {Player, PlayerInfo, TerraNullius, Tile} from "../Game"; import {Config, PlayerConfig, Theme} from "./Config"; import {pastelTheme} from "./PastelTheme"; @@ -19,9 +19,28 @@ export const defaultConfig = new class implements Config { } export const defaultPlayerConfig = new class implements PlayerConfig { + + attackLogic(attacker: Player, defender: Player | TerraNullius, tileToConquer: Tile): {attackerTroopLoss: number; defenderTroopLoss: number; tilesPerTickUsed: number} { + if (defender.isPlayer()) { + return { + attackerTroopLoss: Math.max(defender.troops() / attacker.troops(), 1), + defenderTroopLoss: 0, + tilesPerTickUsed: Math.max(defender.troops() / attacker.troops(), .25) + } + } else { + return {attackerTroopLoss: 1, defenderTroopLoss: 0, tilesPerTickUsed: 1} + } + + } + + attackTilesPerTick(attacker: Player, defender: Player | TerraNullius, numAdjacentTilesWithEnemy: number): number { + return numAdjacentTilesWithEnemy / 4 + } + boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number { return attacker.troops() / 5 } + attackAmount(attacker: Player, defender: Player | TerraNullius) { if (attacker.info().isBot) { return attacker.troops() / 20 @@ -44,8 +63,4 @@ export const defaultPlayerConfig = new class implements PlayerConfig { return Math.min(player.troops() + toAdd, max) } - attackLogic(attack: Player, defender: Player | TerraNullius): number { - throw new Error("Method not implemented."); - } - } \ No newline at end of file diff --git a/src/core/execution/AttackExecution.ts b/src/core/execution/AttackExecution.ts index e50044eb8..2ddb98af7 100644 --- a/src/core/execution/AttackExecution.ts +++ b/src/core/execution/AttackExecution.ts @@ -2,6 +2,7 @@ import PriorityQueue from "priority-queue-typescript"; import {Cell, Execution, MutableGame, MutablePlayer, PlayerID, Player, TerrainTypes, TerraNullius, Tile} from "../Game"; import {PseudoRandom} from "../PseudoRandom"; import {manhattanDist} from "../Util"; +import {PlayerConfig} from "../configuration/Config"; export class AttackExecution implements Execution { private active: boolean = true; @@ -20,7 +21,8 @@ export class AttackExecution implements Execution { private troops: number, private _ownerID: PlayerID, private targetID: PlayerID | null, - private targetCell: Cell | null + private targetCell: Cell | null, + private playerConfig: PlayerConfig ) { } init(mg: MutableGame, ticks: number) { @@ -61,7 +63,7 @@ export class AttackExecution implements Execution { return } - let numTilesPerTick = this.numTilesWithEnemy / 4 + let numTilesPerTick = this.playerConfig.attackTilesPerTick(this._owner, this.target, this.numTilesWithEnemy) if (this.targetCell != null) { numTilesPerTick /= 2 } @@ -88,15 +90,13 @@ export class AttackExecution implements Execution { badTiles++ continue } - // TODO: move this to configs - this._owner.conquer(tileToConquer) + const {attackerTroopLoss, defenderTroopLoss, tilesPerTickUsed} = this.playerConfig.attackLogic(this._owner, this.target, tileToConquer) + numTilesPerTick -= tilesPerTickUsed + this.troops -= attackerTroopLoss if (this.target.isPlayer()) { - this.troops -= Math.max(this.target.troops() / this._owner.troops(), 1) - numTilesPerTick -= Math.max(this.target.troops() / this._owner.troops(), .25) - } else { - this.troops -= 1 - numTilesPerTick -= 1 + this.target.removeTroops(defenderTroopLoss) } + this._owner.conquer(tileToConquer) } } diff --git a/src/core/execution/BoatAttackExecution.ts b/src/core/execution/BoatAttackExecution.ts index ddadc7565..f844c80e4 100644 --- a/src/core/execution/BoatAttackExecution.ts +++ b/src/core/execution/BoatAttackExecution.ts @@ -2,6 +2,7 @@ import PriorityQueue from "priority-queue-typescript"; import {Boat, Cell, Execution, MutableBoat, MutableGame, MutablePlayer, Player, PlayerID, Tile} from "../Game"; import {manhattanDist} from "../Util"; import {AttackExecution} from "./AttackExecution"; +import {PlayerConfig} from "../configuration/Config"; export class BoatAttackExecution implements Execution { @@ -29,7 +30,8 @@ export class BoatAttackExecution implements Execution { private attackerID: PlayerID, private targetID: PlayerID | null, private cell: Cell, - private troops: number + private troops: number, + private playerConfig: PlayerConfig ) { } init(mg: MutableGame, ticks: number) { @@ -48,7 +50,7 @@ export class BoatAttackExecution implements Execution { this.src = this.closestShoreTileToTarget(this.attacker, this.cell) this.dst = this.closestShoreTileToTarget(this.target, this.cell) - if(this.src == null || this.dst == null) { + if (this.src == null || this.dst == null) { this.active = false return } @@ -80,7 +82,7 @@ export class BoatAttackExecution implements Execution { return } this.attacker.conquer(this.dst) - this.mg.addExecution(new AttackExecution(this.troops, this.attacker.id(), this.targetID, null)) + this.mg.addExecution(new AttackExecution(this.troops, this.attacker.id(), this.targetID, null, this.playerConfig)) this.active = false return } diff --git a/src/core/execution/BotExecution.ts b/src/core/execution/BotExecution.ts index 893d004de..f6cc4d108 100644 --- a/src/core/execution/BotExecution.ts +++ b/src/core/execution/BotExecution.ts @@ -1,3 +1,4 @@ +import {PlayerConfig} from "../configuration/Config"; import {Cell, Execution, MutableGame, MutablePlayer, Player, PlayerID, PlayerInfo, TerraNullius} from "../Game" import {PseudoRandom} from "../PseudoRandom" import {AttackExecution} from "./AttackExecution"; @@ -10,7 +11,7 @@ export class BotExecution implements Execution { private gs: MutableGame private neighborsTerra = true - constructor(private bot: MutablePlayer) { + constructor(private bot: MutablePlayer, private playerConfig: PlayerConfig) { this.random = new PseudoRandom(bot.id()) this.attackRate = this.random.nextInt(10, 50) @@ -57,7 +58,8 @@ export class BotExecution implements Execution { this.bot.troops() / 20, this.bot.id(), toAttack.isPlayer() ? toAttack.id() : null, - null + null, + this.playerConfig )) } diff --git a/src/core/execution/Executor.ts b/src/core/execution/Executor.ts index a555d48ce..c976bbb64 100644 --- a/src/core/execution/Executor.ts +++ b/src/core/execution/Executor.ts @@ -25,7 +25,8 @@ export class Executor { intent.troops, intent.attackerID, intent.targetID, - new Cell(intent.targetX, intent.targetY) + new Cell(intent.targetX, intent.targetY), + this.playerConfig ) ) } else if (intent.type == "spawn") { @@ -43,6 +44,7 @@ export class Executor { intent.targetID, new Cell(intent.x, intent.y), intent.troops, + this.playerConfig ) ) } else { diff --git a/src/core/execution/SpawnExecution.ts b/src/core/execution/SpawnExecution.ts index 840da08e9..aa58ce0d9 100644 --- a/src/core/execution/SpawnExecution.ts +++ b/src/core/execution/SpawnExecution.ts @@ -30,7 +30,7 @@ export class SpawnExecution implements Execution { }) this.gs.addExecution(new PlayerExecution(player.id(), this.playerConfig)) if (player.info().isBot) { - this.gs.addExecution(new BotExecution(player)) + this.gs.addExecution(new BotExecution(player, this.playerConfig)) } this.active = false }