Wave Field is a deterministic two-player strategy game played on a 7x7 board generated by the pieces themselves. Every Round Hat, Tower, Triangle Hat, and Big Hat emits an invisible wave of energy that extends across the board. Red and Blue use opposite sign orientations, and every square is the sum of all piece waves reaching it. Because the patterns alternate, either team's wave may contribute both positive and negative energy on different squares.
This repository is a live, playable application of the current rules. See RULES.md for the full rules reference. See docs/STRATEGY.md for strategy, teaching, and emergent-pattern research notes.
Win by trapping the opposing Big Hat. A Big Hat is trapped when its square is hostile territory, making the Big Hat unstable. After a move traps a Big Hat, the trapped player gets a visible rescue turn. If the rules cannot find a rescue, the status line says so instead of ending the game immediately.
Each turn ends when you move one piece. Before moving, you may tune your wave controls as much as you like. You can play by moving alone, but tuning is usually the way to escape danger, protect your Big Hat, or turn a distant part of the board.
Click a piece to see its legal destinations, or drag it across the board. Moving one piece ends the turn and relocates that piece's wave origin, so a local move can change territory far away.
The + and - controls flip the polarity of a piece type's canonical wave
pattern. Each piece type starts with one pattern: Round Hats use a checkerboard,
Towers use a paired push/pull cadence, Triangle Hats use a compass rose, and
Big Hats use a block checker. Tuning is
shared by type, so both of your Towers use the same Tower profile.
Every piece has a controllable wave pattern that contributes energy to every square. A single pattern can contain both positive and negative energy, and tuning changes which components are active or inverted. The total field is the sum of all active piece patterns from both teams.
The sign of the final total determines territory:
| Field value | Territory |
|---|---|
| Greater than zero | Red |
| Zero | Neutral |
| Less than zero | Blue |
Moving a piece changes its wave origin, so one move can reshape territory across the entire board.
Each piece type has a home-square energy parameter for its own square. The
defaults are Round Hat 0, Tower 0, Triangle Hat 0.5, and Big Hat 0. Other pieces can
still contribute to that square from afar.
Every basis wave halves once per square ring: 1, 1/2, 1/4, 1/8, and so
on. Coefficients and strengths are integers, so combined field totals are always
dyadic fractions whose denominators are powers of two. A sum may be 3/8 or
5/16, but never 1/3 or 1/5.
The wave editor also has a Grid mode for raw integer pattern values. Those
integers are still multiplied by ring decay, so a distant cell can intentionally
use a larger value such as 4 or 8 to send remote energy without disabling
decay for every pattern.
Each piece type also has friendly and hostile scale parameters. A piece's active
components first combine into positive and negative raw energy buckets for a
square. Positive energy uses the friendly scale, and negative energy uses the
hostile scale before the two buckets are added. Current defaults are Round Hat 4/1, Tower 3/1, Triangle Hat
3/0, and Big Hat 4/2 for friendly/hostile. Round Hats therefore have a first ring
of +2 on friendly cells and -1/2 on hostile cells for Red, with signs
reversed for Blue.
Each player begins with two Round Hats, two Towers, one Triangle Hat, and one Big Hat. Blue moves first.
| Piece | Wave components | Energy | Active | Home | Default (Red / Blue) | Movement |
|---|---|---|---|---|---|---|
| Round Hat | 1 | 1 | 1 | 0 | + / - |
Any distance in one direction |
| Tower | 1 | 2 | 1 | 0 | + / - |
Any distance in one direction |
| Triangle Hat | 1 | 2 | 1 | 0.5 | + / - |
Any distance in one direction, ignoring territory |
| Big Hat | 1 | 2 | 1 | 0 | + / - |
Any distance in one direction |
A direction may be horizontal, vertical, or diagonal, giving eight possible rays. Despite their familiar names, pieces do not use chess movement.
Developer mode can expand a piece type back toward the older multi-pattern debug space. In the normal ruleset, every piece type uses exactly one reversible pattern.
During a turn, a player may:
- Tune their wave components any number of times.
- Move one piece.
Moving a piece ends the turn. Tuning does not.
The dice control randomizes every piece type's tuning while keeping each type at full active strength. It counts as tuning and does not end the turn. The adjacent reset control restores the current player to the configured defaults as one undoable tuning action.
A tuning change may temporarily leave the player's Big Hat unprotected because the player can keep tuning during the turn. The turn-ending move must leave their Big Hat safe.
The controls display each component's signed field contribution:
+for a positive Red wave;-for a negative Blue wave.
Because Blue's owner sign reverses the shared coefficient, the live Blue controls display the opposite signs from Red for the same underlying profile.
Tap + or - to choose the current orientation. These controls do not mean
"Red energy" or "Blue energy" by themselves; each component is a spatial pattern
that may contain both positive and negative energy after owner sign, scale, and
territory effects are applied. If developer mode expands a piece type to
multiple patterns, activating another component at the active limit turns off
the least recently pressed component.
Tuning is shared by piece type. Both of a player's Towers always use that player's Tower settings, while the opposing player controls a separate set.
The default controls in developer mode use shared intrinsic (Red) signs and are applied to both players when the game restarts. Restart keeps the currently selected wave definitions; the developer-only "Restart and reset definitions" control restores the built-in wave definitions too.
Choose one of the eight directions and move any distance along that ray. For non-Triangle Hat pieces, every crossed square, including the destination, must be unoccupied and either friendly territory or Neutral. The first occupied or hostile square stops the ray, so pieces cannot jump or turn during a move.
- Red pieces may move through Red or Neutral territory.
- Blue pieces may move through Blue or Neutral territory.
- Triangle Hats may move through territory of either sign or Neutral.
- Pieces cannot capture by collision; friendly and opposing pieces both block.
The board distinguishes movement from turn safety:
- A white ring marks a move that can be completed.
- A yellow
Bmarks a reachable square that is blocked because ending there would leave your Big Hat unprotected. - A yellow diamond with
!marks a playable move that will cause one of your non-Big Hat pieces to be lost when the turn resolves.
A non-Big Hat piece standing on hostile territory is unstable. The player may rescue it by moving that piece to a safe square or by moving a different piece whose relocated wave makes the unstable piece's square friendly or Neutral. A newly unstable non-Big Hat piece remains on the board through its owner's next turn, including all tuning changes and the turn-ending move.
One move may rescue multiple unstable pieces if the resulting field stabilizes all of their squares. Any piece that was unstable at the start of the turn and remains on hostile territory after the move is removed.
The field is recalculated after each removal because the lost piece's wave disappears. This can trigger further removals among pieces whose rescue deadline has arrived.
Triangle Hats still ignore hostile territory while moving, but a Triangle Hat that stands on hostile territory after a turn resolves is unstable like any other non-Big Hat piece.
A Big Hat must be protected by friendly or Neutral territory at the end of every move. A player cannot complete a move that leaves their own Big Hat on hostile territory.
When a completed move places the opposing Big Hat on hostile territory, the opponent begins their turn with an unstable, trapped Big Hat. The game looks for a rescue across every valid combined tuning profile, followed by one legal move. If a rescue exists, the status line gives a concrete hint such as "tune, then move Triangle Hat to 4,5". If no rescue is found, the status line says so and leaves the trapped player in control.
While trapped, a player may resign from the unprotected-Big Hat warning instead of continuing to search for an alternate tuning and legal escape. The adjacent Hint control searches every valid combined tuning profile, applies the profile with the fewest changed component slots, and selects a piece with a legal rescuing move.
Big Hats are never captured or removed. A trapped player remains in control until they find a rescue, resign, or undo.
The opening formation is rotationally symmetric:
Blue
. . P B P . .
. . S T S . .
. . . . . . .
. . . . . . .
. . . . . . .
. . S T S . .
. . P B P . .
Red
R = Round Hat, T = Tower, A = Triangle Hat, B = Big Hat.
The demo includes an optional heuristic Red opponent, selected-piece influence borders colored by contribution, drag-to-preview field updates, live wave-pattern thumbnails, a per-square piece-type contribution overlay, an interactive CMYK energy view with isolatable Round Hat, Tower, Triangle Hat, and Big Hat channels and per-square composition ratios, legal-move indicators, blocked-Big Hat move markers, instability warnings, loss burst animations, undo and restart, continuous field-magnitude shading, a compact mobile tuning panel, and a developer mode for inspecting the raw field, piece contributions, mobility, and editable wave definitions. Developer mode also provides editable pattern slot counts, default component controls, friendly/hostile wave scales, and home-square energy. The selected control profile is applied to both players on restart. Its scrollable History Roll reconstructs moves, tuning changes, dice and hint profiles, piece losses, and turn transitions from the active undo timeline. The Pressure panel summarizes legal moves, unstable pieces, Big Hat safety, and a recent pressure trend.
The optional Red AI uses a bounded heuristic search. It evaluates many tuning and movement candidates quickly, then runs exact safety validation on a small shortlist so mobile browsers remain responsive.
The implementation is deterministic: the same position and component settings always produce the same field and legal moves.
npm install
npm run engine:build
npm run devThe development app and AI arena use the Rust rule engine through WebAssembly. Install its one-time toolchain prerequisites with:
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.126 --lockednpm run dev and npm run arena rebuild the WebAssembly module before starting
Vite. The public /arena route is static-safe for GitHub Pages; local neural
model controls live under /local-arena in development and call Python model
servers on localhost. The Rust crate lives in engine/; its native JSON-lines
binary is also a convenient boundary for scripts and future Python bindings.
During migration, the production build continues to use the TypeScript engine.
Use npm test to build Rust, run the existing TypeScript rules suite, and run
cross-language parity checks for field evaluation, movement, turn resolution,
tuning, instability, and check behavior. Use cargo test --manifest-path engine/Cargo.toml for Rust-only tests and npm run build for the production
build.
The native Rust CLI supports developer simulation modes for arena analysis and training experiments:
simulateRandomGames: random legal self-play with rich per-ply metrics.simulateRandomLeanGames: random legal self-play with terminal stats only.profileRandomGames: lean random self-play with timing for candidate generation and move application.simulateAiGames: heuristic AI self-play baseline.
Run the layered benchmark with:
npm run engine:benchUseful overrides:
npm run engine:bench -- --games 5000 --heuristic-games 50 --time-budget-ms 10Lean mode uses a training-oriented move path that skips browser-only history, status-message work, and full no-rescue trap search while preserving ordinary move consequences and cheap terminal checks.
The code in this repository is licensed under the MIT License. See LICENSE.