Skip to content

2661 PR 1/3 Warship Retreat Core, Blue UI Signal, and Transport-First Target Priority#3498

Open
Zixer1 wants to merge 6 commits intoopenfrontio:mainfrom
Zixer1:split/2661-300-v2-pr1
Open

2661 PR 1/3 Warship Retreat Core, Blue UI Signal, and Transport-First Target Priority#3498
Zixer1 wants to merge 6 commits intoopenfrontio:mainfrom
Zixer1:split/2661-300-v2-pr1

Conversation

@Zixer1
Copy link
Copy Markdown

@Zixer1 Zixer1 commented Mar 23, 2026

Part of #2661 (split into 3 PRs so they are not too large..)

Description:

Part 1/3 of #2661.

This PR adds warship retreat basics, a blue retreating UI state, and updates target priority.

Added:

  • Retreat state handling
  • Blue visual for retreating warships
  • Target priority: transport > warship > trade
  • Tests for retreat and target priority

Example video:
https://youtu.be/2hE2qeOeY48
Ship retreating:
image
Ship healing:
image
Back to being deployed:
image

Please complete the following:

  • I have added screenshots for all UI updates
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory
  • I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced

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

zixer._

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 23, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 23, 2026

Walkthrough

Adds warship repair-and-retreat behavior and persistent retreat state: warships heal and auto-retreat to nearest friendly port when pre-heal health falls below a new configurable threshold; rendering and targeting order updated; config, unit API, execution logic, view, and tests adjusted.

Changes

Cohort / File(s) Summary
Configuration
src/core/configuration/Config.ts, src/core/configuration/DefaultConfig.ts
Added warshipRetreatHealthThreshold(): number to config interface and default implementation (returns 750).
Warship execution
src/core/execution/WarshipExecution.ts
Added persistent retreat state and helpers: health snapshot/healing, shouldStartRepairRetreat(), startRepairRetreat(), handleRepairRetreat(), cancelRepairRetreat(), findNearestPort(), isFullyHealed(); reordered targeting priority to prefer TransportShip.
Unit model & game API
src/core/game/Game.ts, src/core/game/UnitImpl.ts
Added setRetreating(retreating: boolean) to Unit API and implemented it; UnitImpl.modifyHealth now always enqueues updates; orderBoatRetreat() delegates to new setter.
View & rendering
src/core/game/GameView.ts, src/client/graphics/layers/UnitLayer.ts
UnitView.retreating() now permits TransportShip or Warship; warship rendering uses early-return: retreating warships drawn cyan, non-retreating colored by target state.
Tests
tests/Warship.test.ts
Added tests: transport-target priority and retreat-to-port behavior (checks retreating state and approach toward port when health below threshold).

Sequence Diagram

sequenceDiagram
    actor GameLoop as Game Loop
    participant WExec as WarshipExecution
    participant Finder as PortFinder
    participant Path as Pathfinder
    participant Unit as Unit

    GameLoop->>WExec: tick()
    Note over WExec: snapshot healthBeforeHeal\nhealWarship()
    WExec->>WExec: shouldStartRepairRetreat()? (pre-heal < threshold, has port)
    alt start retreat
        WExec->>Finder: findNearestPort()
        Finder-->>WExec: port tile (or none)
        WExec->>Unit: setRetreating(true)
        WExec->>Path: request path to port
        Path-->>WExec: path / status
        WExec->>WExec: handleRepairRetreat() (move toward port)
        alt reached and fully healed
            WExec->>Unit: setRetreating(false)
            WExec->>WExec: cancelRepairRetreat()
        end
    else normal combat flow
        WExec->>WExec: patrol()
        WExec->>WExec: acquire target (TransportShip > Warship > TradeShip)
        WExec->>Unit: shootTarget() / engage
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

⚓ Warship turns its bow toward home,
Cyan beacon lights the foam,
Hull heals slow while engines hum,
Targets wait — the port will come,
Home and dawn restore the roam.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: warship retreat core, blue UI signal for retreating units, and transport-first target priority are all clearly present in the changeset.
Description check ✅ Passed The description directly explains the changes made in the PR, including retreat state handling, blue visual for retreating warships, target priority updates, and added tests—all of which match the actual code changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/core/execution/WarshipExecution.ts (3)

114-131: Redundant port check.

Lines 125-127 check unitCount(Port) === 0 and return false. Lines 129-130 check ports.length > 0 and return that. If the first check passes (ports exist), the second check will always be true.

♻️ Suggested simplification
   private shouldStartRepairRetreat(
     healthBeforeHealing = this.warship.health(),
   ): boolean {
     if (this.retreatingForRepair) {
       return false;
     }
     if (
       healthBeforeHealing >= this.mg.config().warshipRetreatHealthThreshold()
     ) {
       return false;
     }
-    if (this.warship.owner().unitCount(UnitType.Port) === 0) {
-      return false;
-    }
-    // Only retreat if there's a friendly port
     const ports = this.warship.owner().units(UnitType.Port);
     return ports.length > 0;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/execution/WarshipExecution.ts` around lines 114 - 131, The method
shouldStartRepairRetreat contains a redundant port existence check: remove the
earlier unitCount( UnitType.Port ) === 0 check and only use the ports array
check returned from this.warship.owner().units(UnitType.Port); keep the initial
early-return checks for this.retreatingForRepair and the health threshold
(this.mg.config().warshipRetreatHealthThreshold()), then compute const ports =
this.warship.owner().units(UnitType.Port) and return ports.length > 0 as the
final decision; this simplifies logic and avoids duplicate queries to the owner.

481-481: Minor: Trailing newline after closing brace.

The pipeline reports Prettier formatting issues. Run npx prettier --write . to fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/execution/WarshipExecution.ts` at line 481, Remove the trailing
blank line after the final closing brace in WarshipExecution (class/file ending)
and reformat the file with Prettier; run npx prettier --write . or apply
Prettier rules to src/core/execution/WarshipExecution.ts so the extraneous
newline is removed and formatting passes.

245-259: Remove unused method or call it in handleRepairRetreat to refresh the retreat port.

The refreshRetreatPortTile() method is never called. Consider integrating it into handleRepairRetreat() around line 215, where retreatPortTile is undefined. Instead of returning false when the port is undefined, call refreshRetreatPortTile() to find a new nearest port and continue the retreat.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/execution/WarshipExecution.ts` around lines 245 - 259, The method
refreshRetreatPortTile() is never invoked; update handleRepairRetreat() so when
retreatPortTile is undefined it calls refreshRetreatPortTile() (which uses
findNearestPort() and updates this.retreatPortTile) instead of immediately
returning false; if refreshRetreatPortTile() still returns false then return
false, otherwise proceed with the existing retreat logic using the newly set
this.retreatPortTile.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/Warship.test.ts`:
- Around line 285-286: The test references a non-existent config property
warshipPortHealingBonus causing TS2339; either add warshipPortHealingBonus():
number to the Config interface and implement it in DefaultConfig (returning the
current default 1) so calls like game.config().warshipPortHealingBonus()
compile, or remove the test line setting warshipPortHealingBonus and keep the
existing fixed heal behavior in WarshipExecution.healWarship(); update the
Config/DefaultConfig definitions if you choose the first option and ensure
WarshipExecution.healWarship() reads the new config method.
- Around line 203-224: The test "Warship prioritizes transport ships over
warships" fails because WarshipExecution needs init time; either create a port
for player1 before building the warship (mirror the "Warship captures trade if
player has port" setup) so targeting initializes in one tick, or leave no port
and advance multiple ticks (e.g., call game.executeNextTick() in a loop like the
other no-port test) to allow WarshipExecution to pick its target; update the
test to use one of these approaches around WarshipExecution and executeNextTick
so warship.targetUnit() becomes a TransportShip.

---

Nitpick comments:
In `@src/core/execution/WarshipExecution.ts`:
- Around line 114-131: The method shouldStartRepairRetreat contains a redundant
port existence check: remove the earlier unitCount( UnitType.Port ) === 0 check
and only use the ports array check returned from
this.warship.owner().units(UnitType.Port); keep the initial early-return checks
for this.retreatingForRepair and the health threshold
(this.mg.config().warshipRetreatHealthThreshold()), then compute const ports =
this.warship.owner().units(UnitType.Port) and return ports.length > 0 as the
final decision; this simplifies logic and avoids duplicate queries to the owner.
- Line 481: Remove the trailing blank line after the final closing brace in
WarshipExecution (class/file ending) and reformat the file with Prettier; run
npx prettier --write . or apply Prettier rules to
src/core/execution/WarshipExecution.ts so the extraneous newline is removed and
formatting passes.
- Around line 245-259: The method refreshRetreatPortTile() is never invoked;
update handleRepairRetreat() so when retreatPortTile is undefined it calls
refreshRetreatPortTile() (which uses findNearestPort() and updates
this.retreatPortTile) instead of immediately returning false; if
refreshRetreatPortTile() still returns false then return false, otherwise
proceed with the existing retreat logic using the newly set
this.retreatPortTile.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6e780270-d739-4b02-9d97-3d38bb6d0619

📥 Commits

Reviewing files that changed from the base of the PR and between 5279312 and fb2fac2.

📒 Files selected for processing (8)
  • src/client/graphics/layers/UnitLayer.ts
  • src/core/configuration/Config.ts
  • src/core/configuration/DefaultConfig.ts
  • src/core/execution/WarshipExecution.ts
  • src/core/game/Game.ts
  • src/core/game/GameView.ts
  • src/core/game/UnitImpl.ts
  • tests/Warship.test.ts

@github-project-automation github-project-automation bot moved this from Triage to Development in OpenFront Release Management Mar 23, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/core/execution/WarshipExecution.ts (1)

114-131: Redundant port existence checks.

Line 125 already returns false when unitCount(UnitType.Port) === 0. After that guard, lines 129-130 fetch the same ports and check ports.length > 0, which is guaranteed to be true at that point.

♻️ Simplify by removing redundant check
   private shouldStartRepairRetreat(
     healthBeforeHealing = this.warship.health(),
   ): boolean {
     if (this.retreatingForRepair) {
       return false;
     }
     if (
       healthBeforeHealing >= this.mg.config().warshipRetreatHealthThreshold()
     ) {
       return false;
     }
-    if (this.warship.owner().unitCount(UnitType.Port) === 0) {
-      return false;
-    }
-    // Only retreat if there's a friendly port
-    const ports = this.warship.owner().units(UnitType.Port);
-    return ports.length > 0;
+    // Only retreat if there's a friendly port
+    return this.warship.owner().unitCount(UnitType.Port) > 0;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/execution/WarshipExecution.ts` around lines 114 - 131, The method
shouldStartRepairRetreat currently checks for port existence twice
(this.warship.owner().unitCount(UnitType.Port) === 0 and then
this.warship.owner().units(UnitType.Port) with a length check). Replace the
duplicated checks with a single consistent check: call
this.warship.owner().units(UnitType.Port) once, store the result (e.g., ports),
return false if ports.length === 0, otherwise continue/return true; remove the
unitCount(...) guard to avoid the redundant call. Ensure changes are made inside
shouldStartRepairRetreat and reference UnitType.Port, owner().units, and
owner().unitCount accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/core/execution/WarshipExecution.ts`:
- Around line 415-417: The isDocked() method in the WarshipExecution class is
unused and always returns false; remove the isDocked() method from
WarshipExecution unless it is required by an interface or superclass contract—if
it's required, implement it correctly to reflect actual docked state (e.g.,
consult this.dockingStatus or relevant property) and update any interface
signature accordingly; otherwise delete the isDocked() method declaration to
eliminate dead code.
- Around line 245-259: Remove the unused private method
refreshRetreatPortTile(): boolean from the WarshipExecution class; the
retreatPortTile field is already managed elsewhere (e.g., handleRepairRetreat),
so delete the entire refreshRetreatPortTile implementation and any references
(there should be none) to refreshRetreatPortTile to eliminate dead code and keep
the class focused on the single source of truth for retreatPortTile.

---

Nitpick comments:
In `@src/core/execution/WarshipExecution.ts`:
- Around line 114-131: The method shouldStartRepairRetreat currently checks for
port existence twice (this.warship.owner().unitCount(UnitType.Port) === 0 and
then this.warship.owner().units(UnitType.Port) with a length check). Replace the
duplicated checks with a single consistent check: call
this.warship.owner().units(UnitType.Port) once, store the result (e.g., ports),
return false if ports.length === 0, otherwise continue/return true; remove the
unitCount(...) guard to avoid the redundant call. Ensure changes are made inside
shouldStartRepairRetreat and reference UnitType.Port, owner().units, and
owner().unitCount accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 79365db2-6564-454f-a711-167a75bdf777

📥 Commits

Reviewing files that changed from the base of the PR and between fb2fac2 and dd282c6.

📒 Files selected for processing (2)
  • src/core/execution/WarshipExecution.ts
  • tests/Warship.test.ts
✅ Files skipped from review due to trivial changes (1)
  • tests/Warship.test.ts

@Zixer1 Zixer1 force-pushed the split/2661-300-v2-pr1 branch from dd282c6 to e798f4b Compare March 23, 2026 23:32
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/core/execution/WarshipExecution.ts (2)

415-417: ⚠️ Potential issue | 🟡 Minor

Dead code: isDocked() always returns false and is never called.

Remove this method unless it's required by an interface.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/execution/WarshipExecution.ts` around lines 415 - 417, The
isDocked() method in WarshipExecution always returns false and is unused; either
remove the method from the WarshipExecution class or implement it correctly if
required by an interface/contract (confirm whether WarshipExecution implements
an interface or base class that declares isDocked). If it's required, replace
the stub with a proper check using the class's docking state (e.g., reference
whatever property/method tracks docking status inside WarshipExecution);
otherwise delete the isDocked() method to eliminate dead code.

245-259: ⚠️ Potential issue | 🟡 Minor

Dead code: refreshRetreatPortTile() is never called.

This method is not used anywhere. The retreatPortTile field is managed directly in startRepairRetreat() and handleRepairRetreat(). Remove it to keep the code clean.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/execution/WarshipExecution.ts` around lines 245 - 259, Remove the
dead private method refreshRetreatPortTile from the WarshipExecution class;
locate and delete the refreshRetreatPortTile() implementation and any redundant
comments referencing it, and ensure retreatPortTile continues to be managed by
startRepairRetreat() and handleRepairRetreat() without calling the removed
method; also remove any imports or references exclusively used by
refreshRetreatPortTile (e.g., local uses of UnitType.Port within that method) so
there are no unused-symbol warnings.
🧹 Nitpick comments (1)
src/core/execution/WarshipExecution.ts (1)

114-131: Redundant port count check.

Line 125-127 checks unitCount(UnitType.Port) === 0, and lines 129-130 check ports.length > 0. These are the same check. You can remove one.

♻️ Suggested simplification
   private shouldStartRepairRetreat(
     healthBeforeHealing = this.warship.health(),
   ): boolean {
     if (this.retreatingForRepair) {
       return false;
     }
     if (
       healthBeforeHealing >= this.mg.config().warshipRetreatHealthThreshold()
     ) {
       return false;
     }
-    if (this.warship.owner().unitCount(UnitType.Port) === 0) {
-      return false;
-    }
-    // Only retreat if there's a friendly port
     const ports = this.warship.owner().units(UnitType.Port);
     return ports.length > 0;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/execution/WarshipExecution.ts` around lines 114 - 131, The method
shouldStartRepairRetreat has a redundant port existence check: it calls
warship.owner().unitCount(UnitType.Port) === 0 and then later builds ports =
warship.owner().units(UnitType.Port) and checks ports.length > 0; remove one of
these redundant checks (prefer keeping the units(...) call so you can reuse the
ports array) by deleting the unitCount(...) check and relying on ports.length >
0 to determine if a friendly Port exists; keep all other guards
(retreatingForRepair and mg.config().warshipRetreatHealthThreshold()) intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/core/execution/WarshipExecution.ts`:
- Around line 212-215: When retreatPortTile is undefined while the ship is in a
retreat state, cancel the retreat so the ship doesn't get stuck: in the block
around retreatPortTile and retreatingForRepair (used by
shouldStartRepairRetreat() and handleRepairRetreat()), detect retreatPortTile
=== undefined and, if retreatingForRepair is true, reset the retreat state
(clear retreatingForRepair and any associated retreatPortTile/retreat metadata)
before returning false; update the logic in handleRepairRetreat()/where
retreatPortTile is read to perform this state cleanup so subsequent calls won't
treat the ship as still retreating.

---

Duplicate comments:
In `@src/core/execution/WarshipExecution.ts`:
- Around line 415-417: The isDocked() method in WarshipExecution always returns
false and is unused; either remove the method from the WarshipExecution class or
implement it correctly if required by an interface/contract (confirm whether
WarshipExecution implements an interface or base class that declares isDocked).
If it's required, replace the stub with a proper check using the class's docking
state (e.g., reference whatever property/method tracks docking status inside
WarshipExecution); otherwise delete the isDocked() method to eliminate dead
code.
- Around line 245-259: Remove the dead private method refreshRetreatPortTile
from the WarshipExecution class; locate and delete the refreshRetreatPortTile()
implementation and any redundant comments referencing it, and ensure
retreatPortTile continues to be managed by startRepairRetreat() and
handleRepairRetreat() without calling the removed method; also remove any
imports or references exclusively used by refreshRetreatPortTile (e.g., local
uses of UnitType.Port within that method) so there are no unused-symbol
warnings.

---

Nitpick comments:
In `@src/core/execution/WarshipExecution.ts`:
- Around line 114-131: The method shouldStartRepairRetreat has a redundant port
existence check: it calls warship.owner().unitCount(UnitType.Port) === 0 and
then later builds ports = warship.owner().units(UnitType.Port) and checks
ports.length > 0; remove one of these redundant checks (prefer keeping the
units(...) call so you can reuse the ports array) by deleting the unitCount(...)
check and relying on ports.length > 0 to determine if a friendly Port exists;
keep all other guards (retreatingForRepair and
mg.config().warshipRetreatHealthThreshold()) intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 655d11db-3898-4dc3-b856-8b24bb5a3e00

📥 Commits

Reviewing files that changed from the base of the PR and between dd282c6 and e798f4b.

📒 Files selected for processing (8)
  • src/client/graphics/layers/UnitLayer.ts
  • src/core/configuration/Config.ts
  • src/core/configuration/DefaultConfig.ts
  • src/core/execution/WarshipExecution.ts
  • src/core/game/Game.ts
  • src/core/game/GameView.ts
  • src/core/game/UnitImpl.ts
  • tests/Warship.test.ts
✅ Files skipped from review due to trivial changes (3)
  • src/core/game/Game.ts
  • src/client/graphics/layers/UnitLayer.ts
  • tests/Warship.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/core/configuration/DefaultConfig.ts
  • src/core/configuration/Config.ts
  • src/core/game/UnitImpl.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/core/execution/WarshipExecution.ts (1)

209-212: ⚠️ Potential issue | 🟡 Minor

Stuck state when retreatPortTile is undefined while retreating.

If retreatPortTile becomes undefined while retreatingForRepair is true (e.g., timing edge case), the ship gets stuck: handleRepairRetreat() returns false without clearing the retreat flag, and shouldStartRepairRetreat() also returns false (already retreating). The warship remains in retreat visual state but cannot actually retreat.

Cancel the retreat to ensure consistent state:

🛡️ Suggested fix
     const retreatPortTile = this.retreatPortTile;
     if (retreatPortTile === undefined) {
+      this.cancelRepairRetreat();
       return false;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/execution/WarshipExecution.ts` around lines 209 - 212, If
retreatPortTile is undefined during a repair retreat, clear the retreating state
so the ship doesn't get stuck: inside the logic around retreatPortTile (used by
handleRepairRetreat()), detect the undefined case and set the retreat flag
(retreatingForRepair) back to false and invoke any existing cancel/cleanup paths
(e.g., call or emulate cancelRepairRetreat()/clearRetreatVisualState() if
present) so shouldStartRepairRetreat() no longer thinks the unit is retreating;
update handleRepairRetreat() to perform this cleanup when retreatPortTile ===
undefined and ensure any related state/reset logic is centralized so visuals and
flags remain consistent.
🧹 Nitpick comments (1)
src/core/execution/WarshipExecution.ts (1)

163-174: Fallback port selection may cause repeated pathfinding failures.

The fallback loop ignores water component connectivity. If the warship cannot reach any port (all in different water bodies), this returns an unreachable port. Then pathfinding fails with NOT_FOUND, which calls findNearestPort() again, selecting the same unreachable port—creating an infinite retry cycle.

Consider returning undefined in the fallback case to trigger cancelRepairRetreat() instead:

♻️ Suggested change
    // Fallback if component filtering leaves no options
-   bestDistance = Infinity;
-   for (const port of ports) {
-     const portTile = port.tile();
-     const distance = this.mg.euclideanDistSquared(warshipTile, portTile);
-     if (distance < bestDistance) {
-       bestDistance = distance;
-       bestTile = portTile;
-     }
-   }
-
-   return bestTile;
+   // No reachable port in same water component - cancel retreat
+   return undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/execution/WarshipExecution.ts` around lines 163 - 174, The fallback
loop in findNearestPort (WarshipExecution) selects the closest port by distance
without checking water-component connectivity, which can return an unreachable
port and cause repeated NOT_FOUND retries; update the fallback to only consider
ports in the same water component as the warship (or detect reachability) and if
none exist return undefined instead of bestTile so the caller
(cancelRepairRetreat()) can abort; locate the loop that iterates over ports
(uses port.tile(), this.mg.euclideanDistSquared, bestDistance/bestTile) and
change its logic to skip ports not in the warship's water component (or add a
connectivity check) and return undefined when no reachable port was found.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/core/execution/WarshipExecution.ts`:
- Around line 209-212: If retreatPortTile is undefined during a repair retreat,
clear the retreating state so the ship doesn't get stuck: inside the logic
around retreatPortTile (used by handleRepairRetreat()), detect the undefined
case and set the retreat flag (retreatingForRepair) back to false and invoke any
existing cancel/cleanup paths (e.g., call or emulate
cancelRepairRetreat()/clearRetreatVisualState() if present) so
shouldStartRepairRetreat() no longer thinks the unit is retreating; update
handleRepairRetreat() to perform this cleanup when retreatPortTile === undefined
and ensure any related state/reset logic is centralized so visuals and flags
remain consistent.

---

Nitpick comments:
In `@src/core/execution/WarshipExecution.ts`:
- Around line 163-174: The fallback loop in findNearestPort (WarshipExecution)
selects the closest port by distance without checking water-component
connectivity, which can return an unreachable port and cause repeated NOT_FOUND
retries; update the fallback to only consider ports in the same water component
as the warship (or detect reachability) and if none exist return undefined
instead of bestTile so the caller (cancelRepairRetreat()) can abort; locate the
loop that iterates over ports (uses port.tile(), this.mg.euclideanDistSquared,
bestDistance/bestTile) and change its logic to skip ports not in the warship's
water component (or add a connectivity check) and return undefined when no
reachable port was found.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 18e218d9-65c8-4989-bcd0-7edba0cff014

📥 Commits

Reviewing files that changed from the base of the PR and between e798f4b and 9eedc3f.

📒 Files selected for processing (1)
  • src/core/execution/WarshipExecution.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Development

Development

Successfully merging this pull request may close these issues.

2 participants