From a4799a3c21795a2b313cbc9a4e8583f8fbca8e17 Mon Sep 17 00:00:00 2001 From: evanpelle Date: Mon, 12 Aug 2024 16:31:32 -0700 Subject: [PATCH] moved attack config to separate config class --- src/client/Client.ts | 4 +- src/client/ClientGame.ts | 30 +++--- src/client/graphics/GameRenderer.ts | 2 +- src/client/graphics/NameRenderer.ts | 2 +- src/core/Game.ts | 1 + src/core/Settings.ts | 130 ------------------------ src/core/Ticker.ts | 2 +- src/core/configuration/Config.ts | 31 ++++++ src/core/configuration/DefaultConfig.ts | 59 +++++++++++ src/core/configuration/PastelTheme.ts | 92 +++++++++++++++++ src/core/execution/Executor.ts | 4 +- src/core/execution/PlayerExecution.ts | 13 +-- src/core/execution/SpawnExecution.ts | 6 +- src/server/GameManager.ts | 7 +- src/server/GameServer.ts | 4 +- src/server/Server.ts | 4 +- 16 files changed, 222 insertions(+), 169 deletions(-) delete mode 100644 src/core/Settings.ts create mode 100644 src/core/configuration/Config.ts create mode 100644 src/core/configuration/DefaultConfig.ts create mode 100644 src/core/configuration/PastelTheme.ts diff --git a/src/client/Client.ts b/src/client/Client.ts index 66a011a34..62fc5c9d1 100644 --- a/src/client/Client.ts +++ b/src/client/Client.ts @@ -1,6 +1,6 @@ +import {defaultConfig} from "../core/configuration/DefaultConfig"; import {TerrainMap} from "../core/Game"; import {ServerMessage, ServerMessageSchema} from "../core/Schemas"; -import {defaultSettings} from "../core/Settings"; import {loadTerrainMap} from "../core/TerrainMapLoader"; import {generateUniqueID} from "../core/Util"; import {ClientGame, createClientGame} from "./ClientGame"; @@ -84,7 +84,7 @@ class Client { if (this.game != null) { return } - this.game = createClientGame(uuidv4().slice(0, 4), generateUniqueID(), lobbyID, defaultSettings, map) + this.game = createClientGame(uuidv4().slice(0, 4), generateUniqueID(), lobbyID, defaultConfig, map) this.game.joinLobby() }) } diff --git a/src/client/ClientGame.ts b/src/client/ClientGame.ts index 652a2bb97..bb9942df7 100644 --- a/src/client/ClientGame.ts +++ b/src/client/ClientGame.ts @@ -1,20 +1,20 @@ import {Executor} from "../core/execution/Executor"; -import {Cell, ClientID, MutableGame, LobbyID, PlayerEvent, PlayerID, PlayerInfo, MutablePlayer, TerrainMap, TileEvent, Player, Game, BoatEvent} from "../core/Game"; +import {Cell, ClientID, MutableGame, LobbyID, PlayerEvent, PlayerID, PlayerInfo, MutablePlayer, TerrainMap, TileEvent, Player, Game, BoatEvent, TerrainTypes} from "../core/Game"; import {createGame} from "../core/GameImpl"; import {Ticker, TickEvent} from "../core/Ticker"; import {EventBus} from "../core/EventBus"; -import {Settings} from "../core/Settings"; +import {Config} from "../core/configuration/Config"; import {GameRenderer} from "./graphics/GameRenderer"; import {InputHandler, MouseUpEvent, ZoomEvent, DragEvent, MouseDownEvent} from "./InputHandler" import {ClientIntentMessageSchema, ClientJoinMessageSchema, ClientMessageSchema, ServerMessage, ServerMessageSchema, ServerSyncMessage, Turn} from "../core/Schemas"; -export function createClientGame(name: string, clientID: ClientID, lobbyID: LobbyID, settings: Settings, terrainMap: TerrainMap): ClientGame { +export function createClientGame(name: string, clientID: ClientID, lobbyID: LobbyID, config: Config, terrainMap: TerrainMap): ClientGame { let eventBus = new EventBus() let gs = createGame(terrainMap, eventBus) - let gameRenderer = new GameRenderer(gs, settings.theme(), document.createElement("canvas")) - let ticker = new Ticker(settings.tickIntervalMs(), eventBus) + let gameRenderer = new GameRenderer(gs, config.theme(), document.createElement("canvas")) + let ticker = new Ticker(config.tickIntervalMs(), eventBus) return new ClientGame( name, @@ -25,7 +25,8 @@ export function createClientGame(name: string, clientID: ClientID, lobbyID: Lobb gs, gameRenderer, new InputHandler(eventBus), - new Executor(gs) + new Executor(gs, config.player()), + config ) } @@ -54,7 +55,8 @@ export class ClientGame { private gs: Game, private renderer: GameRenderer, private input: InputHandler, - private executor: Executor + private executor: Executor, + private config: Config ) { } public joinLobby() { @@ -158,13 +160,13 @@ export class ClientGame { const owner = tile.owner() const targetID = owner.isPlayer() ? owner.id() : null - if (tile.owner() != this.myPlayer) { + if (tile.owner() != this.myPlayer && tile.terrain() == TerrainTypes.Land) { if (this.myPlayer.sharesBorderWith(tile.owner())) { - this.sendAttackIntent(targetID, cell) + this.sendAttackIntent(targetID, cell, this.config.player().attackAmount(this.myPlayer, owner)) } else { // TODO verify on ocean console.log('going to send boat') - this.sendBoatAttackIntent(targetID, cell) + this.sendBoatAttackIntent(targetID, cell, this.config.player().boatAttackAmount(this.myPlayer, owner)) } } @@ -194,7 +196,7 @@ export class ClientGame { } } - private sendAttackIntent(targetID: PlayerID, cell: Cell) { + private sendAttackIntent(targetID: PlayerID, cell: Cell, troops: number) { const attack = JSON.stringify( ClientIntentMessageSchema.parse({ type: "intent", @@ -204,7 +206,7 @@ export class ClientGame { type: "attack", attackerID: this.myPlayer.id(), targetID: targetID, - troops: this.myPlayer.troops() / 5, + troops: troops, targetX: cell.x, targetY: cell.y } @@ -219,7 +221,7 @@ export class ClientGame { } } - private sendBoatAttackIntent(targetID: PlayerID, cell: Cell) { + private sendBoatAttackIntent(targetID: PlayerID, cell: Cell, troops: number) { const attack = JSON.stringify( ClientIntentMessageSchema.parse({ type: "intent", @@ -229,7 +231,7 @@ export class ClientGame { type: "boat", attackerID: this.myPlayer.id(), targetID: targetID, - troops: 2000, + troops: troops, x: cell.x, y: cell.y, } diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts index 6856109a9..5ff388d52 100644 --- a/src/client/graphics/GameRenderer.ts +++ b/src/client/graphics/GameRenderer.ts @@ -1,6 +1,6 @@ import {Colord} from "colord"; import {Cell, MutableGame, Game, PlayerEvent, Tile, TileEvent, Player, Execution, BoatEvent} from "../../core/Game"; -import {Theme} from "../../core/Settings"; +import {Theme} from "../../core/configuration/Config"; import {DragEvent, ZoomEvent} from "../InputHandler"; import {calculateBoundingBox, placeName} from "../NameBoxCalculator"; import {PseudoRandom} from "../../core/PseudoRandom"; diff --git a/src/client/graphics/NameRenderer.ts b/src/client/graphics/NameRenderer.ts index a04638f2e..0ca10bb6f 100644 --- a/src/client/graphics/NameRenderer.ts +++ b/src/client/graphics/NameRenderer.ts @@ -1,7 +1,7 @@ import PriorityQueue from "priority-queue-typescript" import {Cell, Game, Player} from "../../core/Game" import {PseudoRandom} from "../../core/PseudoRandom" -import {Theme} from "../../core/Settings" +import {Theme} from "../../core/configuration/Config" import {calculateBoundingBox} from "../NameBoxCalculator" class RenderInfo { diff --git a/src/core/Game.ts b/src/core/Game.ts index 666aa7d3c..3bb7f61ca 100644 --- a/src/core/Game.ts +++ b/src/core/Game.ts @@ -90,6 +90,7 @@ export interface MutableBoat extends Boat { export interface TerraNullius { ownsTile(cell: Cell): boolean isPlayer(): false + id(): PlayerID // always zero, maybe make it TerraNulliusID? } export interface Player { diff --git a/src/core/Settings.ts b/src/core/Settings.ts deleted file mode 100644 index e670d9b20..000000000 --- a/src/core/Settings.ts +++ /dev/null @@ -1,130 +0,0 @@ -import {PlayerID, TerrainType, TerrainTypes} from "./Game"; -import {Colord, colord} from "colord"; - -export interface Settings { - theme(): Theme; - turnIntervalMs(): number - tickIntervalMs(): number - ticksPerTurn(): number - lobbyCreationRate(): number - lobbyLifetime(): number -} - -export interface Theme { - playerInfoColor(id: PlayerID): Colord; - territoryColor(id: PlayerID): Colord; - borderColor(id: PlayerID): Colord; - terrainColor(tile: TerrainType): Colord; - backgroundColor(): Colord; - font(): string; -} - -export const defaultSettings = new class implements Settings { - ticksPerTurn(): number { - return 1 - } - turnIntervalMs(): number { - return 100 - } - lobbyCreationRate(): number { - return 2 * 1000 - } - lobbyLifetime(): number { - return 3 * 1000 - } - theme(): Theme {return pastelTheme;} - - tickIntervalMs(): number { - return 1000 / 20; // 50ms - } -} - -const pastelTheme = new class implements Theme { - private background = colord({r: 100, g: 100, b: 100}); - private land = colord({r: 244, g: 243, b: 198}); - private water = colord({r: 160, g: 203, b: 231}); - private territory = colord({r: 173, g: 216, b: 230}); - private territoryColors: Colord[] = [ - colord({r: 255, g: 179, b: 186}), // Vibrant Light Pink - colord({r: 255, g: 223, b: 186}), // Vibrant Peach - colord({r: 190, g: 255, b: 190}), // Vibrant Light Green - colord({r: 173, g: 216, b: 255}), // Vibrant Light Blue - colord({r: 224, g: 187, b: 255}), // Vibrant Light Purple - colord({r: 255, g: 191, b: 230}), // Vibrant Pink - colord({r: 210, g: 255, b: 210}), // Vibrant Mint Green - colord({r: 255, g: 213, b: 179}), // Vibrant Light Orange - colord({r: 198, g: 198, b: 255}), // Vibrant Lavender - colord({r: 255, g: 255, b: 186}), // Vibrant Light Yellow - colord({r: 186, g: 255, b: 201}), // Vibrant Seafoam Green - colord({r: 255, g: 186, b: 255}), // Vibrant Light Magenta - colord({r: 210, g: 255, b: 210}), // Vibrant Pale Green - colord({r: 255, g: 202, b: 202}), // Vibrant Salmon Pink - colord({r: 206, g: 206, b: 255}), // Vibrant Periwinkle - colord({r: 255, g: 234, b: 186}), // Vibrant Cream - colord({r: 186, g: 255, b: 255}), // Vibrant Light Cyan - colord({r: 238, g: 210, b: 255}), // Vibrant Lilac - colord({r: 206, g: 255, b: 238}), // Vibrant Pale Turquoise - colord({r: 255, g: 209, b: 186}), // Vibrant Peach - colord({r: 186, g: 216, b: 255}), // Vibrant Baby Blue - colord({r: 246, g: 255, b: 186}), // Vibrant Pale Yellow - colord({r: 220, g: 186, b: 255}), // Vibrant Light Violet - colord({r: 255, g: 186, b: 213}), // Vibrant Rose - colord({r: 186, g: 255, b: 226}), // Vibrant Honeydew - colord({r: 206, g: 236, b: 255}), // Vibrant Sky Blue - colord({r: 255, g: 232, b: 206}), // Vibrant Wheat - colord({r: 206, g: 255, b: 255}), // Vibrant Pale Cyan - colord({r: 255, g: 216, b: 216}), // Vibrant Misty Rose - colord({r: 216, g: 216, b: 255}), // Vibrant Pale Lavender - colord({r: 255, g: 250, b: 205}), // Vibrant Pale Goldenrod - colord({r: 216, g: 255, b: 216}), // Vibrant Pale Mint - colord({r: 255, g: 216, b: 255}), // Vibrant Pale Plum - colord({r: 220, g: 255, b: 220}), // Vibrant Mint Cream - colord({r: 255, g: 220, b: 220}), // Vibrant Pale Pink - colord({r: 220, g: 220, b: 255}), // Vibrant Pale Blue - colord({r: 255, g: 255, b: 220}), // Vibrant Light Goldenrod - colord({r: 220, g: 255, b: 255}), // Vibrant Light Azure - colord({r: 255, g: 220, b: 255}), // Vibrant Pale Magenta - colord({r: 230, g: 255, b: 230}), // Vibrant Honeydew - colord({r: 255, g: 230, b: 230}), // Vibrant Lavender Blush - colord({r: 230, g: 230, b: 255}), // Vibrant Ghost White - colord({r: 255, g: 239, b: 219}), // Vibrant Seashell - colord({r: 219, g: 255, b: 239}), // Vibrant Mint Cream - colord({r: 239, g: 219, b: 255}), // Vibrant Pale Lavender - colord({r: 255, g: 250, b: 230}), // Vibrant Floral White - colord({r: 230, g: 255, b: 250}), // Vibrant Azure Mist - colord({r: 250, g: 230, b: 255}), // Vibrant Pale Purple - colord({r: 250, g: 255, b: 230}), // Vibrant Ivory - colord({r: 230, g: 250, b: 255}) // Vibrant Alice Blue - ]; - playerInfoColor(id: PlayerID): Colord { - return colord({r: 0, g: 0, b: 0}) - } - - territoryColor(id: PlayerID): Colord { - return this.territoryColors[id % this.territoryColors.length] - } - - borderColor(id: PlayerID): Colord { - const tc = this.territoryColor(id).rgba; - return colord({ - r: Math.max(tc.r - 20, 0), - g: Math.max(tc.g - 20, 0), - b: Math.max(tc.b - 20, 0) - }) - } - - terrainColor(tile: TerrainType): Colord { - if (tile == TerrainTypes.Land) { - return this.land; - } - return this.water; - } - - backgroundColor(): Colord { - return this.background; - } - - font(): string { - return "Arial"; - } -} \ No newline at end of file diff --git a/src/core/Ticker.ts b/src/core/Ticker.ts index 9b8a85da8..e18569940 100644 --- a/src/core/Ticker.ts +++ b/src/core/Ticker.ts @@ -1,5 +1,5 @@ import {EventBus, GameEvent} from "./EventBus"; -import {Settings} from "./Settings"; +import {Config} from "./configuration/Config"; export class TickEvent implements GameEvent { constructor(public readonly tickCount: number) { } diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts new file mode 100644 index 000000000..5be6a386e --- /dev/null +++ b/src/core/configuration/Config.ts @@ -0,0 +1,31 @@ +import {Player, PlayerID, PlayerInfo, TerrainType, TerrainTypes, TerraNullius} from "../Game"; +import {Colord, colord} from "colord"; +import {pastelTheme} from "./PastelTheme"; + +export interface Config { + theme(): Theme; + player(): PlayerConfig + turnIntervalMs(): number + tickIntervalMs(): number + ticksPerTurn(): number + lobbyCreationRate(): number + lobbyLifetime(): number +} + +export interface PlayerConfig { + startTroops(playerInfo: PlayerInfo): number + troopAdditionRate(player: Player): number + attackLogic(attack: Player, defender: Player | TerraNullius): number + attackAmount(attacker: Player, defender: Player | TerraNullius): number + boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number +} + +export interface Theme { + playerInfoColor(id: PlayerID): Colord; + territoryColor(id: PlayerID): Colord; + borderColor(id: PlayerID): Colord; + terrainColor(tile: TerrainType): Colord; + backgroundColor(): Colord; + font(): string; +} + diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts new file mode 100644 index 000000000..feadd5356 --- /dev/null +++ b/src/core/configuration/DefaultConfig.ts @@ -0,0 +1,59 @@ +import {Player, PlayerInfo, TerraNullius} from "../Game"; +import {Config, PlayerConfig, Theme} from "./Config"; +import {pastelTheme} from "./PastelTheme"; + +export const defaultConfig = new class implements Config { + player(): PlayerConfig { + throw new Error("Method not implemented."); + } + + ticksPerTurn(): number { + return 1 + } + turnIntervalMs(): number { + return 100 + } + lobbyCreationRate(): number { + return 2 * 1000 + } + lobbyLifetime(): number { + return 3 * 1000 + } + theme(): Theme {return pastelTheme;} + + tickIntervalMs(): number { + return 1000 / 20; // 50ms + } +} + +export const defaultPlayerConfig = new class implements PlayerConfig { + 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 + } else { + return attacker.troops() / 5 + } + } + + startTroops(playerInfo: PlayerInfo): number { + return 1000 + } + + troopAdditionRate(player: Player): number { + let toAdd = Math.sqrt(player.numTilesOwned() * player.troops()) / 5 + + const max = Math.sqrt(player.numTilesOwned()) * 100 + 1000 + const ratio = 1 - player.troops() / max + toAdd *= ratio * ratio * ratio + toAdd = Math.max(2, toAdd) + return Math.min(player.troops(), 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/configuration/PastelTheme.ts b/src/core/configuration/PastelTheme.ts new file mode 100644 index 000000000..cccee6278 --- /dev/null +++ b/src/core/configuration/PastelTheme.ts @@ -0,0 +1,92 @@ +import {Colord, colord} from "colord"; +import {PlayerID, TerrainType, TerrainTypes} from "../Game"; +import {Theme} from "./Config"; + +export const pastelTheme = new class implements Theme { + private background = colord({r: 100, g: 100, b: 100}); + private land = colord({r: 244, g: 243, b: 198}); + private water = colord({r: 160, g: 203, b: 231}); + private territoryColors: Colord[] = [ + colord({r: 255, g: 179, b: 186}), // Vibrant Light Pink + colord({r: 255, g: 223, b: 186}), // Vibrant Peach + colord({r: 190, g: 255, b: 190}), // Vibrant Light Green + colord({r: 173, g: 216, b: 255}), // Vibrant Light Blue + colord({r: 224, g: 187, b: 255}), // Vibrant Light Purple + colord({r: 255, g: 191, b: 230}), // Vibrant Pink + colord({r: 210, g: 255, b: 210}), // Vibrant Mint Green + colord({r: 255, g: 213, b: 179}), // Vibrant Light Orange + colord({r: 198, g: 198, b: 255}), // Vibrant Lavender + colord({r: 255, g: 255, b: 186}), // Vibrant Light Yellow + colord({r: 186, g: 255, b: 201}), // Vibrant Seafoam Green + colord({r: 255, g: 186, b: 255}), // Vibrant Light Magenta + colord({r: 210, g: 255, b: 210}), // Vibrant Pale Green + colord({r: 255, g: 202, b: 202}), // Vibrant Salmon Pink + colord({r: 206, g: 206, b: 255}), // Vibrant Periwinkle + colord({r: 255, g: 234, b: 186}), // Vibrant Cream + colord({r: 186, g: 255, b: 255}), // Vibrant Light Cyan + colord({r: 238, g: 210, b: 255}), // Vibrant Lilac + colord({r: 206, g: 255, b: 238}), // Vibrant Pale Turquoise + colord({r: 255, g: 209, b: 186}), // Vibrant Peach + colord({r: 186, g: 216, b: 255}), // Vibrant Baby Blue + colord({r: 246, g: 255, b: 186}), // Vibrant Pale Yellow + colord({r: 220, g: 186, b: 255}), // Vibrant Light Violet + colord({r: 255, g: 186, b: 213}), // Vibrant Rose + colord({r: 186, g: 255, b: 226}), // Vibrant Honeydew + colord({r: 206, g: 236, b: 255}), // Vibrant Sky Blue + colord({r: 255, g: 232, b: 206}), // Vibrant Wheat + colord({r: 206, g: 255, b: 255}), // Vibrant Pale Cyan + colord({r: 255, g: 216, b: 216}), // Vibrant Misty Rose + colord({r: 216, g: 216, b: 255}), // Vibrant Pale Lavender + colord({r: 255, g: 250, b: 205}), // Vibrant Pale Goldenrod + colord({r: 216, g: 255, b: 216}), // Vibrant Pale Mint + colord({r: 255, g: 216, b: 255}), // Vibrant Pale Plum + colord({r: 220, g: 255, b: 220}), // Vibrant Mint Cream + colord({r: 255, g: 220, b: 220}), // Vibrant Pale Pink + colord({r: 220, g: 220, b: 255}), // Vibrant Pale Blue + colord({r: 255, g: 255, b: 220}), // Vibrant Light Goldenrod + colord({r: 220, g: 255, b: 255}), // Vibrant Light Azure + colord({r: 255, g: 220, b: 255}), // Vibrant Pale Magenta + colord({r: 230, g: 255, b: 230}), // Vibrant Honeydew + colord({r: 255, g: 230, b: 230}), // Vibrant Lavender Blush + colord({r: 230, g: 230, b: 255}), // Vibrant Ghost White + colord({r: 255, g: 239, b: 219}), // Vibrant Seashell + colord({r: 219, g: 255, b: 239}), // Vibrant Mint Cream + colord({r: 239, g: 219, b: 255}), // Vibrant Pale Lavender + colord({r: 255, g: 250, b: 230}), // Vibrant Floral White + colord({r: 230, g: 255, b: 250}), // Vibrant Azure Mist + colord({r: 250, g: 230, b: 255}), // Vibrant Pale Purple + colord({r: 250, g: 255, b: 230}), // Vibrant Ivory + colord({r: 230, g: 250, b: 255}) // Vibrant Alice Blue + ]; + playerInfoColor(id: PlayerID): Colord { + return colord({r: 0, g: 0, b: 0}) + } + + territoryColor(id: PlayerID): Colord { + return this.territoryColors[id % this.territoryColors.length] + } + + borderColor(id: PlayerID): Colord { + const tc = this.territoryColor(id).rgba; + return colord({ + r: Math.max(tc.r - 20, 0), + g: Math.max(tc.g - 20, 0), + b: Math.max(tc.b - 20, 0) + }) + } + + terrainColor(tile: TerrainType): Colord { + if (tile == TerrainTypes.Land) { + return this.land; + } + return this.water; + } + + backgroundColor(): Colord { + return this.background; + } + + font(): string { + return "Arial"; + } +} \ No newline at end of file diff --git a/src/core/execution/Executor.ts b/src/core/execution/Executor.ts index f4d8f5b72..959e125dc 100644 --- a/src/core/execution/Executor.ts +++ b/src/core/execution/Executor.ts @@ -5,11 +5,12 @@ import {AttackExecution} from "./AttackExecution"; import {SpawnExecution} from "./SpawnExecution"; import {BotSpawner} from "./BotSpawner"; import {BoatAttackExecution} from "./BoatAttackExecution"; +import {PlayerConfig} from "../configuration/Config"; export class Executor { - constructor(private gs: Game) { + constructor(private gs: Game, private playerConfig: PlayerConfig) { } @@ -32,6 +33,7 @@ export class Executor { new SpawnExecution( new PlayerInfo(intent.name, intent.isBot), new Cell(intent.x, intent.y), + this.playerConfig ) ) } else if (intent.type == "boat") { diff --git a/src/core/execution/PlayerExecution.ts b/src/core/execution/PlayerExecution.ts index 6d1738b82..cd1c19ed0 100644 --- a/src/core/execution/PlayerExecution.ts +++ b/src/core/execution/PlayerExecution.ts @@ -1,10 +1,11 @@ +import {PlayerConfig} from "../configuration/Config" import {Execution, MutableGame, MutablePlayer, PlayerID} from "../Game" export class PlayerExecution implements Execution { private player: MutablePlayer - constructor(private playerID: PlayerID) { + constructor(private playerID: PlayerID, private playerConfig: PlayerConfig) { } init(gs: MutableGame, ticks: number) { @@ -12,15 +13,7 @@ export class PlayerExecution implements Execution { } tick(ticks: number) { - let toAdd = Math.sqrt(this.player.numTilesOwned() * this.player.troops()) / 5 - - const max = Math.sqrt(this.player.numTilesOwned()) * 100 + 1000 - const ratio = 1 - this.player.troops() / max - toAdd *= ratio * ratio * ratio - this.player.addTroops( - Math.max(2, toAdd) - ); - this.player.setTroops(Math.min(this.player.troops(), max)) + this.player.setTroops(this.playerConfig.troopAdditionRate(this.player)) } owner(): MutablePlayer { diff --git a/src/core/execution/SpawnExecution.ts b/src/core/execution/SpawnExecution.ts index 4f7a52859..1f5f325f0 100644 --- a/src/core/execution/SpawnExecution.ts +++ b/src/core/execution/SpawnExecution.ts @@ -1,3 +1,4 @@ +import {PlayerConfig} from "../configuration/Config" import {Cell, Execution, MutableGame, MutablePlayer, PlayerInfo} from "../Game" import {BotExecution} from "./BotExecution" import {PlayerExecution} from "./PlayerExecution" @@ -11,6 +12,7 @@ export class SpawnExecution implements Execution { constructor( private playerInfo: PlayerInfo, private cell: Cell, + private playerConfig: PlayerConfig ) { } @@ -22,12 +24,12 @@ export class SpawnExecution implements Execution { if (!this.isActive()) { return } - const player = this.gs.addPlayer(this.playerInfo, 1000) + const player = this.gs.addPlayer(this.playerInfo, this.playerConfig.startTroops(this.playerInfo)) getSpawnCells(this.gs, this.cell).forEach(c => { console.log('conquering cell') player.conquer(this.gs.tile(c)) }) - this.gs.addExecution(new PlayerExecution(player.id())) + this.gs.addExecution(new PlayerExecution(player.id(), this.playerConfig)) if (player.info().isBot) { this.gs.addExecution(new BotExecution(player)) } diff --git a/src/server/GameManager.ts b/src/server/GameManager.ts index 15b5aa918..3be081a3d 100644 --- a/src/server/GameManager.ts +++ b/src/server/GameManager.ts @@ -2,8 +2,9 @@ import {GameID, LobbyID} from "../core/Game"; import {Client} from "./Client"; import {Lobby} from "./Lobby"; import {GameServer} from "./GameServer"; -import {defaultSettings, Settings} from "../core/Settings"; +import {Config} from "../core/configuration/Config"; import {generateUniqueID} from "../core/Util"; +import {defaultConfig} from "../core/configuration/DefaultConfig"; export class GameManager { @@ -13,7 +14,7 @@ export class GameManager { private games: Map = new Map() - constructor(private settings: Settings) { } + constructor(private settings: Config) { } public hasLobby(lobbyID: LobbyID): boolean { @@ -41,7 +42,7 @@ export class GameManager { } startGame(lobby: Lobby) { - const gs = new GameServer(generateUniqueID(), lobby.clients, defaultSettings) + const gs = new GameServer(generateUniqueID(), lobby.clients, defaultConfig) this.games.set(gs.id, gs) gs.start() } diff --git a/src/server/GameServer.ts b/src/server/GameServer.ts index a14cb99da..a1ff20b84 100644 --- a/src/server/GameServer.ts +++ b/src/server/GameServer.ts @@ -1,7 +1,7 @@ import {EventBus} from "../core/EventBus"; import {ClientID, GameID} from "../core/Game"; import {ClientMessage, ClientMessageSchema, Intent, ServerStartGameMessage, ServerStartGameMessageSchema, ServerTurnMessageSchema, Turn} from "../core/Schemas"; -import {Settings} from "../core/Settings"; +import {Config} from "../core/configuration/Config"; import {Ticker, TickEvent} from "../core/Ticker"; import {Client} from "./Client"; @@ -13,7 +13,7 @@ export class GameServer { constructor( public readonly id: GameID, private clients: Map, - private settings: Settings, + private settings: Config, ) { } diff --git a/src/server/Server.ts b/src/server/Server.ts index e0817be1b..161cf37e0 100644 --- a/src/server/Server.ts +++ b/src/server/Server.ts @@ -7,7 +7,7 @@ import {GameManager} from './GameManager'; import {Client} from './Client'; import {ClientMessage, ClientMessageSchema} from '../core/Schemas'; import {Lobby} from './Lobby'; -import {defaultSettings} from '../core/Settings'; +import {defaultConfig} from '../core/configuration/DefaultConfig'; @@ -23,7 +23,7 @@ const wss = new WebSocketServer({server}); app.use(express.static(path.join(__dirname, '../../out'))); app.use(express.json()) -const gm = new GameManager(defaultSettings) +const gm = new GameManager(defaultConfig) // New GET endpoint to list lobbies app.get('/lobbies', (req, res) => {