Evan 2789db8b96 Optimize core simulation hot paths (no behavior change) (#4230)
## Summary

Pure performance optimizations to the attack/conquer/cluster hot paths
in `src/core`, driven by the full-game perf harness from #4228. **No
behavior change**: the final game-state hash is identical before/after
on every config tested — world quick run (2 different seeds),
giantworldmap, and the default 1800-tick run.

### Changes

- **Flat-arithmetic neighbor iteration**: `forEachNeighbor` /
`forEachNeighborWithDiag` / `isBorder` / `isOceanShore` are now
implemented inside `GameMapImpl` using raw `ref±1` / `ref±width` index
math, skipping the per-neighbor `ref()` coordinate validation
(`Number.isInteger` etc.). `GameImpl` and `GameView` delegate.
- **New `neighbors4(ref, out)`**: zero-allocation, callback-free
neighbor query for hot loops (W, E, N, S — same order as
`forEachNeighbor`).
- **`AttackExecution`**: the per-tile closures in `tick()` /
`addNeighbors()` are replaced with reusable neighbor buffers, a cached
`GameMap` reference, and integer `smallID()` owner comparisons instead
of owner-object lookups.
- **`GameImpl`**: the per-conquer `updateBorders` closure is hoisted to
a method with a reusable buffer; `removeInactiveExecutions` compacts the
executions array in place instead of allocating a new ~4200-element
array every tick.
- **`PlayerExecution`**: `surroundedBySamePlayer` / `isSurrounded` /
`getCapturingPlayer` de-closured (`neighbors4` + integer compares;
neighbor visit order preserved, so `getCapturingPlayer`'s
Map-insertion-order tie-breaking is unchanged); flood-fill visit closure
hoisted out of the while loop.
- **`FlatBinaryHeap.dequeue`**: returns the tile directly instead of
allocating a `[tile, priority]` tuple per dequeued tile (AttackExecution
is the only caller).

### Performance (`npm run perf:game`, same machine, before → after)

| run | mean tick | ticks/sec | max tick |
|---|---|---|---|
| default (world, 400 bots, 1800 ticks) | 9.04 → **7.98 ms** | 111 →
**125** | 31.7 → 35.7 ms |
| giantworldmap, 600 ticks | 22.5 → **17.4 ms** | 44 → **58** | 52.8 →
**36.2 ms** |

The giantworldmap tail improvement (max tick −31%) is the most relevant
for the 100 ms tick budget.

### Determinism verification

Identical `Final hash` before and after on all configs:

| config | hash |
|---|---|
| `--map world --ticks 200 --bots 100` | `5455008589403520` |
| same + `--seed second-seed-check` | `5580840142777488` |
| `--map giantworldmap --ticks 600` | `37373734953428430` |
| default run | `26773450321979388` |

### Tests

- New `tests/NeighborIteration.test.ts` pins the exact neighbor
iteration orders (W,E,N,S cardinal; dx-major diagonal — conquest order
and RNG consumption depend on them) and conquer/border-tile invariants
checked mid-battle.
- New `tests/FlatBinaryHeap.test.ts` covers heap ordering, clear, and
growth.
- Full suite passes (122 files / 1386 tests + server tests); lint and
prettier clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 19:58:42 -07:00

OpenFrontIO Logo

OpenFront.io is an online real-time strategy game focused on territorial control and alliance building. Players compete to expand their territory, build structures, and form strategic alliances in various maps based on real-world geography.

This is a fork/rewrite of WarFront.io. Credit to https://github.com/WarFrontIO.

CI Crowdin CLA assistant License: AGPL v3 Assets: CC BY-SA 4.0

License

OpenFront source code is licensed under the GNU Affero General Public License v3.0

Current copyright notices appear in:

  • Footer: "© OpenFront and Contributors"
  • Loading screen: "© OpenFront and Contributors"

Modified versions must preserve these notices in reasonably visible locations.

See the LICENSE for complete requirements.

For asset licensing, see LICENSE-ASSETS.
For license history, see LICENSING.md.

🌟 Features

  • Real-time Strategy Gameplay: Expand your territory and engage in strategic battles
  • Alliance System: Form alliances with other players for mutual defense
  • Multiple Maps: Play across various geographical regions including Europe, Asia, Africa, and more
  • Resource Management: Balance your expansion with defensive capabilities
  • Cross-platform: Play in any modern web browser

📋 Prerequisites

  • npm (v10.9.2 or higher)
  • A modern web browser (Chrome, Firefox, Edge, etc.)

🚀 Installation

  1. Clone the repository

    git clone https://github.com/openfrontio/OpenFrontIO.git
    cd OpenFrontIO
    
  2. Install dependencies

    npm run inst
    

    Do NOT use npm install nor npm i but instead use our npm run inst. It runs the safer npm ci --ignore-scripts to install dependencies exactly according to the versions in package-lock.json and doesn't run scripts. This can prevent being hit by a supply chain attack.

🎮 Running the Game

Development Mode

Run both the client and server in development mode with live reloading:

npm run dev

This will:

  • Start the webpack dev server for the client
  • Launch the game server with development settings
  • Open the game in your default browser (to disable this behavior, set SKIP_BROWSER_OPEN=true in your environment)

Client Only

To run just the client with hot reloading:

npm run start:client

Server Only

To run just the server with development settings:

npm run start:server-dev

Connecting to staging or production backends

Sometimes it's useful to connect to production servers when replaying a game, testing user profiles, purchases, or login flow.

To replay a production game, make sure you're on the same commit that the game you want to replay was executed on, you can find the gitCommit value via https://api.openfront.io/game/[gameId]. Unfinished games cannot be replayed on localhost.

To connect to staging api servers:

npm run dev:staging

To connect to production api servers:

npm run dev:prod

🛠️ Development Tools

  • Format code:

    npm run format
    
  • Lint code:

    npm run lint
    
  • Lint and fix code:

    npm run lint:fix
    
  • Testing

    npm test
    

🏗️ Project Structure

  • /src/client - Frontend game client
  • /src/core - Deterministic game simulation
  • /src/server - Backend game server
  • /resources - Static assets (images, maps, etc.)

🤝 Contributing

Contributions and translations are welcome! See CONTRIBUTING.md for the workflow, the approved-issue process, project governance, and translation info.

S
Description
Languages
TypeScript 91.3%
GLSL 2.6%
JavaScript 1.9%
HTML 1.7%
CSS 1%
Other 1.5%