Skip to content

Conversation

@scamiv
Copy link
Contributor

@scamiv scamiv commented Nov 12, 2025

Description:

Add visual indicators to territory borders that reflect diplomatic relationships between players, making it easier to identify relations at a glance.

Problem Statement

Currently, players must check diplomatic status through other UI elements. There's no immediate visual feedback on the map showing which borders represent embargo or friendly relationships.

Benefits

  1. Improved Gameplay Clarity: Quickly identify diplomatic relationships without opening menus
  2. Strategic Awareness: Visual feedback helps make tactical decisions about border defense

Proposed Solution

Tint territory borders based on neighbor relationships: embargo red, friendly green

Implementation Details

  • Border variants are based on this._borderColor (theme/style handling unchanged) computed in the constructor and stored in userSettings UnitView
  • Apply tinting to checkerboard for defended borders
  • borderColor() checks all neighbors to determine the worst relationship status
  • Embargos take priority.
image 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

- Pre-compute border color variants (neutral, friendly, embargo) per player
- Tint borders based on neighbor relationships (embargo → red, friendly → green)
- Apply tinting before theme checkerboard for defended borders
- Simplify border color selection logic
@scamiv scamiv requested a review from a team as a code owner November 12, 2025 21:35
@CLAassistant
Copy link

CLAassistant commented Nov 12, 2025

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 12, 2025

Walkthrough

PlayerView's border color logic now considers neighbor relationships. The changes introduce pre-computed color variants for Neutral, Friendly, and Embargo states, plus separate defended variants. The borderColor() method dynamically selects colors based on whether neighbors have embargo or friendly relations, then applies appropriate defended tinting when needed.

Changes

Cohort / File(s) Summary
Border color and tint system refactor
src/core/game/GameView.ts
Added global tint targets and border tint ratio constants. Introduced pre-computed border color variants (Neutral, Friendly, Embargo base colors and their Defended counterparts) on PlayerView. Reworked PlayerView constructor to compute and cache these color variants. Refactored borderColor() method to inspect neighbor relationships, determine embargo/friendly status, select appropriate base and defended colors, and return the correct variant based on tile light/dark pattern.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant borderColor as borderColor(tile, isDefended)
    participant neighbors as Neighbor Check
    participant colorSelect as Color Selection
    
    Caller->>borderColor: Request border color
    borderColor->>borderColor: tile === undefined?
    alt Tile Undefined
        borderColor-->>Caller: Return base border color
    else Tile Defined
        borderColor->>neighbors: Check tile neighbors
        neighbors-->>borderColor: Relations identified
        borderColor->>colorSelect: Embargo relation found?
        alt Embargo Relation
            colorSelect-->>borderColor: Use Embargo colors
        else Friendly Relation
            colorSelect-->>borderColor: Use Friendly colors
        else Neutral
            colorSelect-->>borderColor: Use Neutral colors
        end
        borderColor->>borderColor: isDefended?
        alt Not Defended
            borderColor-->>Caller: Return base color
        else Defended
            borderColor->>borderColor: Check light/dark pattern
            borderColor-->>Caller: Return appropriate defended variant
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Neighbor relationship logic: Verify the embargo/friendly priority order is correct and handles edge cases
  • Color variant pre-computation: Confirm all color variants (Neutral, Friendly, Embargo + Defended) are properly initialized
  • borderColor() method complexity: Trace through multiple conditional branches to ensure correct color selection for all tile/defense/neighbor combinations
  • Light/dark pattern application: Validate that the defended color variant selection based on tile pattern is accurate

Possibly related issues

Suggested reviewers

  • evanpelle

Poem

🎨 Colors dance where borders meet,
Friendly green and embargo heat,
Neighbors whisper, shades align,
Defended posts in tint design,
Neutral grounds now brightly greet! ✨

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding visual tinting to territory borders based on player diplomatic relationships.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The pull request description clearly relates to the changeset, detailing diplomatic relationship visual indicators for territory borders.

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
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: 0

🧹 Nitpick comments (1)
src/core/game/GameView.ts (1)

262-293: Extract duplicated tinting formula into a helper function.

The color tinting formula is duplicated for friendly (lines 262-276) and embargo (lines 279-293). Consider extracting into a helper:

function applyTint(base: Colord, target: {r: number, g: number, b: number}, ratio: number): Colord {
  const baseRgb = base.toRgb();
  return colord({
    r: Math.round(baseRgb.r * (1 - ratio) + target.r * ratio),
    g: Math.round(baseRgb.g * (1 - ratio) + target.g * ratio),
    b: Math.round(baseRgb.b * (1 - ratio) + target.b * ratio),
    a: baseRgb.a,
  });
}

Then use it:

this._borderColorFriendly = applyTint(this._borderColor, FRIENDLY_TINT_TARGET, BORDER_TINT_RATIO);
this._borderColorEmbargo = applyTint(this._borderColor, EMBARGO_TINT_TARGET, BORDER_TINT_RATIO);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0200df3 and d920bcf.

📒 Files selected for processing (1)
  • src/core/game/GameView.ts (4 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: Ble4Ch
Repo: openfrontio/OpenFrontIO PR: 1063
File: src/core/configuration/Colors.ts:114-330
Timestamp: 2025-06-06T15:36:31.739Z
Learning: In the OpenFrontIO project, color improvements are implemented incrementally. The current focus for player colors is ensuring sufficient unique color availability rather than optimizing for visual distinction or accessibility features.
📚 Learning: 2025-06-10T09:56:44.473Z
Learnt from: Ble4Ch
Repo: openfrontio/OpenFrontIO PR: 1063
File: src/core/configuration/PastelThemeDark.ts:53-53
Timestamp: 2025-06-10T09:56:44.473Z
Learning: In ColorAllocator class in src/core/configuration/Colors.ts, the correct method names are assignColor(id: string): Colord for general color assignment and assignTeamColor(team: Team): Colord for team-specific colors. There are no assignPlayerColor() or assignBotColor() methods.

Applied to files:

  • src/core/game/GameView.ts
📚 Learning: 2025-10-26T15:37:07.732Z
Learnt from: GlacialDrift
Repo: openfrontio/OpenFrontIO PR: 2298
File: src/client/graphics/layers/TerritoryLayer.ts:200-210
Timestamp: 2025-10-26T15:37:07.732Z
Learning: In GameImpl.ts lines 124-139, team assignment logic varies by number of teams: when numPlayerTeams < 8, teams are assigned ColoredTeams values (Red, Blue, Yellow, Green, Purple, Orange, Teal); when numPlayerTeams >= 8, teams are assigned generic string identifiers like "Team 1", "Team 2", etc., which are not members of ColoredTeams.

Applied to files:

  • src/core/game/GameView.ts
📚 Learning: 2025-06-06T15:36:31.739Z
Learnt from: Ble4Ch
Repo: openfrontio/OpenFrontIO PR: 1063
File: src/core/configuration/Colors.ts:114-330
Timestamp: 2025-06-06T15:36:31.739Z
Learning: In the OpenFrontIO project, color improvements are implemented incrementally. The current focus for player colors is ensuring sufficient unique color availability rather than optimizing for visual distinction or accessibility features.

Applied to files:

  • src/core/game/GameView.ts
📚 Learning: 2025-06-22T21:51:14.990Z
Learnt from: devalnor
Repo: openfrontio/OpenFrontIO PR: 1248
File: src/client/graphics/layers/TerritoryInfoLayer.ts:20-20
Timestamp: 2025-06-22T21:51:14.990Z
Learning: In TerritoryInfoLayer.ts, the highlightedTerritory field uses both null and undefined intentionally: undefined represents initial state or inactive layer (Ctrl released), while null represents active layer with no territory being highlighted at cursor position. This distinction is important for proper state change detection.

Applied to files:

  • src/core/game/GameView.ts
🧬 Code graph analysis (1)
src/core/game/GameView.ts (3)
src/core/configuration/DefaultConfig.ts (1)
  • theme (637-641)
src/core/game/GameMap.ts (3)
  • TileRef (3-3)
  • x (122-124)
  • y (126-128)
src/core/game/GameImpl.ts (2)
  • x (798-800)
  • y (801-803)
🔇 Additional comments (3)
src/core/game/GameView.ts (3)

44-46: LGTM - Clear tinting constants.

The 35% blend ratio provides visual distinction while preserving the base border color identity.


192-198: LGTM - Pre-computed variants improve performance.

Storing all color variants upfront avoids repeated computation during rendering.


323-380: LGTM - Relationship-based border tinting logic is correct.

The implementation correctly:

  • Prioritizes embargo over friendly (line 349 breaks early)
  • Checks both directions for friendly relationships (line 352) to handle non-symmetric alliances during transitions
  • Applies type narrowing safely (line 343)
  • Handles edge cases (no neighbors → neutral colors)
  • Uses standard checkerboard pattern for defended borders

@evanpelle
Copy link
Collaborator

should I review this or wait for the webgl version?

@scamiv
Copy link
Contributor Author

scamiv commented Nov 20, 2025

Depends, do you want to keep the non-webgl renderer? do we need a fallback?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants