Markdown version: https://ai.hiina.space/reports/magic-circle-programming-languages/05-widdershins-a-stack-language-where-neatness-is.md · index

Index of everything on this site: https://ai.hiina.space/index.md

Magic circle programming languages: 5. Widdershins: a stack language where neatness is mana

5. Widdershins: a stack language where neatness is mana

A spell is a ring of freehand glyphs read counter-clockwise from a keystone. Small rings tangent to the main ring are quotations, and leaving a ring open defers it. The program is an ordinary concatenative stack language in the line of Joy and Hex Casting, so its semantics is deterministic. Drawing quality only changes what the spell costs: neat glyphs are efficient, sloppy ones burn more mana, and because mana is also gas, every spell terminates. Widdershins is the VR design and casts through the existing VR stroke pipeline almost unchanged.

Visual element Meaning
Main ring, closed Program; runs when the cast button is released
Main ring with a gap Prepared spell: compiled and stored on the wand; a later stroke across the gap fires it
Keystone (a small ▸ wedge on the ring) Program start; reading proceeds counter-clockwise (widdershins) from here
Glyph in the ring band, at angle θ One operator; program order is angular order θ, not draw order
Sub-ring tangent to the band, with a gap Quotation [ … ] pushed as a value; contents read CCW from the tangent point
Sub-ring tangent to the band, closed ( … ): quotation executed inline
Dot / bar / n-gon (3 ≤ n ≤ 6) / empty small circle Numerals 1 / 2 / n / 0
Glyph quality q Efficiency of that token's mana cost
Main-ring quality q_R Global efficiency multiplier (a "leaky" ring wastes everything)

Model and evaluation. Values are numbers, vectors, entities, quotations and garbage. A program is the token sequence t₁…tₙ sorted by angle from the keystone, with each sub-ring parsed recursively. Operators include target (an eye glyph; pushes the entity under your gaze), gaze (an arrow; pushes your unit look vector), + (a cross), × (a saltire), dup (a fork), drop (a slash), swap (an hourglass), impel (a chevron; E v → E, pushes E along v), ignite (a zigzag; E → E), i (a spiral; executes the quotation on top), times (a lemniscate; n [Q] → runs Q n times) and if (a Y; b [T] [F]). Effects deliberately leave their target on the stack.

Execution is Joy-style left to right over the angular sequence. Each executed token t costs k(t, args) / η_t, where η_t = q'_t · q'_R, paid from the caster's pool M. An unrecognised glyph, a stack underflow or a type error pushes garbage, and an effect applied to garbage does nothing but still costs, which is Hex's limp-on approach. Every token costs at least k_min > 0, so a run executes at most M / k_min tokens and the language is total. Hex enforces a similar bound with a separate op counter; here the bound is the mana the player already sees. Loop bodies are charged per iteration at their own glyphs' η, so a sloppy glyph inside a loop is paid for every time round, which rewards neat loop bodies without an extra rule. Because program order is angular while draw order only groups strokes into glyphs, a caster can insert a token by drawing it between two existing ones, a real editing gesture.

Worked example: "triple gust" flings whatever you are looking at along your gaze, three times. Draw one closed main ring with the keystone at 3 o'clock and five tokens counter-clockwise at roughly 72° steps: an eye (target) at 0°, a triangle (3) at 72°, an open tangent sub-ring holding an arrow then a chevron ([gaze impel]) at 144°, a lemniscate (times) at 216°, and a slash (drop) at 288°.

                  Δ
          .-""""""""""-.
     C   /              \
         |              | ▸◉
         |      ·       |
     ∞   \              /
          '-.________.-'
                    /
   ◉ target (keystone)   Δ 3   C open sub-ring [→ ›]   ∞ times   / drop

Text form: target 3 [gaze impel] times drop. The trace uses pool M = 50, q_floor = 0.25 (example value), ring quality q_R = 0.9 (so q'_R = 0.925), and nominal costs target 1, numeral 0.5, quote 0.5, gaze 0.5, impel 4·|v|, times 1, drop 0.2 (example values).

Step Token (q) Stack after Cost
1 target (0.8) E 1/(0.85·0.925) = 1.27
2 3 (0.9) E 3 0.58
3 open sub-ring (0.7) E 3 Q 0.70
4 times (0.5) pops 3, Q E 1.73
4a–c gaze (0.8) ×3 E v → … 3 × 0.64 = 1.91
4a–c impel (0.6) ×3, |v| = 1 E 3 × 6.18 = 18.53
5 drop (0.9) (empty) 0.23

The total is about 24.96 of 50. Drawn perfectly, the same spell costs 16.7. The effect is identical either way: three unit pushes. Because the loop count is a literal, the parser can compute the cost statically while you draw, as Psi computes spell stats from constants at compile time; the ring's glow shows projected cost against the pool, and each glyph tints by its η as you finish it.

Mishaps. An unknown glyph renders as a grey smudge with a yellow flare, borrowing Hex's Invalid Pattern colour. An underflow makes the glyph flicker and pads the stack with garbage. When the pool runs out, in safe mode the ring goes dark mid-sequence and the remaining tokens dim; in overcast mode, as in Hex, the deficit comes out of health and the ring burns red. An unclosed ring is not a mishap: the spell stays prepared, hovering at the wand.

Parsing. In VR, the first closed stroke whose circle-fit residual passes threshold becomes the main ring and fixes a polar frame. Strokes are grouped into glyphs by time gap (a pen-up under about 400 ms, guess) and by centroid falling inside the band [0.6R, 1.0R]. Each glyph is rotated so its local radial direction points up before $Q matching, which makes the whole spell rotation-invariant, as Hex's turn-list key is, without discretising the input. Sub-ring tangency is a centre-distance test, |c_sub − c| ≈ R − r_sub. All of this costs well under a millisecond per stroke. From an image the steps are the same after rectification, but the keystone must be found (a filled wedge is easy) and band glyphs are small, exactly where detectors and VLMs are weakest. That is why Widdershins is VR-first.

New versus borrowed. The stack machine, garbage values and mishap colours come from Hex Casting, concatenative semantics from Joy, counter-clockwise reading and tangent auxiliary rings from Mystical, open-equals-prepared from Witch Hat Atelier, the wand as stored program from Noita, and the ring as the unit of control from Rotary. New, as far as this research found, are freehand glyphs in a polar frame, angular order as program order (which gives insert-editing), quality as cost efficiency rather than effect strength, and mana doubling as gas for totality. Untested: whether about 16 freehand glyphs stay separable in mid-air at speed. Wizard of Wii's finding that players dislike similar circular gestures says the glyph set should be strokes and corners, not loops.


Text licensed CC BY 4.0 (attribution: Hiina, ai.hiina.space). Source: https://github.com/hiinaspace/ai-hiina-space