Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,8 @@
"warships": "Warships",
"health": "Health",
"attitude": "Attitude",
"levels": "Levels"
"levels": "Levels",
"estimate": "(estimate)"
},
"events_display": {
"retreating": "retreating",
Expand Down
49 changes: 49 additions & 0 deletions src/client/graphics/layers/PlayerInfoOverlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,12 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
this.game.myPlayer()?.isFriendly(unit.owner())) ??
false;

// Calculate trade ship gold if applicable
let tradeShipGold: bigint | null = null;
if (unit.type() === UnitType.TradeShip) {
tradeShipGold = this.calculateTradeShipGold(unit);
}

return html`
<div class="p-2">
<div class="font-bold mb-1 ${isAlly ? "text-green-500" : "text-white"}">
Expand All @@ -422,11 +428,54 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
</div>
`
: ""}
${tradeShipGold !== null
? html`
<div class="flex gap-2 text-sm opacity-80 mt-1" translate="no">
<img
src=${goldCoinIcon}
alt=${translateText("player_info_overlay.gold")}
width="15"
height="15"
style="vertical-align: middle;"
/>
<span class="text-yellow-400 font-bold">
${renderNumber(tradeShipGold)}
</span>
</div>
`
: ""}
${unit.type() === UnitType.TransportShip && unit.troops() > 0
? html`
<div class="flex gap-2 text-sm opacity-80 mt-1" translate="no">
${translateText("player_info_overlay.troops")}:
<span class="ml-auto mr-0 font-bold">
${renderTroops(unit.troops())}
</span>
</div>
`
: ""}
</div>
</div>
`;
}

private calculateTradeShipGold(unit: UnitView): bigint | null {
const distanceTraveled = unit.distanceTraveled();
if (distanceTraveled === undefined) {
return null;
}

// Show gold from myPlayer's perspective - how much they would get
const myPlayer = this.game.myPlayer();
if (!myPlayer) {
return null;
}

const numPorts = myPlayer.totalUnitLevels(UnitType.Port);

return this.game.config().tradeShipGold(distanceTraveled, numPorts);
}

render() {
if (!this._isActive) {
return html``;
Expand Down
8 changes: 5 additions & 3 deletions src/core/execution/TradeShipExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export class TradeShipExecution implements Execution {
private tradeShip: Unit | undefined;
private wasCaptured = false;
private pathFinder: PathFinder;
private tilesTraveled = 0;

constructor(
private origOwner: Player,
Expand All @@ -44,6 +43,7 @@ export class TradeShipExecution implements Execution {
}
this.tradeShip = this.origOwner.buildUnit(UnitType.TradeShip, spawn, {
targetUnit: this._dstPort,
sourceUnit: this.srcPort,
lastSetSafeFromPirates: ticks,
});
this.mg.stats().boatSendTrade(this.origOwner, this._dstPort.owner());
Expand Down Expand Up @@ -115,7 +115,9 @@ export class TradeShipExecution implements Execution {
this.tradeShip.setSafeFromPirates();
}
this.tradeShip.move(result.node);
this.tilesTraveled++;
this.tradeShip.setDistanceTraveled(
this.tradeShip.distanceTraveled() + 1,
);
break;
case PathFindResultType.Completed:
this.complete();
Expand All @@ -136,7 +138,7 @@ export class TradeShipExecution implements Execution {
const gold = this.mg
.config()
.tradeShipGold(
this.tilesTraveled,
this.tradeShip!.distanceTraveled(),
this.tradeShip!.owner().unitCount(UnitType.Port),
);

Expand Down
5 changes: 5 additions & 0 deletions src/core/game/Game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,9 @@ export interface UnitParamsMap {

[UnitType.TradeShip]: {
targetUnit: Unit;
sourceUnit: Unit;
lastSetSafeFromPirates?: number;
distanceTraveled?: number;
};
Comment on lines 254 to 259
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix type consistency between params and interface methods.

The param types don't match the interface method signatures:

  1. Line 256: sourceUnit: Unit (required) conflicts with line 499: sourceUnit(): Unit | undefined
  2. Line 258: distanceTraveled?: number (optional) conflicts with line 500: distanceTraveled(): number (non-optional)

Either:

  • Make sourceUnit optional in params: sourceUnit?: Unit, OR make the interface return non-optional: sourceUnit(): Unit
  • Make distanceTraveled required in params: distanceTraveled: number, OR make the interface return optional: distanceTraveled(): number | undefined

Based on the context that TradeShips are created with a source Port and track distance as they travel, the recommended fix is:

  [UnitType.TradeShip]: {
    targetUnit: Unit;
-   sourceUnit: Unit;
+   sourceUnit?: Unit;
    lastSetSafeFromPirates?: number;
    distanceTraveled?: number;
  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[UnitType.TradeShip]: {
targetUnit: Unit;
sourceUnit: Unit;
lastSetSafeFromPirates?: number;
distanceTraveled?: number;
};
[UnitType.TradeShip]: {
targetUnit: Unit;
sourceUnit?: Unit;
lastSetSafeFromPirates?: number;
distanceTraveled?: number;
};
🤖 Prompt for AI Agents
In src/core/game/Game.ts around lines 254 to 259, the TradeShip param types are
inconsistent with the interface methods: make sourceUnit optional and
distanceTraveled required to match the method signatures; change the param
declaration to use sourceUnit?: Unit and distanceTraveled: number so
sourceUnit() can still return Unit | undefined while distanceTraveled()
continues to return a non-optional number.


[UnitType.Train]: {
Expand Down Expand Up @@ -495,6 +497,9 @@ export interface Unit {
// Trade Ships
setSafeFromPirates(): void; // Only for trade ships
isSafeFromPirates(): boolean; // Only for trade ships
sourceUnit(): Unit | undefined; // Only for trade ships
distanceTraveled(): number; // Only for trade ships
setDistanceTraveled(distance: number): void; // Only for trade ships

// Construction
constructionType(): UnitType | null;
Expand Down
2 changes: 2 additions & 0 deletions src/core/game/GameUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ export interface UnitUpdate {
targetable: boolean;
markedForDeletion: number | false;
targetUnitId?: number; // Only for trade ships
sourceUnitId?: number; // Only for trade ships
distanceTraveled?: number; // Only for trade ships
targetTile?: TileRef; // Only for nukes
health?: number;
constructionType?: UnitType;
Expand Down
6 changes: 6 additions & 0 deletions src/core/game/GameView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ export class UnitView {
targetUnitId(): number | undefined {
return this.data.targetUnitId;
}
sourceUnitId(): number | undefined {
return this.data.sourceUnitId;
}
distanceTraveled(): number | undefined {
return this.data.distanceTraveled;
}
targetTile(): TileRef | undefined {
return this.data.targetTile;
}
Expand Down
24 changes: 24 additions & 0 deletions src/core/game/UnitImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export class UnitImpl implements Unit {
private _reachedTarget = false;
private _wasDestroyedByEnemy: boolean = false;
private _lastSetSafeFromPirates: number; // Only for trade ships
private _sourceUnit: Unit | undefined; // Only for trade ships
private _distanceTraveled: number = 0; // Only for trade ships
private _constructionType: UnitType | undefined;
private _lastOwner: PlayerImpl | null = null;
private _troops: number;
Expand Down Expand Up @@ -60,6 +62,10 @@ export class UnitImpl implements Unit {
"lastSetSafeFromPirates" in params
? (params.lastSetSafeFromPirates ?? 0)
: 0;
this._sourceUnit =
"sourceUnit" in params ? (params.sourceUnit ?? undefined) : undefined;
this._distanceTraveled =
"distanceTraveled" in params ? (params.distanceTraveled ?? 0) : 0;
this._patrolTile =
"patrolTile" in params ? (params.patrolTile ?? undefined) : undefined;
this._targetUnit =
Expand Down Expand Up @@ -134,6 +140,9 @@ export class UnitImpl implements Unit {
health: this.hasHealth() ? Number(this._health) : undefined,
constructionType: this._constructionType,
targetUnitId: this._targetUnit?.id() ?? undefined,
sourceUnitId: this._sourceUnit?.id() ?? undefined,
distanceTraveled:
this._type === UnitType.TradeShip ? this._distanceTraveled : undefined,
targetTile: this.targetTile() ?? undefined,
missileTimerQueue: this._missileTimerQueue,
level: this.level(),
Expand Down Expand Up @@ -412,6 +421,21 @@ export class UnitImpl implements Unit {
);
}

sourceUnit(): Unit | undefined {
return this._sourceUnit;
}

distanceTraveled(): number {
return this._distanceTraveled;
}

setDistanceTraveled(distance: number): void {
if (this._distanceTraveled !== distance) {
this._distanceTraveled = distance;
this.mg.addUpdate(this.toUpdate());
}
}

level(): number {
return this._level;
}
Expand Down
8 changes: 8 additions & 0 deletions tests/Warship.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,13 @@ describe("Warship", () => {
),
);

const srcPort = player2.buildUnit(UnitType.Port, game.ref(coastX, 7), {});
const tradeShip = player2.buildUnit(
UnitType.TradeShip,
game.ref(coastX + 1, 7),
{
targetUnit: player2.buildUnit(UnitType.Port, game.ref(coastX, 10), {}),
sourceUnit: srcPort,
},
);

Expand All @@ -104,11 +106,13 @@ describe("Warship", () => {
),
);

const srcPort = player2.buildUnit(UnitType.Port, game.ref(coastX, 12), {});
const tradeShip = player2.buildUnit(
UnitType.TradeShip,
game.ref(coastX + 1, 11),
{
targetUnit: player1.buildUnit(UnitType.Port, game.ref(coastX, 11), {}),
sourceUnit: srcPort,
},
);

Expand All @@ -134,11 +138,13 @@ describe("Warship", () => {
);
game.addExecution(new WarshipExecution(warship));

const srcPort = player2.buildUnit(UnitType.Port, game.ref(coastX, 7), {});
const tradeShip = player2.buildUnit(
UnitType.TradeShip,
game.ref(coastX + 1, 10),
{
targetUnit: player2.buildUnit(UnitType.Port, game.ref(coastX, 10), {}),
sourceUnit: srcPort,
},
);

Expand Down Expand Up @@ -186,11 +192,13 @@ describe("Warship", () => {
);
game.addExecution(new WarshipExecution(warship));

const srcPort = player2.buildUnit(UnitType.Port, game.ref(coastX, 12), {});
const tradeShip = player2.buildUnit(
UnitType.TradeShip,
game.ref(coastX + 1, 15),
{
targetUnit: player2.buildUnit(UnitType.Port, game.ref(coastX, 10), {}),
sourceUnit: srcPort,
},
);

Expand Down
5 changes: 5 additions & 0 deletions tests/core/executions/TradeShipExecution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,17 @@ describe("TradeShipExecution", () => {
isActive: jest.fn(() => true),
} as any;

let distanceTraveledValue = 0;
tradeShip = {
isActive: jest.fn(() => true),
owner: jest.fn(() => origOwner),
move: jest.fn(),
setTargetUnit: jest.fn(),
setSafeFromPirates: jest.fn(),
setDistanceTraveled: jest.fn((value: number) => {
distanceTraveledValue = value;
}),
distanceTraveled: jest.fn(() => distanceTraveledValue),
delete: jest.fn(),
tile: jest.fn(() => 2001),
} as any;
Expand Down
Loading