From 08672f68a9413dd24f24e73bfeece37934ecab04 Mon Sep 17 00:00:00 2001 From: evanpelle Date: Sun, 22 Sep 2024 19:54:12 -0700 Subject: [PATCH] alliances expire after 1000 ticks (~1.5 minutes) --- src/client/graphics/layers/EventsDisplay.ts | 29 ++++++++++++++++++--- src/core/configuration/Config.ts | 3 ++- src/core/configuration/DefaultConfig.ts | 5 +++- src/core/configuration/DevConfig.ts | 6 ++++- src/core/execution/PlayerExecution.ts | 7 +++++ src/core/game/AllianceImpl.ts | 2 +- src/core/game/Game.ts | 6 ++++- src/core/game/GameImpl.ts | 12 ++++++++- 8 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts index e6d6f84b9..a44807149 100644 --- a/src/client/graphics/layers/EventsDisplay.ts +++ b/src/client/graphics/layers/EventsDisplay.ts @@ -1,6 +1,6 @@ import {nullable} from "zod"; import {EventBus, GameEvent} from "../../../core/EventBus"; -import {AllianceRequest, AllianceRequestEvent, AllianceRequestReplyEvent, BrokeAllianceEvent, Game, PlayerID} from "../../../core/game/Game"; +import {AllianceExpiredEvent, AllianceRequest, AllianceRequestEvent, AllianceRequestReplyEvent, BrokeAllianceEvent, Game, Player, PlayerID} from "../../../core/game/Game"; import {ClientID} from "../../../core/Schemas"; import {Layer} from "./Layer"; @@ -57,6 +57,7 @@ export class EventsDisplay implements Layer { this.eventBus.on(AllianceRequestReplyEvent, a => this.onAllianceRequestReplyEvent(a)) this.eventBus.on(DisplayMessageEvent, e => this.onDisplayMessageEvent(e)) this.eventBus.on(BrokeAllianceEvent, e => this.onBrokeAllianceEvent(e)) + this.eventBus.on(AllianceExpiredEvent, e => this.onAllianceExpiredEvent(e)) this.renderTable() } @@ -148,7 +149,6 @@ export class EventsDisplay implements Layer { createdAt: this.game.ticks(), onDelete: () => this.eventBus.emit(new AllianceRequestReplyUIEvent(event.allianceRequest, false)) }); - this.renderTable() } // TODO: move this to DisplayMessageEvent @@ -167,7 +167,6 @@ export class EventsDisplay implements Layer { highlight: true, createdAt: this.game.ticks(), }); - this.renderTable() } onBrokeAllianceEvent(event: BrokeAllianceEvent) { @@ -193,8 +192,32 @@ export class EventsDisplay implements Layer { } } + onAllianceExpiredEvent(event: AllianceExpiredEvent) { + const myPlayer = this.game.playerByClientID(this.clientID) + if (myPlayer == null) { + return + } + let other: Player = null + if (event.player1 == myPlayer) { + other = event.player2 + } + if (event.player2 == myPlayer) { + other = event.player1 + } + if (other == null) { + return + } + this.addEvent({ + description: `Your alliance with ${other.name()} expired`, + type: MessageType.WARN, + highlight: true, + createdAt: this.game.ticks(), + }) + } + addEvent(event: Event): void { this.events.push(event); + this.renderTable() } removeEvent(index: number): void { diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index 6071b659e..87ba20d46 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -1,4 +1,4 @@ -import {Player, PlayerID, PlayerInfo, TerraNullius, Tile} from "../game/Game"; +import {Player, PlayerID, PlayerInfo, TerraNullius, Tick, Tile} from "../game/Game"; import {Colord, colord} from "colord"; import {devConfig} from "./DevConfig"; import {defaultConfig} from "./DefaultConfig"; @@ -47,6 +47,7 @@ export interface Config { boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number boatMaxDistance(): number boatMaxNumber(): number + allianceDuration(): Tick } export interface Theme { diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 95bbff763..c88d358b5 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -1,4 +1,4 @@ -import {Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tile} from "../game/Game"; +import {Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tick, Tile} from "../game/Game"; import {GameID} from "../Schemas"; import {simpleHash, within} from "../Util"; import {Config, Theme} from "./Config"; @@ -7,6 +7,9 @@ import {pastelTheme} from "./PastelTheme"; export class DefaultConfig implements Config { + allianceDuration(): Tick { + return 10 * 100 + } percentageTilesOwnedToWin(): number { return 95 } diff --git a/src/core/configuration/DevConfig.ts b/src/core/configuration/DevConfig.ts index 4634d8411..5de1387de 100644 --- a/src/core/configuration/DevConfig.ts +++ b/src/core/configuration/DevConfig.ts @@ -1,9 +1,10 @@ +import {Tick} from "../game/Game"; import {GameID} from "../Schemas"; import {DefaultConfig} from "./DefaultConfig"; export const devConfig = new class extends DefaultConfig { percentageTilesOwnedToWin(): number { - return 80 + return 95 } numSpawnPhaseTurns(): number { return 80 @@ -22,6 +23,9 @@ export const devConfig = new class extends DefaultConfig { return 0 } + // allianceDuration(): Tick { + // return 10 * 10 + // } numFakeHumans(gameID: GameID): number { return 0 diff --git a/src/core/execution/PlayerExecution.ts b/src/core/execution/PlayerExecution.ts index 507bab30c..6f115bb87 100644 --- a/src/core/execution/PlayerExecution.ts +++ b/src/core/execution/PlayerExecution.ts @@ -32,6 +32,13 @@ export class PlayerExecution implements Execution { } this.player.setTroops(this.config.troopAdditionRate(this.player)) + const alliances = Array.from(this.player.alliances()) + for (const alliance of alliances) { + if (this.mg.ticks() - alliance.createdAt() > this.mg.config().allianceDuration()) { + alliance.expire() + } + } + if (ticks - this.lastCalc > this.ticksPerClusterCalc) { this.lastCalc = ticks const start = performance.now() diff --git a/src/core/game/AllianceImpl.ts b/src/core/game/AllianceImpl.ts index 550afd2d1..7a941767c 100644 --- a/src/core/game/AllianceImpl.ts +++ b/src/core/game/AllianceImpl.ts @@ -23,7 +23,7 @@ export class AllianceImpl implements MutableAlliance { } expire(): void { - + this.mg.expireAlliance(this) } } \ No newline at end of file diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index b670532d9..3f4ce2dd7 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -183,7 +183,7 @@ export interface Game { executions(): ExecutionView[] terraNullius(): TerraNullius executeNextTick(): void - ticks(): number + ticks(): Tick inSpawnPhase(): boolean addExecution(...exec: Execution[]): void config(): Config @@ -220,4 +220,8 @@ export class AllianceRequestReplyEvent implements GameEvent { export class BrokeAllianceEvent implements GameEvent { constructor(public readonly traitor: Player, public readonly betrayed: Player) { } +} + +export class AllianceExpiredEvent implements GameEvent { + constructor(public readonly player1: Player, public readonly player2: Player) { } } \ No newline at end of file diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 747b364ef..da1ec07ee 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -1,7 +1,7 @@ import {info} from "console"; import {Config} from "../configuration/Config"; import {EventBus} from "../EventBus"; -import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Boat, BoatEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance} from "./Game"; +import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Boat, BoatEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent} from "./Game"; import {TerrainMap} from "./TerrainMapLoader"; import {PlayerImpl} from "./PlayerImpl"; import {TerraNulliusImpl} from "./TerraNulliusImpl"; @@ -366,6 +366,16 @@ export class GameImpl implements MutableGame { this.eventBus.emit(new BrokeAllianceEvent(breaker, other)) } + public expireAlliance(alliance: Alliance) { + const p1Set = new Set(alliance.recipient().alliances()) + const alliances = alliance.requestor().alliances().filter(a => p1Set.has(a)) + if (alliances.length != 1) { + throw new Error(`cannot expire alliance: must have exactly one alliance, have ${alliances.length}`) + } + this.alliances_ = this.alliances_.filter(a => a != alliances[0]) + this.eventBus.emit(new AllianceExpiredEvent(alliance.requestor(), alliance.recipient())) + } + displayMessage(message: string, type: MessageType, playerID: PlayerID | null): void { this.eventBus.emit(new DisplayMessageEvent(message, type, playerID)) }