diff --git a/src/core/Util.ts b/src/core/Util.ts index 82be316dc..7b40d0d2b 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -306,3 +306,19 @@ export function generateID(): GameID { ); return nanoid(); } + +export function toInt(num: number): bigint { + return BigInt(Math.floor(num)); +} + +export function maxInt(a: bigint, b: bigint): bigint { + return a > b ? a : b; +} + +export function minInt(a: bigint, b: bigint): bigint { + return a < b ? a : b; +} +export function withinInt(num: bigint, min: bigint, max: bigint): bigint { + const atLeastMin = maxInt(num, min); + return minInt(atLeastMin, max); +} diff --git a/src/core/execution/PlayerExecution.ts b/src/core/execution/PlayerExecution.ts index c2b3163cc..275e27d91 100644 --- a/src/core/execution/PlayerExecution.ts +++ b/src/core/execution/PlayerExecution.ts @@ -76,7 +76,7 @@ export class PlayerExecution implements Execution { } const popInc = this.config.populationIncreaseRate(this.player); - this.player.addWorkers(popInc * (1 - this.player.targetTroopRatio())); // (1 - this.player.targetTroopRatio())) + this.player.addWorkers(popInc * (1 - this.player.targetTroopRatio())); this.player.addTroops(popInc * this.player.targetTroopRatio()); this.player.addGold(this.config.goldAdditionRate(this.player)); const adjustRate = this.config.troopAdjustmentRate(this.player); diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index 0ca8e55ee..1c5801512 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -26,9 +26,12 @@ import { assertNever, closestOceanShoreFromPlayer, distSortUnit, + maxInt, + minInt, simpleHash, sourceDstOceanShore, targetTransportTile, + toInt, within, } from "../Util"; import { CellString, GameImpl } from "./GameImpl"; @@ -37,7 +40,6 @@ import { MessageType } from "./Game"; import { renderTroops } from "../../client/Utils"; import { TerraNulliusImpl } from "./TerraNulliusImpl"; import { andFN, manhattanDistFN, TileRef } from "./GameMap"; -import { Emoji } from "discord.js"; import { AttackImpl } from "./AttackImpl"; interface Target { @@ -55,10 +57,12 @@ class Donation { export class PlayerImpl implements Player { public _lastTileChange: number = 0; - private _gold: Gold; - private _troops: number; - private _workers: number; - private _targetTroopRatio: number = 1; + private _gold: bigint; + private _troops: bigint; + private _workers: bigint; + + // 0 to 100 + private _targetTroopRatio: bigint = 100n; isTraitor_ = false; @@ -88,14 +92,14 @@ export class PlayerImpl implements Player { private mg: GameImpl, private _smallID: number, private readonly playerInfo: PlayerInfo, - startPopulation: number, + startTroops: number, ) { this._flag = playerInfo.flag; this._name = playerInfo.name; - this._targetTroopRatio = 1; - this._troops = startPopulation * this._targetTroopRatio; - this._workers = startPopulation * (1 - this._targetTroopRatio); - this._gold = 0; + this._targetTroopRatio = 100n; + this._troops = toInt(startTroops); + this._workers = 0n; + this._gold = 0n; this._displayName = this._name; // processName(this._name) } @@ -117,7 +121,7 @@ export class PlayerImpl implements Player { playerType: this.type(), isAlive: this.isAlive(), tilesOwned: this.numTilesOwned(), - gold: this._gold, + gold: Number(this._gold), population: this.population(), workers: this.workers(), troops: this.troops(), @@ -234,7 +238,7 @@ export class PlayerImpl implements Player { return true as const; } setTroops(troops: number) { - this._troops = Math.floor(troops); + this._troops = toInt(troops); } conquer(tile: TileRef) { this.mg.conquer(this, tile); @@ -503,11 +507,11 @@ export class PlayerImpl implements Player { } gold(): Gold { - return this._gold; + return Number(this._gold); } addGold(toAdd: Gold): void { - this._gold += toAdd; + this._gold += toInt(toAdd); } removeGold(toRemove: Gold): void { @@ -516,24 +520,24 @@ export class PlayerImpl implements Player { `Player ${this} does not enough gold (${toRemove} vs ${this._gold}))`, ); } - this._gold -= toRemove; + this._gold -= toInt(toRemove); } population(): number { - return this._troops + this._workers; + return Number(this._troops + this._workers); } workers(): number { - return Math.max(1, this._workers); + return Math.max(1, Number(this._workers)); } addWorkers(toAdd: number): void { - this._workers += toAdd; + this._workers += toInt(toAdd); } removeWorkers(toRemove: number): void { - this._workers = Math.max(1, this._workers - toRemove); + this._workers = maxInt(1n, this._workers - toInt(toRemove)); } targetTroopRatio(): number { - return this._targetTroopRatio; + return Number(this._targetTroopRatio) / 100; } setTargetTroopRatio(target: number): void { @@ -542,11 +546,11 @@ export class PlayerImpl implements Player { `invalid targetTroopRatio ${target} set on player ${PlayerImpl}`, ); } - this._targetTroopRatio = target; + this._targetTroopRatio = toInt(target * 100); } troops(): number { - return this._troops; + return Number(this._troops); } addTroops(troops: number): void { @@ -554,15 +558,15 @@ export class PlayerImpl implements Player { this.removeTroops(-1 * troops); return; } - this._troops += Math.floor(troops); + this._troops += toInt(troops); } removeTroops(troops: number): number { if (troops <= 1) { return 0; } - const toRemove = Math.floor(Math.min(this._troops - 1, troops)); + const toRemove = minInt(this._troops, toInt(troops)); this._troops -= toRemove; - return toRemove; + return Number(toRemove); } captureUnit(unit: Unit): void { diff --git a/src/core/game/UnitImpl.ts b/src/core/game/UnitImpl.ts index 06aa50d9c..baa5f1f05 100644 --- a/src/core/game/UnitImpl.ts +++ b/src/core/game/UnitImpl.ts @@ -1,7 +1,7 @@ import { MessageType } from "./Game"; import { UnitUpdate } from "./GameUpdates"; import { GameUpdateType } from "./GameUpdates"; -import { simpleHash, within } from "../Util"; +import { simpleHash, toInt, within, withinInt } from "../Util"; import { Unit, TerraNullius, UnitType, Player, UnitInfo } from "./Game"; import { GameImpl } from "./GameImpl"; import { PlayerImpl } from "./PlayerImpl"; @@ -9,7 +9,7 @@ import { TileRef } from "./GameMap"; export class UnitImpl implements Unit { private _active = true; - private _health: number; + private _health: bigint; private _lastTile: TileRef = null; private _constructionType: UnitType = undefined; @@ -37,7 +37,7 @@ export class UnitImpl implements Unit { isActive: this._active, pos: this._tile, lastPos: this._lastTile, - health: this.hasHealth() ? this._health : undefined, + health: this.hasHealth() ? Number(this._health) : undefined, constructionType: this._constructionType, }; } @@ -65,7 +65,7 @@ export class UnitImpl implements Unit { return this._troops; } health(): number { - return this._health; + return Number(this._health); } hasHealth(): boolean { return this.info().maxHealth != undefined; @@ -94,7 +94,11 @@ export class UnitImpl implements Unit { } modifyHealth(delta: number): void { - this._health = within(this._health + delta, 0, this.info().maxHealth ?? 1); + this._health = withinInt( + this._health + toInt(delta), + 0n, + toInt(this.info().maxHealth ?? 1), + ); } delete(displayMessage: boolean = true): void {