# Ripple Pond — adopting Gododin in an existing game

A tiny complete Godot game that teaches one full incremental adoption: a
working GDScript game keeps its scene, its rendering, and its optimized
GDScript baseline, and moves its one substantial batch operation — the
per-frame wave-equation step over the pond grid — into a pure Odin package
behind one small native class.

The example directory **is** the adopted game. `game/` beside it is the same
game as it existed before adoption, kept runnable so every delta adoption
made is visible and diffable.

## The game

Click the water to splash it; waves reflect, interfere, and settle. In the
adopted version, keys `1` and `2` switch which arm steps the water each
frame:

- **GDScript** — the preserved baseline (`gd_ripples.gd`, byte-identical in
  `game/` and here): the same fixed-step wave equation on two packed f64
  buffers with one integer write per cell.
- **Odin (native)** — the same arithmetic in `subsystem/pond.odin`, reached
  through the scene's `RipplePond` node: one `step` call and one coarse
  `frame_bytes` call per frame, no per-cell foreign calls.

Both arms run the identical f64 expression sequence, so the water is
byte-for-byte identical — `tests/oracle.gd` proves it — and the example
makes **no performance claim**. The on-screen per-step milliseconds are a
host-local observation; measured, fair language comparisons are their own
workload (see the repository's comparison plans), not a claim this example
makes.

## Requirements

One extracted immutable Gododin SDK, the exact locked Odin compiler, and the
exact pinned Godot executable named by the SDK's `gododin.lock` — the same
prerequisites as the other examples (`examples/setup.sh` wires every example
at once, including this one). No machine-local sibling folders, no private
environment variables, no copied manifests.

## Run and test

The [five-chapter usage guide](../../docs/getting-started.md) teaches adoption,
authoring, iteration and export; [setup](../../docs/setup.md) covers installation.
This README owns the
example's controls, modes, source map and retained journey evidence.

Use [shared example setup](../README.md#one-time-setup) to connect this
configured project to its matching SDK, compiler and engine, then run:

```sh
cd examples/ripple_pond
./test.sh              # pure kernel, before/after game discipline, pipeline, oracle
./test.sh play         # public launcher, interactive windowed game
./test.sh oracle       # public launcher, headless byte/signal oracle
```

Modes are `all` (default), `subsystem`, `game`, `pipeline`, `oracle` and `play`.
The oracle requires `GODODIN_RIPPLE_ORACLE_PASS` (600 frames, six byte
checkpoints and six signal deliveries), `GODODIN_RUN_PASS` and zero Host
owners. Its exit status is the application test result; it measures no speed.

`GODODIN_PROFILE=release ./test.sh` selects a release pipeline build. Currently
`oracle` and `play` invoke public `run` without `--profile`, so those two modes
still launch **debug** even if that environment variable is set. To test/run
release, use the public [profile-aware commands](../../docs/usage/shipping-and-updating.md#choose-a-native-profile)
with this example as `project`. Do not infer the launch profile from the shell
variable; inspect `GODODIN_RUN_IDENTITY`.

To replay adoption, the guide starts from a copy of `game/`. To inspect the
change here, compare `game/main.tscn` and `game/main.gd` with the root versions:
one native `RipplePond` child and the native arm/signal wiring are added;
`project.godot` and the GDScript baseline remain byte-identical.

## File responsibilities

| File | Owns |
| --- | --- |
| `game/` | the before state — never touched by adoption, kept for the diff |
| `project.godot`, `main.tscn`, `main.gd`, `gd_ripples.gd` | the game: scene, input, HUD, rendering, GDScript baseline |
| `tests/oracle.gd` | the application test: native vs GDScript byte oracle |
| `declarations/ripple_pond.odin` | the authored class — the single source for the native surface |
| `subsystem/pond.odin` (+ `_test`) | the pure kernel and its ownership/determinism tests |
| `generated/` | the generated catalog, bridge and docs; `generate` publishes the current bundle, and its output is never hand-edited |
| `gododin.toml`, `gododin.lock` | portable intent; exact accepted identities |

## Journey record

Executed end to end on Windows x86-64 (development-host evidence under the
desktop workstream; the installed attach flow itself carries the recording
host's evidence): checkout authority over an adopted copy of `game/`,
`gododin init` reporting `mode=adopted` with the game's three files
byte-identical, `doctor/generate/check` green (one class, 11 operations,
one property, one signal), accepted debug and release builds, the oracle
passing through the public launcher (`frames=600 checkpoints=6 signals=6`,
zero owners), both profiles exported and the exported applications executed
with their identity environment and zero-owner shutdowns, and one native
editor reload cycle observed clean end to end. Friction found and recorded:
`gododin init`'s template still hardcodes `.dylib` library names and a
macOS target row on every host (a Windows/Linux consumer renames them —
this example's committed files use the suite's recording-host shape), and
the `gododin generate`/`check` lifecycle path needed two Windows fixes that
landed with this example (mixed-separator managed-Odin paths and the
generate stage's symbol-tool resolution); both are recorded in the platform
migration record pending the next SDK reseat. The committed `generated/`
starts as the init skeleton: one `gododin generate` on a host with the
selected SDK publishes the bundle this directory's committed toml binds.
