flan/sand.flan
Joseph Ferano 6df50e9ce1 The sand grid hashes the new generator
The draw is 64 bits now, so every grain lands somewhere else and the old
number could not be right again. Re-taken from a run, which is the one
manual step this case has always had.

sand.flan's two calls say (f32 (rand)).
2026-09-21 11:05:03 +07:00

155 lines
4.6 KiB
Plaintext

(import rl "vendor:raylib")
(import agent "vendor:agent")
(import edn "vendor:edn")
(defconst screen-width 900)
(defconst screen-height 600)
(defconst cell-size 5)
(defconst rows (/ screen-height cell-size))
(defconst cols (/ screen-width cell-size))
(defconst brush-size 10)
(defn dyn->f64 [v f64] f64 v)
(defn dyn->u32 [v i64] u32 (u32 v))
(def gravity dyn 0.05)
(def colors dyn
(let [v (vec-new dyn)]
(push v 0xFFF00FFF)
(push v 0x3B6E8CFF)
(push v 0xA83232FF)
(push v 0xCC6B1FFF)
v))
(defonce grid [rows [cols u32]])
(defonce velocity [rows [cols f32]])
(defonce current-color dyn 0)
(defn insertion-sort [coll [$t]] ()
{:where (ordered? $t)}
(let [i 1
length (len coll)]
(while (and (< i length))
(let [j i]
(while (and (> j 0)
(< (at coll j) (at coll (dec j))))
(let [temp (at coll j)]
(set (at coll j) (at coll (dec j)))
(set (at coll (dec j)) temp))
(-- j)))
(++ i))))
(comment
(insertion-sort [\I \N \S \E \R \T \I \O \N \S \O \R \T])
(insertion-sort (slice [6 2 4 9 1 9 4 5] 0 8))
(let [str (bytes "INSERTIONSORT")]
(insertion-sort str)
(println str))
:-)
(defn clear-grid [] ()
(set grid (zeroed))
(set velocity (zeroed)))
(defn next-color [] ()
(set current-color (% (+ current-color 1) (len colors))))
(defn paint-at [row i32 col i32] ()
(let [half (/ brush-size 2)]
(dotimes [x brush-size]
(dotimes [y brush-size]
(let [r (+ y (- row half))
c (+ x (- col half))]
(when (and (>= r 0) (< r (- rows 1))
(>= c 0) (< c (- cols 1))
(= 0 (at grid r c))
(< (f32 (rand)) 0.5))
(set (at grid r c) (dyn->u32 (at colors current-color)))
(set (at velocity r c) 1.0)))))))
(defn settle [row i32 col i32] ()
(let [vel (+ (f32 (dyn->f64 gravity)) (at velocity row col))
y (min (- rows 1) (+ row (i32 vel)))]
(while (> y row)
(when (= 0 (at grid y col))
(set (at grid y col) (at grid row col))
(set (at grid row col) 0)
(set (at velocity y col) vel)
(set (at velocity row col) 0.0)
(return))
(let [left? (and (> col 0) (= 0 (at grid y (- col 1))))
right? (and (< col (- cols 1)) (= 0 (at grid y (+ col 1))))]
(when (or left? right?)
(let [side (cond
(not left?) 1
(not right?) -1
:else (if (< (f32 (rand)) 0.5) 1 -1))]
(set (at grid y (+ col side)) (at grid row col))
(set (at grid row col) 0)
(set (at velocity y (+ col side)) vel)
(set (at velocity row col) 0.0)
(return))))
(set y (- y 1)))
(set (at velocity row col) 0.0)))
(defn step [] ()
(let [row (- rows 2)]
(while (>= row 0)
(dotimes [col cols]
(unless (= 0 (at grid row col))
(settle row col)))
(set row (- row 1)))))
(defconst fnv-offset u64 0xcbf29ce484222325)
(defconst fnv-prime u64 1099511628211)
(defn hash-grid [] u64
(let [h fnv-offset]
(dotimes [row rows]
(dotimes [col cols]
(let [c (at grid row col)]
(dotimes [b 4]
(set h (bit-xor h (u64 (bit-and (>> c (u32 (* b 8))) 255))))
(set h (* h fnv-prime))))))
h))
(defn game-update [] ()
(when (rl/key-pressed? :key-r) (clear-grid))
(when (rl/mouse-button-down? :mouse-left)
(let [m (rl/get-mouse-position)]
(paint-at (/ (i32 (.y m)) cell-size)
(/ (i32 (.x m)) cell-size))))
(when (rl/mouse-button-released? :mouse-left) (next-color))
(step))
(defn game-draw [] ()
(rl/clear-background rl/black)
(dotimes [row rows]
(dotimes [col cols]
(let [c (at grid row col)]
(unless (= 0 c)
(rl/draw-rectangle (i32 (* col cell-size))
(i32 (* row cell-size))
cell-size cell-size
(rl/get-color c))))))
(rl/draw-fps 20 20))
(defonce frame Allocator (arena-new 262144))
(def game-data dyn
(handler-case (edn/read-file "game-data.edn")
[(FileError [c] nil)]))
(defn main [] ()
(rl/set-trace-log-level :log-warning)
(rl/init-window screen-width screen-height "SAND")
(defer (rl/close-window))
(rl/set-target-fps 120)
(agent/start "/tmp/flan-sand.sock")
(until (rl/window-should-close?)
(restart-case
(do (agent/poll)
(game-update))
(continue [] (do)))
(rl/with-drawing
(game-draw))))