# Turtle Graphics HOWTO — `capsules/turtle.4th` **Status:** WORKING. First entry in the "cookbook" track Captain Bob asked for on 2026-08-18 (memory: `project-stadium-logo-turtle-idea`, floated 2026-08-11) — a small, low-stakes demo capsule meant to make the CANVAS/ framebuffer substrate satisfying to drive interactively, not a production subsystem. Second cookbook entry (DoE package/library HOWTO) is a separate, later doc. ## What this is A limited LOGO-style turtle graphics vocabulary: a cursor with a position and heading that moves around the screen, drawing a trail when its "pen" is down. Classic commands — `FORWARD`, `BACK`, `LEFT`, `RIGHT`, `PENUP`/ `PENDOWN` — composed entirely in FORTH on top of primitives that already exist: - `PLOT` / `FB-WIDTH` / `FB-HEIGHT` (`src/word_source/framebuffer_words.c`) — raw hardware-boundary pixel write, kernel-only (no-op on hosted builds). - `LINE` / `CIRC-PT` / `Q.SIN` / `Q.COS` (`capsules/fabric.4th`, `src/word_source/q48_words.c`) — Cartesian line-drawing (Bresenham, in raster space) and Q48.16 fixed-point trig, both already load-bearing for the glyph-rendering pipeline. No new C words were added for this — per this repo's standing rule ("compose in FORTH first; new C primitives are justified only for raw hardware access, atomics, syscalls, or freestanding kernel ops"), a turtle is pure policy on top of primitives that already exist. ## Prerequisites - `capsules/fabric.4th` must be loaded first — the turtle uses its `LINE` word directly, and (transitively) `Q.SIN`/`Q.COS`/`Q.FROM-INT`/`Q.TO-INT`/ `Q.*`/`Q.+` from `q48_words.c`, which is always registered. - A real framebuffer. `PLOT` is a no-op on hosted (`make`) builds, so the turtle is only visually meaningful under the kernel/QEMU build with the `gtk` display (`make -f Makefile.starkernel ARCH= qemu`). It loads and runs its arithmetic identically on hosted builds — useful for logic verification, not for seeing anything. ## Loading it Not wired into `init.4th` — it is not part of the Mama VM's boot sequence, by design (memory: "invoked from the REPL", not autoloaded). Load and run it interactively: ```forth S" turtle.4th" EXEC TURTLE-DEMO ``` `TURTLE-DEMO` clears the screen, draws a cyan hexagon, then a magenta five-pointed star from the same starting point — a one-call visual smoke test. ## Vocabulary | Word | Stack effect | Effect | |------|---------------|--------| | `HOME` | `( -- )` | Turtle to screen center, heading east (0°), pen down, color white. Does not clear the screen. | | `CS` | `( -- )` | Clear the framebuffer to black. Plain nested `PLOT` loop (no fill primitive exists) — slow under TCG for a full screen; a one-shot clear, not a per-frame op. | | `PENUP` / `PENDOWN` | `( -- )` | Whether `FORWARD`/`BACK` draw while moving. | | `SETCOLOR` | `( color -- )` | 24-bit `0xRRGGBB`, same format `PLOT` takes directly. | | `SETXY` | `( x y -- )` | Jump to `(x y)` without drawing, regardless of pen state. | | `SETHEADING` | `( deg -- )` | Absolute heading in degrees, 0 = east, counterclockwise positive. | | `FORWARD` | `( n -- )` | Move `n` pixels along the current heading, drawing a `LINE` from old to new position if the pen is down. | | `BACK` | `( n -- )` | `FORWARD` in reverse (`NEGATE FORWARD`). | | `LEFT` | `( deg -- )` | Turn `deg` degrees counterclockwise in place. | | `RIGHT` | `( deg -- )` | Turn `deg` degrees clockwise in place (`NEGATE LEFT`). | | `POLYGON` | `( sides len -- )` | Regular polygon, drawn from the turtle's current position/heading — call `HOME` first for a clean start. | | `STAR` | `( len -- )` | Classic self-intersecting 5-pointed star (`FORWARD` + a 144° turn, five times — not `360/5=72°`, which draws a plain pentagon). | | `TURTLE-DEMO` | `( -- )` | `CS`, a cyan hexagon, then a magenta star. | Internal state (`TX`/`TY`/`THEAD`/`TPEN`/`TCOLOR` and the `FORWARD` scratch pair `TNX`/`TNY`) is exposed as ordinary `VARIABLE`s, matching every other piece of drawing-fabric state in `fabric.4th` — nothing here is hidden or C-side. ## Worked example — a five-pointed star by hand ```forth S" turtle.4th" EXEC HOME 16711935 SETCOLOR ( magenta, 0xFF00FF ) 100 STAR ``` Equivalent to running `TURTLE-DEMO`'s second half. `STAR` is not built from `POLYGON` with a different turn angle — a mathematically regular pentagon (`5 100 POLYGON`, turning `360/5 = 72°` per corner) is convex and does not self-intersect; the classic five-pointed star shape requires overshooting the turn to `144°` per corner instead, which is why `STAR` is its own word rather than a `POLYGON` call with `n=5`. ## Design notes for anyone extending this - **Heading storage.** `THEAD` stores heading directly in Q48.16 radians (not degrees) so `FORWARD` can hand it straight to `Q.SIN`/`Q.COS` without a conversion on every step. `LEFT`/`RIGHT`/`SETHEADING` do the degrees→radians conversion once, at the turn, via the `DEG2RAD` constant (`1144`, Q48.16 for `π/180 ≈ 0.0174533`). - **No manual angle wraparound.** `q48_sin_approx`/`q48_cos_approx` (`src/math_portable.c`) range-reduce internally via `q48_reduce_angle()`, so `THEAD` can accumulate indefinitely across many turns without the turtle needing to keep it inside `[0, 2π)` itself. - **Coordinates are Cartesian, not raster.** `TX`/`TY` follow `fabric.4th`'s own convention (Y increases upward) — the Y-flip to raster space happens once, inside `LINE`'s call to `TO-RASTER`/`CART-Y`. The turtle never touches raster coordinates directly. - **z is always 0.** `fabric.4th`'s `LINE` takes 3D Cartesian points (`x1 y1 z1 x2 y2 z2 color`) because it also serves the cavalier-projection glyph/cube-drawing code; the turtle is flat, so it always passes `0` for both z arguments. ## Verification performed - `mkcapsule --lint capsules/` — clean, no block-size or namespace violations (block range `5100`–`5108`, clear of `fabric.4th`'s highest block at `5002`). - Logic verified on the hosted build: `fabric.4th`'s core blocks (`4900`– `4909`) plus `turtle.4th` piped directly into `./build/amd64/standard/ starforth`, exercising `HOME`, `SETCOLOR`, `POLYGON`, `STAR`, `FORWARD`, and (transitively) `LINE` — zero VM errors, correct stack balance throughout (`--log-debug` trace confirms every `FORWARD` call computes `dx`/`dy` via `Q.COS`/`Q.SIN` correctly and calls `LINE` with the expected seven arguments). - Baked cleanly into `capsule_generated.c` (capsule `[35]`) on a full `Makefile.starkernel ARCH=amd64` build, zero warnings; boot verified clean through POST and into the DoE campaign with the capsule present (not autoloaded, so it cannot affect the boot path it isn't on). - **Visually confirmed 2026-08-19**, live in a `gtk`-display QEMU session: a red `6 100 POLYGON` (hexagon) and a green `100 STAR` both render with correct geometry and color. Screenshot: `evidence/amd64/qemu-screenshot-20260819-074637-turtle-polygon-star- verified.png`. Two things had to be worked out first, worth recording since they'll matter for any future interactive session: - The `~25–30` minute wall this doc used to describe turned out to actually be `capsules/artemis/init.4th`'s `ART-STRESS-CAMPAIGN` (auto-runs at Artemis's birth, unrelated to any DoE mechanism documented in `DOE-LIBRARY-HOWTO-20260819.md`) — it carried a stale `TEMP: ... revert once that run is done` comment for a verification run that had already closed. Reverted to disabled, matching the file's own note (FABRIC-2.md section K/L). - The kernel's heartbeat CSV logging (`[HADES][DOE ]` rows) draws to the *same* console surface `PLOT` draws pixels to, and scrolls continuously — anything drawn gets visually overwritten within a fraction of a second unless silenced first with `HB-OFF` (registered in `src/starkernel/doe_log.c`; `HB-ON` re-enables it). Do this before drawing anything you want to actually see. - `TURTLE-DEMO`'s own `CS` call turned out to be dramatically slower than "slow under TCG" suggested — closer to 20+ minutes than a minor delay, for a full-framebuffer nested `PLOT` loop. For a quick visual check, call `HOME`/`SETCOLOR`/`POLYGON`/`STAR` directly and skip `CS`.