flan/test/programs/virtual-controls-headless.flan
Joseph Ferano afec482722 Ten raylib examples, and what they could not say
The first ten of raylib's core list, ported. Seven new bindings and the
named colour palette; nothing else was added, because a binding called
by nothing is the same as not having bound it.

The gaps they found are the point. No number reaches draw-text: i64->bytes
answers [u8], draw-text wants a string, and nothing bridges — five of the
ten wanted TextFormat and got a glyph table instead. And an enum parameter
cannot be driven by a loop variable: the index is an i32, the parameter is
an enum, neither converts, and a second declare-c with an i32 face is
refused because one C function gets one binding. Two correct rules that
compose into a wall.

None of the gaps expected blocked anything: no generics, no allocator, no
Vec, no escaping closure, no block-scoped defer. These are input-and-draw
programs over fixed-size state, which is the shape the language has.
2026-09-12 05:06:01 +07:00

60 lines
2.8 KiB
Plaintext

;;;; core-input-virtual-controls.flan's other half: no window, a scripted
;;;; pointer, hash where the player ended up.
;;;;
;;;; The same split sand.flan and sand-headless.flan already have, and it is
;;;; available here for the same reason: the interesting part of that example —
;;;; which D-pad button is under the pointer, and what a held button does to
;;;; the player — is arithmetic over numbers, so it runs with no window, no GL
;;;; context and no libraylib. The link follows what the program reaches:
;;;; nothing below calls into raylib, so no shim is compiled and no -lraylib is
;;;; passed, and the example's own drawing functions are never emitted — which
;;;; was checked with ldd on the built binary: libm and libc and nothing else.
;;;; The example's `main` is not exported, so the only main is this one.
;;;;
;;;; Unlike sand-headless there is no wasm32 case for it yet. Nothing here
;;;; should stop one, for exactly the reason above — but it has not been run,
;;;; so it is not claimed.
;;;;
;;;; It is the only one of the ten ported examples with a headless case, and
;;;; the honest reason is that it is the only one that earns it. The other nine
;;;; are input read straight into drawing calls: a test of them would assert
;;;; that raylib answers 0 for every input with no window open, which is also
;;;; what a binding with its arguments crossed would answer.
;;;;
;;;; What this DOES pin: that the four buttons are where the geometry says they
;;;; are, that the diamond hit test uses x and y the right way round, and that
;;;; the four directions move the player the four different ways. A crossed
;;;; axis anywhere in nearest-button or move-player changes the hash.
(import vc "../../examples/core-input-virtual-controls.flan")
(import rl "vendor:raylib")
;; A sixtieth of a second, fixed. The real program uses get-frame-time, which
;; is exactly the thing a headless run has no answer for.
(defconst dt f32 0.0166666)
;; A lawnmower sweep over the pad's corner of the screen, two pixels at a time.
;; It crosses all four buttons and the dead space between them, so every branch
;; of nearest-button is taken and button-none is taken most of all.
(defconst sweep-x0 20)
(defconst sweep-x1 180)
(defconst sweep-y0 280)
(defconst sweep-y1 420)
(defconst sweep-step 2)
(defn main [] i32
(vc/reset-player)
(let [y sweep-y0]
(while (<= y sweep-y1)
(let [x sweep-x0]
(while (<= x sweep-x1)
(let [p (rl/Vector2 {:x (f32 x) :y (f32 y)})]
(vc/move-player (vc/nearest-button p) dt))
(set x (+ x sweep-step))))
(set y (+ y sweep-step))))
;; write-stdout and i64->bytes are builtins (lib/check.ml), not prelude
;; functions, so this does not go through the printers.
(write-stdout (i64->bytes (i64 (vc/hash-player))))
(write-stdout (bytes "\n"))
0)