Remove workers & troop ratio bar, only have troops (#1676)

## Description:

The troop/worker ratio bar is almost never changed. so remove it and the
entire concept of workers. Now there is just troops.

Now players get a consistent 1k/s gold.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I have read and accepted the CLA agreement (only required once).

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
This commit is contained in:
evanpelle
2025-08-01 16:06:59 -07:00
committed by GitHub
parent cba4baccbd
commit 3b8a36166a
22 changed files with 57 additions and 325 deletions
-4
View File
@@ -51,7 +51,6 @@
"ui_control_desc": "The control panel contains the following elements:",
"ui_pop": "Pop - The amount of units you have, your max population and the rate at which you gain them.",
"ui_gold": "Gold - The amount of gold you have and the rate at which you gain it.",
"ui_troops_workers": "Troops and Workers - The amount of allocated troops and workers. Troops are used to attack or defend against attacks. Workers are used to generate gold. You can adjust the number of troops and workers using the slider.",
"ui_attack_ratio": "Attack ratio - The amount of troops that will be used when you attack. You can adjust the attack ratio using the slider. Having more attacking troops than defending troops will make you lose fewer troops in the attack, while having less will increase the damage dealt to your attacking troops. The effect doesn't go beyond ratios of 2:1.",
"ui_events": "Event panel",
"ui_events_desc": "The Event panel displays the latest events, requests and Quick Chat messages. Some examples are:",
@@ -289,7 +288,6 @@
"right_click_opens_menu": "Right click opens menu",
"attack_ratio_label": "⚔️ Attack Ratio",
"attack_ratio_desc": "What percentage of your troops to send in an attack (1100%)",
"troop_ratio_label": "🪖🛠️ Troops and Workers Ratio",
"troop_ratio_desc": "Adjust the balance between troops (for combat) and workers (for gold production) (1100%)",
"territory_patterns_label": "🏳️ Territory Patterns",
"territory_patterns_desc": "Choose whether to display territory pattern designs in game",
@@ -504,10 +502,8 @@
"default": "Default"
},
"control_panel": {
"pop": "Pop",
"gold": "Gold",
"troops": "Troops",
"workers": "Workers",
"attack_ratio": "Attack Ratio"
},
"player_panel": {
-4
View File
@@ -166,11 +166,7 @@ export class HelpModal extends LitElement {
<div>
<p class="mb-4">${translateText("help_modal.ui_control_desc")}</p>
<ul>
<li class="mb-4">${translateText("help_modal.ui_pop")}</li>
<li class="mb-4">${translateText("help_modal.ui_gold")}</li>
<li class="mb-4">
${translateText("help_modal.ui_troops_workers")}
</li>
<li class="mb-4">
${translateText("help_modal.ui_attack_ratio")}
</li>
-5
View File
@@ -97,11 +97,6 @@ export class LocalServer {
return;
}
if (this.paused) {
if (clientMsg.intent.type === "troop_ratio") {
// Store troop change events because otherwise they are
// not registered when game is paused.
this.intents.push(clientMsg.intent);
}
return;
}
this.intents.push(clientMsg.intent);
-15
View File
@@ -141,10 +141,6 @@ export class CancelBoatIntentEvent implements GameEvent {
constructor(public readonly unitID: number) {}
}
export class SendSetTargetTroopRatioEvent implements GameEvent {
constructor(public readonly ratio: number) {}
}
export class SendWinnerEvent implements GameEvent {
constructor(
public readonly winner: Winner,
@@ -227,9 +223,6 @@ export class Transport {
this.eventBus.on(SendEmbargoIntentEvent, (e) =>
this.onSendEmbargoIntent(e),
);
this.eventBus.on(SendSetTargetTroopRatioEvent, (e) =>
this.onSendSetTargetTroopRatioEvent(e),
);
this.eventBus.on(BuildUnitIntentEvent, (e) => this.onBuildUnitIntent(e));
this.eventBus.on(PauseGameEvent, (e) => this.onPauseGameEvent(e));
@@ -532,14 +525,6 @@ export class Transport {
});
}
private onSendSetTargetTroopRatioEvent(event: SendSetTargetTroopRatioEvent) {
this.sendIntent({
type: "troop_ratio",
clientID: this.lobbyConfig.clientID,
ratio: event.ratio,
});
}
private onBuildUnitIntent(event: BuildUnitIntentEvent) {
this.sendIntent({
type: "build_unit",
-11
View File
@@ -342,17 +342,6 @@ export class UserSettingModal extends LitElement {
@change=${this.sliderAttackRatio}
></setting-slider>
<!-- 🪖🛠️ Troop Ratio -->
<setting-slider
label="${translateText("user_setting.troop_ratio_label")}"
description="${translateText("user_setting.troop_ratio_desc")}"
min="1"
max="100"
.value=${Number(localStorage.getItem("settings.troopRatio") ?? "0.95") *
100}
@change=${this.sliderTroopRatio}
></setting-slider>
${this.showEasterEggSettings
? html`
<setting-slider
+18 -105
View File
@@ -6,7 +6,6 @@ import { Gold } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
import { ClientID } from "../../../core/Schemas";
import { AttackRatioEvent } from "../../InputHandler";
import { SendSetTargetTroopRatioEvent } from "../../Transport";
import { renderNumber, renderTroops } from "../../Utils";
import { UIState } from "../UIState";
import { Layer } from "./Layer";
@@ -22,54 +21,29 @@ export class ControlPanel extends LitElement implements Layer {
private attackRatio: number = 0.2;
@state()
private targetTroopRatio = 0.95;
private _maxTroops: number;
@state()
private currentTroopRatio = 0.95;
@state()
private _population: number;
@state()
private _maxPopulation: number;
@state()
private popRate: number;
private troopRate: number;
@state()
private _troops: number;
@state()
private _workers: number;
@state()
private _isVisible = false;
@state()
private _manpower: number = 0;
@state()
private _gold: Gold;
@state()
private _goldPerSecond: Gold;
private _troopRateIsIncreasing: boolean = true;
private _popRateIsIncreasing: boolean = true;
private _lastPopulationIncreaseRate: number;
private init_: boolean = false;
private _lastTroopIncreaseRate: number;
init() {
this.attackRatio = Number(
localStorage.getItem("settings.attackRatio") ?? "0.2",
);
this.targetTroopRatio = Number(
localStorage.getItem("settings.troopRatio") ?? "0.95",
);
this.init_ = true;
this.uiState.attackRatio = this.attackRatio;
this.currentTroopRatio = this.targetTroopRatio;
this.eventBus.on(AttackRatioEvent, (event) => {
let newAttackRatio =
(parseInt(
@@ -97,13 +71,6 @@ export class ControlPanel extends LitElement implements Layer {
}
tick() {
if (this.init_) {
this.eventBus.emit(
new SendSetTargetTroopRatioEvent(this.targetTroopRatio),
);
this.init_ = false;
}
if (!this._isVisible && !this.game.inSpawnPhase()) {
this.setVisibile(true);
}
@@ -115,28 +82,24 @@ export class ControlPanel extends LitElement implements Layer {
}
if (this.game.ticks() % 5 === 0) {
this.updatePopulationIncrease();
this.updateTroopIncrease();
}
this._population = player.population();
this._maxPopulation = this.game.config().maxPopulation(player);
this._troops = player.troops();
this._maxTroops = this.game.config().maxTroops(player);
this._gold = player.gold();
this._troops = player.troops();
this._workers = player.workers();
this.popRate = this.game.config().populationIncreaseRate(player) * 10;
this._goldPerSecond = this.game.config().goldAdditionRate(player) * 10n;
this.currentTroopRatio = player.troops() / player.population();
this.troopRate = this.game.config().troopIncreaseRate(player) * 10;
this.requestUpdate();
}
private updatePopulationIncrease() {
private updateTroopIncrease() {
const player = this.game?.myPlayer();
if (player === null) return;
const popIncreaseRate = this.game.config().populationIncreaseRate(player);
this._popRateIsIncreasing =
popIncreaseRate >= this._lastPopulationIncreaseRate;
this._lastPopulationIncreaseRate = popIncreaseRate;
const troopIncreaseRate = this.game.config().troopIncreaseRate(player);
this._troopRateIsIncreasing =
troopIncreaseRate >= this._lastTroopIncreaseRate;
this._lastTroopIncreaseRate = troopIncreaseRate;
}
onAttackRatioChange(newRatio: number) {
@@ -156,19 +119,6 @@ export class ControlPanel extends LitElement implements Layer {
this.requestUpdate();
}
targetTroops(): number {
return this._manpower * this.targetTroopRatio;
}
onTroopChange(newRatio: number) {
this.eventBus.emit(new SendSetTargetTroopRatioEvent(newRatio));
}
delta(): number {
const d = this._population - this.targetTroops();
return d;
}
render() {
return html`
<style>
@@ -219,17 +169,16 @@ export class ControlPanel extends LitElement implements Layer {
<div class="block bg-black/30 text-white mb-4 p-2 rounded">
<div class="flex justify-between mb-1">
<span class="font-bold"
>${translateText("control_panel.pop")}:</span
>${translateText("control_panel.troops")}:</span
>
<span translate="no"
>${renderTroops(this._population)} /
${renderTroops(this._maxPopulation)}
>${renderTroops(this._troops)} / ${renderTroops(this._maxTroops)}
<span
class="${this._popRateIsIncreasing
class="${this._troopRateIsIncreasing
? "text-green-500"
: "text-yellow-500"}"
translate="no"
>(+${renderTroops(this.popRate)})</span
>(+${renderTroops(this.troopRate)})</span
></span
>
</div>
@@ -237,43 +186,7 @@ export class ControlPanel extends LitElement implements Layer {
<span class="font-bold"
>${translateText("control_panel.gold")}:</span
>
<span translate="no"
>${renderNumber(this._gold)}
(+${renderNumber(this._goldPerSecond)})</span
>
</div>
</div>
<div class="relative mb-4 sm:mb-4">
<label class="block text-white mb-1" translate="no"
>${translateText("control_panel.troops")}:
<span translate="no">${renderTroops(this._troops)}</span> |
${translateText("control_panel.workers")}:
<span translate="no">${renderTroops(this._workers)}</span></label
>
<div class="relative h-8">
<!-- Background track -->
<div
class="absolute left-0 right-0 top-3 h-2 bg-white/20 rounded"
></div>
<!-- Fill track -->
<div
class="absolute left-0 top-3 h-2 bg-blue-500/60 rounded transition-all duration-300"
style="width: ${this.currentTroopRatio * 100}%"
></div>
<!-- Range input - exactly overlaying the visual elements -->
<input
type="range"
min="1"
max="100"
.value=${(this.targetTroopRatio * 100).toString()}
@input=${(e: Event) => {
this.targetTroopRatio =
parseInt((e.target as HTMLInputElement).value) / 100;
this.onTroopChange(this.targetTroopRatio);
}}
class="absolute left-0 right-0 top-2 m-0 h-4 cursor-pointer targetTroopRatio"
/>
<span translate="no">${renderNumber(this._gold)}</span>
</div>
</div>
-10
View File
@@ -35,7 +35,6 @@ export type Intent =
| EmojiIntent
| DonateGoldIntent
| DonateTroopsIntent
| TargetTroopRatioIntent
| BuildUnitIntent
| EmbargoIntent
| QuickChatIntent
@@ -59,9 +58,6 @@ export type EmojiIntent = z.infer<typeof EmojiIntentSchema>;
export type DonateGoldIntent = z.infer<typeof DonateGoldIntentSchema>;
export type DonateTroopsIntent = z.infer<typeof DonateTroopIntentSchema>;
export type EmbargoIntent = z.infer<typeof EmbargoIntentSchema>;
export type TargetTroopRatioIntent = z.infer<
typeof TargetTroopRatioIntentSchema
>;
export type BuildUnitIntent = z.infer<typeof BuildUnitIntentSchema>;
export type UpgradeStructureIntent = z.infer<
typeof UpgradeStructureIntentSchema
@@ -314,11 +310,6 @@ export const DonateTroopIntentSchema = BaseIntentSchema.extend({
troops: z.number().nullable(),
});
export const TargetTroopRatioIntentSchema = BaseIntentSchema.extend({
type: z.literal("troop_ratio"),
ratio: z.number().min(0).max(1),
});
export const BuildUnitIntentSchema = BaseIntentSchema.extend({
type: z.literal("build_unit"),
unit: z.enum(UnitType),
@@ -378,7 +369,6 @@ const IntentSchema = z.discriminatedUnion("type", [
EmojiIntentSchema,
DonateGoldIntentSchema,
DonateTroopIntentSchema,
TargetTroopRatioIntentSchema,
BuildUnitIntentSchema,
UpgradeStructureIntentSchema,
EmbargoIntentSchema,
+4 -5
View File
@@ -89,9 +89,8 @@ export interface Config {
playerTeams(): TeamCountConfig;
startManpower(playerInfo: PlayerInfo): number;
populationIncreaseRate(player: Player | PlayerView): number;
troopIncreaseRate(player: Player | PlayerView): number;
goldAdditionRate(player: Player | PlayerView): Gold;
troopAdjustmentRate(player: Player): number;
attackTilesPerTick(
attckTroops: number,
attacker: Player,
@@ -114,8 +113,8 @@ export interface Config {
// When computing likelihood of trading for any given port, the X closest port
// are twice more likely to be selected. X is determined below.
proximityBonusPortsNb(totalPorts: number): number;
maxPopulation(player: Player | PlayerView): number;
cityPopulationIncrease(): number;
maxTroops(player: Player | PlayerView): number;
cityTroopIncrease(): number;
boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number;
shellLifetime(): number;
boatMaxNumber(): number;
@@ -162,7 +161,7 @@ export interface Config {
nukeType: NukeType,
humans: number,
tilesOwned: number,
maxPop: number,
maxTroops: number,
): number;
structureMinDist(): number;
isReplay(): boolean;
+21 -36
View File
@@ -273,7 +273,7 @@ export class DefaultConfig implements Config {
}
}
cityPopulationIncrease(): number {
cityTroopIncrease(): number {
return 250_000;
}
@@ -714,8 +714,8 @@ export class DefaultConfig implements Config {
return this.infiniteTroops() ? 1_000_000 : 25_000;
}
maxPopulation(player: Player | PlayerView): number {
const maxPop =
maxTroops(player: Player | PlayerView): number {
const maxTroops =
player.type() === PlayerType.Human && this.infiniteTroops()
? 1_000_000_000
: 2 * (Math.pow(player.numTilesOwned(), 0.6) * 1000 + 50000) +
@@ -723,34 +723,34 @@ export class DefaultConfig implements Config {
.units(UnitType.City)
.map((city) => city.level())
.reduce((a, b) => a + b, 0) *
this.cityPopulationIncrease();
this.cityTroopIncrease();
if (player.type() === PlayerType.Bot) {
return maxPop / 2;
return maxTroops / 2;
}
if (player.type() === PlayerType.Human) {
return maxPop;
return maxTroops;
}
switch (this._gameConfig.difficulty) {
case Difficulty.Easy:
return maxPop * 0.5;
return maxTroops * 0.5;
case Difficulty.Medium:
return maxPop * 1;
return maxTroops * 1;
case Difficulty.Hard:
return maxPop * 1.5;
return maxTroops * 1.5;
case Difficulty.Impossible:
return maxPop * 2;
return maxTroops * 2;
}
}
populationIncreaseRate(player: Player): number {
const max = this.maxPopulation(player);
troopIncreaseRate(player: Player): number {
const max = this.maxTroops(player);
let toAdd = 10 + Math.pow(player.population(), 0.73) / 4;
let toAdd = 10 + Math.pow(player.troops(), 0.73) / 4;
const ratio = 1 - player.population() / max;
const ratio = 1 - player.troops() / max;
toAdd *= ratio;
if (player.type() === PlayerType.Bot) {
@@ -774,26 +774,11 @@ export class DefaultConfig implements Config {
}
}
return Math.min(player.population() + toAdd, max) - player.population();
return Math.min(player.troops() + toAdd, max) - player.troops();
}
goldAdditionRate(player: Player): Gold {
return BigInt(Math.floor(0.045 * player.workers() ** 0.7));
}
troopAdjustmentRate(player: Player): number {
const maxDiff = this.maxPopulation(player) / 1000;
const target = player.population() * player.targetTroopRatio();
const diff = target - player.troops();
if (Math.abs(diff) < maxDiff) {
return diff;
}
const adjustment = maxDiff * Math.sign(diff);
// Can ramp down troops much faster
if (adjustment < 0) {
return adjustment * 5;
}
return adjustment;
return 100n;
}
nukeMagnitudes(unitType: UnitType): NukeMagnitude {
@@ -824,22 +809,22 @@ export class DefaultConfig implements Config {
return 80;
}
// Humans can be population, soldiers attacking, soldiers in boat etc.
// Humans can be soldiers, soldiers attacking, soldiers in boat etc.
nukeDeathFactor(
nukeType: NukeType,
humans: number,
tilesOwned: number,
maxPop: number,
maxTroops: number,
): number {
if (nukeType !== UnitType.MIRVWarhead) {
return (5 * humans) / Math.max(1, tilesOwned);
}
const targetPop = 0.03 * maxPop;
const excessPop = Math.max(0, humans - targetPop);
const targetTroops = 0.03 * maxTroops;
const excessTroops = Math.max(0, humans - targetTroops);
const scalingFactor = 500;
const steepness = 2;
const normalizedExcess = excessPop / maxPop;
const normalizedExcess = excessTroops / maxTroops;
return scalingFactor * (1 - Math.exp(-steepness * normalizedExcess));
}
-4
View File
@@ -74,10 +74,6 @@ export class DevConfig extends DefaultConfig {
// return 1
// }
// populationIncreaseRate(player: Player): number {
// return this.maxPopulation(player)
// }
// boatMaxDistance(): number {
// return 5000
// }
-1
View File
@@ -31,7 +31,6 @@ export class BotExecution implements Execution {
init(mg: Game) {
this.mg = mg;
this.bot.setTargetTroopRatio(0.7);
}
tick(ticks: number) {
+1 -1
View File
@@ -21,7 +21,7 @@ export class DonateTroopsExecution implements Execution {
this.recipient = mg.player(this.recipientID);
this.troops ??= mg.config().defaultDonationAmount(this.sender);
const maxDonation =
mg.config().maxPopulation(this.recipient) - this.recipient.population();
mg.config().maxTroops(this.recipient) - this.recipient.troops();
this.troops = Math.min(this.troops, maxDonation);
}
-3
View File
@@ -20,7 +20,6 @@ import { MoveWarshipExecution } from "./MoveWarshipExecution";
import { NoOpExecution } from "./NoOpExecution";
import { QuickChatExecution } from "./QuickChatExecution";
import { RetreatExecution } from "./RetreatExecution";
import { SetTargetTroopRatioExecution } from "./SetTargetTroopRatioExecution";
import { SpawnExecution } from "./SpawnExecution";
import { TargetPlayerExecution } from "./TargetPlayerExecution";
import { TransportShipExecution } from "./TransportShipExecution";
@@ -98,8 +97,6 @@ export class Executor {
);
case "donate_gold":
return new DonateGoldExecution(player, intent.recipient, intent.gold);
case "troop_ratio":
return new SetTargetTroopRatioExecution(player, intent.ratio);
case "embargo":
return new EmbargoExecution(player, intent.targetID, intent.action);
case "build_unit":
-7
View File
@@ -153,13 +153,6 @@ export class FakeHumanExecution implements Execution {
return;
}
if (
this.player.troops() > 100_000 &&
this.player.targetTroopRatio() > 0.7
) {
this.player.setTargetTroopRatio(0.7);
}
this.updateRelationsFromEmbargos();
this.behavior.handleAllianceRequests();
this.handleUnits();
+5 -15
View File
@@ -203,8 +203,8 @@ export class NukeExecution implements Execution {
const toDestroy = this.tilesToDestroy();
this.maybeBreakAlliances(toDestroy);
const maxPop = this.target().isPlayer()
? this.mg.config().maxPopulation(this.target() as Player)
const maxTroops = this.target().isPlayer()
? this.mg.config().maxTroops(this.target() as Player)
: 1;
for (const tile of toDestroy) {
@@ -218,17 +218,7 @@ export class NukeExecution implements Execution {
this.nukeType,
owner.troops(),
owner.numTilesOwned(),
maxPop,
),
);
owner.removeWorkers(
this.mg
.config()
.nukeDeathFactor(
this.nukeType,
owner.workers(),
owner.numTilesOwned(),
maxPop,
maxTroops,
),
);
owner.outgoingAttacks().forEach((attack) => {
@@ -239,7 +229,7 @@ export class NukeExecution implements Execution {
this.nukeType,
attack.troops(),
owner.numTilesOwned(),
maxPop,
maxTroops,
) ?? 0;
attack.setTroops(attack.troops() - deaths);
});
@@ -251,7 +241,7 @@ export class NukeExecution implements Execution {
this.nukeType,
attack.troops(),
owner.numTilesOwned(),
maxPop,
maxTroops,
) ?? 0;
attack.setTroops(attack.troops() - deaths);
});
+2 -7
View File
@@ -56,19 +56,14 @@ export class PlayerExecution implements Execution {
return;
}
const popInc = this.config.populationIncreaseRate(this.player);
this.player.addWorkers(popInc * (1 - this.player.targetTroopRatio()));
this.player.addTroops(popInc * this.player.targetTroopRatio());
const troopInc = this.config.troopIncreaseRate(this.player);
this.player.addTroops(troopInc);
const goldFromWorkers = this.config.goldAdditionRate(this.player);
this.player.addGold(goldFromWorkers);
// Record stats
this.mg.stats().goldWork(this.player, goldFromWorkers);
const adjustRate = this.config.troopAdjustmentRate(this.player);
this.player.addTroops(adjustRate);
this.player.removeWorkers(adjustRate);
const alliances = Array.from(this.player.alliances());
for (const alliance of alliances) {
if (alliance.expiresAt() <= this.mg.ticks()) {
@@ -1,31 +0,0 @@
import { Execution, Game, Player } from "../game/Game";
export class SetTargetTroopRatioExecution implements Execution {
private active = true;
constructor(
private player: Player,
private targetTroopsRatio: number,
) {}
init(mg: Game, ticks: number): void {}
tick(ticks: number): void {
if (this.targetTroopsRatio < 0 || this.targetTroopsRatio > 1) {
console.warn(
`target troop ratio of ${this.targetTroopsRatio} for player ${this.player} invalid`,
);
} else {
this.player.setTargetTroopRatio(this.targetTroopsRatio);
}
this.active = false;
}
isActive(): boolean {
return this.active;
}
activeDuringSpawnPhase(): boolean {
return false;
}
}
+3 -4
View File
@@ -59,8 +59,8 @@ export class BotBehavior {
}
private hasSufficientTroops(): boolean {
const maxPop = this.game.config().maxPopulation(this.player);
const ratio = this.player.population() / maxPop;
const maxTroops = this.game.config().maxTroops(this.player);
const ratio = this.player.troops() / maxTroops;
return ratio >= this.triggerRatio;
}
@@ -208,8 +208,7 @@ export class BotBehavior {
sendAttack(target: Player | TerraNullius) {
if (target.isPlayer() && this.player.isOnSameTeam(target)) return;
const maxPop = this.game.config().maxPopulation(this.player);
const maxTroops = maxPop * this.player.targetTroopRatio();
const maxTroops = this.game.config().maxTroops(this.player);
const reserveRatio = target.isPlayer()
? this.reserveRatio
: this.expandRatio;
+2 -8
View File
@@ -510,17 +510,11 @@ export interface Player {
conquer(tile: TileRef): void;
relinquish(tile: TileRef): void;
// Resources & Population
// Resources & Troops
gold(): Gold;
population(): number;
workers(): number;
troops(): number;
targetTroopRatio(): number;
addGold(toAdd: Gold, tile?: TileRef): void;
removeGold(toRemove: Gold): Gold;
addWorkers(toAdd: number): void;
removeWorkers(toRemove: number): void;
setTargetTroopRatio(target: number): void;
troops(): number;
setTroops(troops: number): void;
addTroops(troops: number): void;
removeTroops(troops: number): number;
-3
View File
@@ -154,10 +154,7 @@ export interface PlayerUpdate {
isDisconnected: boolean;
tilesOwned: number;
gold: Gold;
population: number;
workers: number;
troops: number;
targetTroopRatio: number;
allies: number[];
embargoes: Set<PlayerID>;
isTraitor: boolean;
-9
View File
@@ -291,15 +291,6 @@ export class PlayerView {
gold(): Gold {
return this.data.gold;
}
population(): number {
return this.data.population;
}
workers(): number {
return this.data.workers;
}
targetTroopRatio(): number {
return this.data.targetTroopRatio;
}
troops(): number {
return this.data.troops;
+1 -37
View File
@@ -4,7 +4,6 @@ import { ClientID } from "../Schemas";
import {
assertNever,
distSortUnit,
maxInt,
minInt,
simpleHash,
toInt,
@@ -72,10 +71,6 @@ export class PlayerImpl implements Player {
private _gold: bigint;
private _troops: bigint;
private _workers: bigint;
// 0 to 100
private _targetTroopRatio: bigint;
markedTraitorTick = -1;
@@ -115,9 +110,7 @@ export class PlayerImpl implements Player {
private readonly _team: Team | null,
) {
this._name = sanitizeUsername(playerInfo.name);
this._targetTroopRatio = 95n;
this._troops = toInt(startTroops);
this._workers = 0n;
this._gold = 0n;
this._displayName = this._name; // processName(this._name)
this._pseudo_random = new PseudoRandom(simpleHash(this.playerInfo.id));
@@ -144,10 +137,7 @@ export class PlayerImpl implements Player {
isDisconnected: this.isDisconnected(),
tilesOwned: this.numTilesOwned(),
gold: this._gold,
population: this.population(),
workers: this.workers(),
troops: this.troops(),
targetTroopRatio: this.targetTroopRatio(),
allies: this.alliances().map((a) => a.other(this).smallID()),
embargoes: new Set([...this.embargoes.keys()].map((p) => p.toString())),
isTraitor: this.isTraitor(),
@@ -731,32 +721,6 @@ export class PlayerImpl implements Player {
return actualRemoved;
}
population(): number {
return Number(this._troops + this._workers);
}
workers(): number {
return Math.max(1, Number(this._workers));
}
addWorkers(toAdd: number): void {
this._workers += toInt(toAdd);
}
removeWorkers(toRemove: number): void {
this._workers = maxInt(1n, this._workers - toInt(toRemove));
}
targetTroopRatio(): number {
return Number(this._targetTroopRatio) / 100;
}
setTargetTroopRatio(target: number): void {
if (target < 0 || target > 1) {
throw new Error(
`invalid targetTroopRatio ${target} set on player ${PlayerImpl}`,
);
}
this._targetTroopRatio = toInt(target * 100);
}
troops(): number {
return Number(this._troops);
}
@@ -1051,7 +1015,7 @@ export class PlayerImpl implements Player {
hash(): number {
return (
simpleHash(this.id()) * (this.population() + this.numTilesOwned()) +
simpleHash(this.id()) * (this.troops() + this.numTilesOwned()) +
this._units.reduce((acc, unit) => acc + unit.hash(), 0)
);
}