luvcraft/birthday/party.lisp
The party world's save, beside the ordinary world under name's name.
(values name age) for the machine named host.
The party follows the computer: on wigwam it is Daniel's, born the fifteenth of August 1985 -- belatedly, most years -- with his age read off the calendar rather than written down. Everywhere else it is Alex's, who is four.
Pinned time of day: past sunset, before deep night, so a warm band still hangs on the horizon while the stars and fireworks read against the indigo above it.
The y of the highest solid block in the column, probing downward.
Balloon plists from the gazebo's anchors: one balloon floating above each post, and a bouquet crowding the roof finial.
Gnome plists standing in a ring on the lawn around the gazebo.
Throw the party: open the birthday meadow and decorate it.
Loads or creates the party world under its own save file, raises the gazebo,
ties on the balloons, calls in the gnomes, scatters the funny balls, hangs
the greeting in the air, pins the sky at dusk, and starts the fireworks.
Returns the session; luvcraft:stop-playing ends the party and saves it.
name and age default by machine: see honoree-for-host. A film or capture
passes :visible-p NIL, its exact :width and :height, :frames-per-second NIL,
and :register-p NIL so the hidden party neither displaces nor becomes the
interactive *SESSION*.
The lawn must be resident before the gazebo's edits can land. Rebuilding over an existing gazebo rewrites the same cells with the same blocks, so the build is idempotent across reopenings.
The meadow promises a flat lawn at *CLEARING-HEIGHT*, so the gazebo
is told its ground rather than probing for it: the probe scans the
column from above the top chunk layer, which a restored world's
space rejects rather than reading as absent.
A fresh party spawns at the vantage that frames gazebo and greeting together; a resumed one keeps its player where Alex last stood.
The lobby's corner instrument has no place at a party.
The greeting is a marquee wall over the entrance: the name and the age in scrolling lights, mounted above the eave.
Shells rise from high behind the roof: from the lawn the launch point hides behind the gazebo, rockets crest the ridge, and every burst opens in the clear sky above the finial's balloon bouquet rather than behind the cap.
Film the birthday party into an MP4 at pathname and return it.
A hidden party session plays for seconds of real time while the camera
swings sweep radians around the gazebo from the spawn vantage, rising lift
cells and tilting up toward the bursts -- the fireworks open in the sky
above the marquee, just over the spawn framing's top edge -- so the
marquee, balloons, gnomes, and fireworks all pass through frame at their
true animation speed.
Pose turtles on the lawn: guests who stayed for the morning.
Film the party as two acts cut together in one MP4.
The evening act, under evening-hour dusk where the marquee burns
brightest: an establishing sweep of the gazebo and a fireworks crescendo.
Then the morning-hour afterparty: telephoto gnome portraits with the
focus-plane blur engaged -- the centre ray rests on the lawn at the
gnome's distance, so the gnome stays sharp while the gazebo melts behind
it -- and a golden wide over the lawn where the turtles stayed.
A cutscene is cinema, not play: no hotbar, no inventory, no crosshair.
The morning sun stands due east (+x); the afterparty wide runs the west side looking sunward for gold and shafts, the first gnome is front-lit with the sun at the camera's back, and the second is backlit into the glow.
Evening: the marquee in lights over the lawn.
Evening: the fireworks crescendo over the finial.
Morning afterparty: a gnome in the early light, telephoto, zooming in; the gazebo melts behind it.
Its neighbour across the ring, backlit into the sun.
Morning: golden wide over the lawn and its turtles.
The party as a verb in the game itself: M-x Celebrate Birthday.
Commands run on the canvas thread, and celebrate-birthday tears that
session down -- stop-playing waits for a frame boundary -- so like the
quit action it runs beside the game, not inside it.
(&key name age fullscreen-p
(provider luv:*gpu-provider*)
(visible-p t) width height
(frames-per-second 60)
(register-p t)
(sky-hour *party-sky-hour*))Throw the party: open the birthday meadow and decorate it. Loads or creates the party world under its own save file, raises the gazebo, ties on the balloons, calls in the gnomes, scatters the funny balls, hangs the greeting in the air, pins the sky at dusk, and starts the fireworks. Returns the session;…
(birth-year birth-month birth-day)Subtraction or unary negation.
Logical disjunction of tests and raw truth values.
Test whether one compatible scalar is less than another.
Logical conjunction of tests and raw truth values.
Test whether two compatible scalars are equal.
(host)(values name age) for the machine named HOST. The party follows the computer: on wigwam it is Daniel's, born the fifteenth of August 1985 -- belatedly, most years -- with his age read off the calendar rather than written down. Everywhere else it is Alex's, who is four.
The inner product of two vectors.
Pinned time of day: past sunset, before deep night, so a warm band still hangs on the horizon while the stars and fireworks read against the indigo above it.
(world x z)(world x y z)Return one site as BLOCK and :RESIDENT, or NIL and :ABSENT. This sparse world-coordinate accessor constructs coordinate descriptors and a chunk lookup key. It is appropriate for inspectors, ray hits, collision probes, and sparse interaction. Algorithms over many cells should select a chunk/domain once and use…
(anchors)Balloon plists from the gazebo's anchors: one balloon floating above each post, and a bouquet crowding the roof finial.
Addition over compatible quantities.
Multiplication and scalar scaling.
(world center-x center-z &key (count 6) (radius 10.5))Division of two represented quantities.
Convert one scalar float or unsigned value to a 32-bit float.
If you're lucky, someone has bound this to a working GPU-PROVIDER.
The interactive block world built on luv.
()Checkpoint and close the game PLAY opened, releasing its resources. *SESSION* is cleared whether or not the release succeeds, so a failed teardown cannot leave the image believing a game is still playing. The failure itself is not swallowed: STOP-LUVCRAFT closes the window first and then signals what went wrong, and…
The live game session in this Lisp, or NIL.
(pathname)Read and validate one luvcraft save from PATHNAME. Return the restored world and its still-portable resume description.
(&key (seed 121) (chunk-radius 4)
(chunk-height 32))Make the birthday meadow with resident chunks around the party lawn. CHUNK-HEIGHT defaults to 32 so there is sky room for balloons and fireworks. CHUNK-RADIUS NIL leaves the resident set empty for streaming to fill, the way MAKE-EMPTY-LITTLE-BLOCK-WORLD does.
(source world center-x center-z &key (radius 4))Materialize a square resident window and evict everything outside it. Return the entering and leaving chunk-coordinate keys. Entering chunks are created as one staged transaction: establish all desired domains, materialize terrain, populate landmarks, then replay sparse edits.
(world &key (center-x 0) (center-z 0)
ground-y (radius 7))Build the party gazebo centered on CENTER-X, CENTER-Z and return its anchor plist (see the file header). GROUND-Y is the y of the surface block to stand on; when NIL the terrain is probed for it. All edits go through the world's source overlay in one change transaction; the caller relights.
The flat party lawn's surface height.
(world)Solve and publish voxel light from scratch for WORLD's resident chunks. Returns the chunks whose published light changed. The selected production solver must have an explicit SOLVE-LIGHT-REGION-USING method.
(description)Return CAMERA, PLAYER, selected block, and carried blocks restored from DESCRIPTION.
(x y z)(camera)(pathname)(&key
(title "luv little block world — click, look, walk")
;; NIL means "as much of this display as
;; comfortably fits"; a capture asks for the
;; exact frame it intends to write out. A
;; KMSDRM console can only present at a real
;; display mode, so the environment may pin
;; the canvas to the panel's native size.
(width (let ((value (uiop:getenv "LUVCRAFT_WIDTH")))
(and value (parse-integer value))))
(height (let ((value (uiop:getenv "LUVCRAFT_HEIGHT")))
(and value (parse-integer value))))
(frames-per-second 60)
(visible-p t)
(fullscreen-p nil)
(high-pixel-density-p t)
(world (make-empty-little-block-world))
(mesher (make-instance
'exposed-face-mesher))
(camera (make-instance 'fly-camera))
player
(selected-block *stone-block*)
(inventory (make-block-inventory))
quit-function
;; A hidden capture wanting animals in frame
;; hands in a population it has already
;; placed; the ordinary game grows its own
;; around the player as it plays.
(critters
(make-instance 'critter-population))
checkpoint-writer
(provider *gpu-provider*)
(sky-clock (make-instance 'sky-clock))
(sky-profile (make-default-sky-profile))
(shadow-diagnostic-p nil)
;; The world-text banner is a proof of the
;; Slug path, not scenery: a caller that
;; wants one asks for it, and the ordinary
;; game sky stays empty.
(world-text-string nil)
(world-text-font-pathname
(cl-dejavu:font-pathname "DejaVuSans.ttf"))
(world-text-distance 8.0)
(world-text-lift 3.0)
(world-text-units-per-em 0.55)
(video-pathname nil)
(video-distance 13.0)
(video-lift 4.5)
(video-height 5.0)
(residency-radius 6)
(publication-limit 2)
(load-schedule-limit 4)
(mesh-capture-limit 1))Open a little CPU-meshed block world. Click to capture the pointer, look with the mouse, walk with WASD, and jump with Space. Once captured, left click removes the block at the centre of view and right click places the selected block. Number keys select materials, middle click picks the targeted material, Shift…
(writer &key (timeout 10.0))(clock)(session overlay &key (release-p t))Detach OVERLAY at a frame boundary and optionally release it there. The no-release path is intentionally preserved for FUSE-LUVCRAFT-OVERLAY: that path may run inside a frame whose command stream still borrows OVERLAY.
(session &key (text "ALEX 4")
(origin '(-4 15 -9))
(width 9) (height 3)
(columns 72) (rows 11))Mount the marquee wall and start its animation; returns the display. Places a WIDTH by HEIGHT rectangle of terminal blocks at ORIGIN facing -z (the :back face), discovers it as a terminal surface, and dresses it in a marquee display showing TEXT. Placing the same blocks again on a reopened world is a no-op edit, so…
(session balloons)Tie BALLOONS -- plists of (:x :y :z :radius :hue :phase) -- into SESSION. One overlay, one instanced draw. Any balloons already tied on are taken down first, so calling this twice redecorates rather than crowds. Returns the overlay, or NIL when BALLOONS is empty.
(session gnomes)Call in the troupe: draw GNOMES dancing in SESSION as one overlay. GNOMES is a list of plists (:x :y :z :scale :phase :hue): feet position in world cells, stature multiplier, dance phase in turns, and hue in turns around the party colour wheel; scale, phase and hue may be omitted. Any troupe already dancing in…
(session &key center (count 20))Scatter a deterministic mix of beach balls, smiley balls, and classic balls around CENTER, each with a small pop-up velocity, and return their handles, newest first. CENTER is an (X Y Z) list; without one the balls burst a few cells ahead of the session's camera. The scatter is hashed, not random, so the same call…
(session &key origin)Start the show: register one scene overlay whose shells rise from near ORIGIN, a list (X Y Z), ahead of the camera by default. Returns the overlay; calling again while a show runs returns the running one.
The checkpoint writer for the world PLAY opened, or NIL.
(pathname
&key name age (seconds 12) (frame-rate 30)
(width 1280) (height 720)
(sweep 0.9) (lift 2.5)
(provider luv:*gpu-provider*))Film the birthday party into an MP4 at PATHNAME and return it. A hidden party session plays for SECONDS of real time while the camera swings SWEEP radians around the gazebo from the spawn vantage, rising LIFT cells and tilting up toward the bursts -- the fireworks open in the sky above the marquee, just over the…
(camera)The maximum of compatible quantities.
(session pathname
&key (seconds 8) (frame-rate 30) before-frame
(include-hud-p t)
(include-viewmodel-p t))Film SESSION for SECONDS of real time into an MP4 at PATHNAME. Frames are captured at FRAME-RATE, paced against the wall clock so that overlay animation driven by real time plays at its true speed. BEFORE-FRAME, when given, is called with the frame index before each capture, and is the place to move the camera. …
An explicitly owned AVFrame.
(camera)(camera)(session)Stop SESSION exactly once and publish its result to every caller. The sole owner attempts every named release step and closes the canvas and device last. Concurrent and later callers observe the same values or RELEASE-ERROR without releasing a native handle twice.
(session)(population critter)(x y z yaw gait-phase &key resting-p (seed 7))(pathname
&key name age (frame-rate 20)
(width 1280) (height 720)
(evening-hour 18.0)
(morning-hour 7.2)
(provider luv:*gpu-provider*))Film the party as two acts cut together in one MP4. The evening act, under EVENING-HOUR dusk where the marquee burns brightest: an establishing sweep of the gazebo and a fireworks crescendo. Then the MORNING-HOUR afterparty: telephoto gnome portraits with the focus-plane blur engaged -- the centre ray rests on the…
(overlay)Return where OVERLAY draws: :SCENE, :WORLD-PANEL, :VIEWMODEL, :HUD, or :NONE. Scene overlays inhabit world depth; viewmodels are first-person geometry above the world but below held items and the crosshair. World panels retain world projection and depth while drawing analytic application graphics at native…
Draw the crosshair. A film shot is not aiming at anything.
The block-world camera's 70-degree vertical field of view.
The componentwise square root of a raw value.
Engage the focus-plane background blur without a modal focus. The focus plane is the depth at the centre of the frame, so a film shot that wants a subject sharp against a blurred background aims the centre ray at ground or blocks standing at the subject's distance. A global rather than a binding because the…
(name (&rest lambda-list) documentation &body body)
The party: how the aspects compose into one scene.
celebrate-birthdayis the only place that knows the whole arrangement: where the gazebo stands on the meadow, how the balloons tie to its posts, where the gnomes dance, where the funny balls scatter, and when the sky settles into the pinned dusk the fireworks want. Each aspect stays ignorant of the others; changing the composition means editing only this file.The world lives under its own save file beside the ordinary one, so the everyday game is untouched and the party can be reopened any time.