diff --git a/src/core/StatsSchemas.ts b/src/core/StatsSchemas.ts index 043b5dfd2..a911d9459 100644 --- a/src/core/StatsSchemas.ts +++ b/src/core/StatsSchemas.ts @@ -99,6 +99,8 @@ export const PlayerStatsSchema = z .object({ attacks: AtLeastOneNumberSchema.optional(), betrayals: BigIntStringSchema.optional(), + killedAt: BigIntStringSchema.optional(), + conquests: BigIntStringSchema.optional(), boats: z.partialRecord(BoatUnitSchema, AtLeastOneNumberSchema).optional(), bombs: z.partialRecord(BombUnitSchema, AtLeastOneNumberSchema).optional(), gold: AtLeastOneNumberSchema.optional(), diff --git a/src/core/execution/PlayerExecution.ts b/src/core/execution/PlayerExecution.ts index db021bd7f..bb348cdc5 100644 --- a/src/core/execution/PlayerExecution.ts +++ b/src/core/execution/PlayerExecution.ts @@ -55,6 +55,7 @@ export class PlayerExecution implements Execution { } }); this.active = false; + this.mg.stats().playerKilled(this.player, ticks); return; } diff --git a/src/core/game/Stats.ts b/src/core/game/Stats.ts index d328c6d71..06c41af9c 100644 --- a/src/core/game/Stats.ts +++ b/src/core/game/Stats.ts @@ -93,4 +93,7 @@ export interface Stats { // Player loses a unit of type unitLose(player: Player, type: OtherUnitType): void; + + // player was killed (0 tiles) + playerKilled(player: Player, tick: number): void; } diff --git a/src/core/game/StatsImpl.ts b/src/core/game/StatsImpl.ts index bd77d1dff..e3e750897 100644 --- a/src/core/game/StatsImpl.ts +++ b/src/core/game/StatsImpl.ts @@ -133,6 +133,22 @@ export class StatsImpl implements Stats { p.units[type][index] += _bigint(value); } + private _addConquest(player: Player) { + const p = this._makePlayerStats(player); + if (p === undefined) return; + if (p.conquests === undefined) { + p.conquests = _bigint(1); + } else { + p.conquests += _bigint(1); + } + } + + private _addPlayerKilled(player: Player, tick: number) { + const p = this._makePlayerStats(player); + if (p === undefined) return; + p.killedAt = _bigint(tick); + } + attack( player: Player, target: Player | TerraNullius, @@ -225,6 +241,7 @@ export class StatsImpl implements Stats { goldWar(player: Player, captured: Player, gold: BigIntLike): void { this._addGold(player, GOLD_INDEX_WAR, gold); + this._addConquest(player); } unitBuild(player: Player, type: OtherUnitType): void { @@ -246,4 +263,8 @@ export class StatsImpl implements Stats { unitLose(player: Player, type: OtherUnitType): void { this._addOtherUnit(player, type, OTHER_INDEX_LOST, 1); } + + playerKilled(player: Player, tick: number): void { + this._addPlayerKilled(player, tick); + } } diff --git a/tests/Stats.test.ts b/tests/Stats.test.ts index c53804b4f..1b654210b 100644 --- a/tests/Stats.test.ts +++ b/tests/Stats.test.ts @@ -160,7 +160,17 @@ describe("Stats", () => { test("goldWar", () => { stats.goldWar(player1, player2, 1); expect(stats.stats()).toStrictEqual({ - client1: { gold: [0n, 1n] }, + client1: { + gold: [0n, 1n], + conquests: 1n, + }, + }); + stats.goldWar(player1, player2, 1); + expect(stats.stats()).toStrictEqual({ + client1: { + gold: [0n, 2n], + conquests: 2n, + }, }); }); @@ -211,6 +221,19 @@ describe("Stats", () => { }); }); + test("playerKilled", () => { + stats.playerKilled(player1, 10); + stats.playerKilled(player2, 40); + expect(stats.stats()).toStrictEqual({ + client1: { + killedAt: 10n, + }, + client2: { + killedAt: 40n, + }, + }); + }); + test("stringify", () => { stats.unitLose(player1, UnitType.Port); expect(JSON.stringify(stats.stats(), replacer)).toBe(