luvcraft/agent/gnome.lisp
gnome
The lengths below, like everything in the shader that draws him, are in
figure units: the frame the gnome is laid out in, where his hat reaches
GNOME-HAT-HEIGHT whatever his stature. gnome-stature is the one place
the world's scale enters, so it multiplies all of them.
The height above his feet of the centre of the gnome's bounding sphere.
The shader's marcher agrees with this number; moving one moves both.
Slack added to the computed bounding radius, for the rim light and for the fillets that push a weld a little outside the parts it joins.
The height of the gnome's eyes above his feet.
What looks at a gnome is aimed here. It is not the top of him: aiming a conversation at the top of a gnome frames his hat.
How many world cells one figure unit is, from the gnome-stature knob.
The radius, in figure units, of a sphere about *GNOME-BODY-CENTRE* that
holds every part of the gnome the knobs are currently asking for.
The billboard is a conservative proxy and nothing outside it is drawn, so this has to be recomputed rather than assumed: a hat raised past a fixed radius does not overflow, it comes out sliced flat across the top. Each term is the extreme of one part -- how far out it reaches and how high it sits -- and the sphere is the largest of them.
the tip, wherever it leans
the cone's skirt
the brim's edge
the end of the nose
the back of the head
the whiskers
the beard's point
the hem at its widest
the hem at the ground
the shoulders
the mittens
the toes
A pane background that paints nothing: colour with zero opacity, which the GPU medium spells as a fully transparent fill.
The cell is the discrete public place; position and VELOCITY are the
physical realization moving between such places. Keeping both makes
the intentional and simulation authorities explicit (#YPGXKI).
One embodied agent at a discrete cell: its thread, figure, and voice.
A small SDF-rendered garden gnome carrying a world-agent.
agent's visible height above its occupied cell, in blocks.
The world point above agent, optionally lift blocks higher.
The world point agent looks from, optionally lift blocks higher.
Where a ray enters agent's conservative body, or NIL.
How far away the focused camera stands from agent.
Return agent's world-agent, opening it synchronously when necessary.
This setup operation may perform network I/O and must not run on the canvas thread. Gnome interaction uses Gnome-Ask's asynchronous first-contact path.
Perform the blocking provider setup for agent and return a fresh world-agent.
Methods construct candidates only. The common opening protocol installs one winner, attaches its observer, and releases candidates that lose to teardown.
Return agent's render body, creating it when necessary.
Return agent's conservative SDF proxy as world-space X, Y, Z, RADIUS.
The visible conversational figures are full block-world bodies. Their behavior is destinational, but contact is the same open body protocol the player and critters use.
The embodied agents in live sessions.
These are semantic individuals, not members of the world's critter population and not readings of its block field. Releasing their session overlays removes them from this registry.
Return session's embodied agents, newest first.
Make one class at X,Y,Z and attach its semantic and render overlays.
Find the embodied agent occupying integer cell X,Y,Z in session.
When make-p is true, create and attach one if the cell is unoccupied.
The height of the hat's tip above his feet, in figure units.
What is above a gnome -- his speech bubbles -- is measured from here, so a taller hat pushes them up rather than growing through them.
The point above the gnome's hat, lift blocks higher.
Compatibility name for embodied-agent-head-position.
The point between the gnome's eyes, lift blocks higher.
Compatibility name for embodied-agent-face-position.
--------------------------------------------------------------------- The embodied agent as an overlay and a focus
Targetable by TAB when the view ray enters the agent before terrain.
Return where a ray enters gnome's upright body, or NIL when it misses.
Compatibility name for embodied-agent-ray-distance.
Step back to a conversational distance, look the gnome in the face, and leave room above its hat for the bubbles.
Start text now, or queue it behind one asynchronous provider opening.
In particular, first contact never performs DNS, TLS, or a WebSocket handshake
on the canvas thread. It returns gnome while opening, and a turn when the
provider was already installed.
--------------------------------------------------------------------- The agent behind the gnome
You are a gnome: a small, cheerful, slightly gruff embodied agent in luvcraft, a block world running inside a live Common Lisp image. A player is talking to you. Your tools are the game's own commands. Coordinates are integer block cells: x and z are horizontal, y is up; you stand at the cell given below. To talk to the player you MUST use the say tool -- only what you say is heard; your final message is not shown. Keep what you say short and in character. Results may mention #ABCD handles; pass one back to describe-handle to read more.
Compatibility name for ensure-embodied-agent-agent.
Observers run in the turn's thread; they only queue intentions the
canvas thread realizes in refresh-luvcraft-overlay.
Publish condition for the next canvas refresh, unless agent was released.
Release a provider candidate that was never published on presence.
Relinquish owner and queue one canvas-safe failure for its pending prompts.
Install candidate iff owner still owns presence's opening.
Return the installed provider and the pending prompts in arrival order. A candidate that loses to release or another publication is detached and closed.
Keep validation inside the cleanup extent: a buggy opener can still have returned a live provider object of the wrong class.
Submit prompts without letting one worker-creation failure lose the rest.
Blocking body of the provider-opening worker owned by owner.
Start owner's named connection worker and return immediately.
This deliberately remains a synchronous setup primitive for SLY and
explicit callers. Canvas interaction reaches only gnome-ask above.
Detach presence from its provider once, without waiting for an opener.
--------------------------------------------------------------------- Saying
--------------------------------------------------------------------- The dialogue line: a HUD title at the bottom of the view.
A pane that paints nothing but its text: the view shows through.
The pane is the whole frame: a layout pane around it would paint its own background, and there is nothing to lay out.
What the line shows: (SPEAKER TEXT INK) or NIL.
Centred at the bottom of the viewport.
NDC spans two units over the viewport, so this is half the pixels.
Make an enabled McCLIM frame embedded in session's canvas; return it.
--------------------------------------------------------------------- The visible body: a sphere-traced scene object, not terrain.
The shared conservative billboard and GPU resources for one SDF agent.
The gnome's SDF body overlay.
The gnome's current conservative proxy, including his visual bob.
Publish overlay's conservative sphere and retained forward direction.
Make and attach one role pipeline body for agent.
--------------------------------------------------------------------- Bubbles: cassettes in the world above the gnome's head.
What the bubble shows, as a key: repaint when it changes.
How tall the slab must be for item.
The cassette: a matte rounded slab standing off the world, as tall as its contents and sitting at the bottom of the pane, nearest the head.
Face the camera from above the gnome, at the bubble's current lift.
Draw the bubble flat, in the scene, facing the player.
Ease toward the stack position the newer bubbles have pushed it to.
Put a new bubble for item above gnome's head, pushing the others up.
The gnome's semantic stack contains only application-owned overlays. A terminal rejection releases OVERLAY before this publication point.
Newest lowest; the ones past the count are taken down.
--------------------------------------------------------------------- Realizing the transcript, on the canvas thread, once a frame.
The gnome itself draws nothing; its refresh is where the turn thread's notes become bubbles and lines, and where old bubbles are taken down.
Run agent's Move To motor at the same fixed step as the player.
The public place follows the continuous base as it crosses cell bounds.
--------------------------------------------------------------------- Spawning one
Spawn an embodied agent of class at integer cell X,Y,Z and return it.
With no coordinate, choose an empty cell a few steps ahead of the player and stand the agent on the first supporting block. The cell names its discrete place while its position and velocity continuously realize travel between places.
Stand on the ground, not in it.
Spawn a visible gnome agent, choosing a supported cell when omitted.
The height above his feet of the centre of the gnome's bounding sphere. The shader's marcher agrees with this number; moving one moves both.
Slack added to the computed bounding radius, for the rim light and for the fillets that push a weld a little outside the parts it joins.
The height of the gnome's eyes above his feet. What looks at a gnome is aimed here. It is not the top of him: aiming a conversation at the top of a gnome frames his hat.
Convert one scalar float or unsigned value to a 32-bit float.
The whole figure's scale, in world cells per figure unit. The marcher works in figure units and this is the only place the world's scale enters, so his bounding sphere follows from it too. At four fifths he stands about a cell and a quarter: shorter than a player, which is rather the point of him.
()The radius, in figure units, of a sphere about *GNOME-BODY-CENTRE* that holds every part of the gnome the knobs are currently asking for. The billboard is a conservative proxy and nothing outside it is drawn, so this has to be recomputed rather than assumed: a hat raised past a fixed radius does not overflow, it…
One live value: where it lives, what it measures, and -- by its class -- what SESSION must do after a change for the change to show.
How high the hat's tip stands above his feet.
The radius of the hat's cone where it meets the brim.
How far forward the hat's tip leans. Zero is a traffic cone.
The brim's radius. Wider than about four tenths and it eats his face.
The radius of the head the face is laid out on.
The radius of the nose, the one feature of him nothing hides.
How broad the beard hangs at the cheeks.
The height of the beard's blunt point above his feet: lower is longer.
The robe's radius at the hem.
The robe's radius at the shoulders.
How far out from the body his mitten hands rest.
Subtraction or unary negation.
The componentwise square root of a raw value.
Addition over compatible quantities.
Multiplication and scalar scaling.
The maximum of compatible quantities.
The componentwise absolute value of a raw value.
A pane background that paints nothing: colour with zero opacity, which the GPU medium spells as a fully transparent fill.
One embodied agent at a discrete cell: its thread, figure, and voice.
(x y z)A small SDF-rendered garden gnome carrying a WORLD-AGENT.
(agent)AGENT's visible height above its occupied cell, in blocks.
(agent &optional lift)The world point above AGENT, optionally LIFT blocks higher.
(agent &optional lift)The world point AGENT looks from, optionally LIFT blocks higher.
(agent origin direction max-distance)Where a ray enters AGENT's conservative body, or NIL.
(agent)How far away the focused camera stands from AGENT.
(agent)Return AGENT's WORLD-AGENT, opening it synchronously when necessary. This setup operation may perform network I/O and must not run on the canvas thread. Gnome interaction uses Gnome-Ask's asynchronous first-contact path.
(agent)Perform the blocking provider setup for AGENT and return a fresh WORLD-AGENT. Methods construct candidates only. The common opening protocol installs one winner, attaches its observer, and releases candidates that lose to teardown.
(agent)Return AGENT's conservative SDF proxy as world-space X, Y, Z, RADIUS.
(subject session)Return SUBJECT's retained YAW and PITCH, or NIL values without a facing.
(body)How quickly BODY changes horizontal velocity on the ground.
One named verb over a session.
((call tool-call) stream)The embodied agents in live sessions. These are semantic individuals, not members of the world's critter population and not readings of its block field. Releasing their session overlays removes them from this registry.
(session)(session x y z)Logical conjunction of tests and raw truth values.
Test whether two compatible scalars are equal.
(class session x y z &key (facing-yaw 0d0))(session overlay)Attach OVERLAY at SESSION's next native frame boundary and return it. ADD consumes a newly offered OVERLAY on both success and terminal rejection. Once SESSION begins stopping, the rejected overlay is released exactly once before APPLICATION-ATTACHMENT-CLOSED is signalled.
(session x y z &optional (make-p t))Find the embodied agent occupying integer cell X,Y,Z in SESSION. When MAKE-P is true, create and attach one if the cell is unoccupied.
Logical disjunction of tests and raw truth values.
()The height of the hat's tip above his feet, in figure units. What is above a gnome -- his speech bubbles -- is measured from here, so a taller hat pushes them up rather than growing through them.
(body)(body)(body)(gnome &optional (lift 0.0))(gnome &optional (lift 0.0))(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…
(focus session)Return a non-negative targeting score when FOCUS can be entered by TAB.
(camera)(session &key (max-distance +luvcraft-target-reach+))Test whether one compatible scalar is less than another.
Test whether one compatible scalar is at most another.
Division of two represented quantities.
Test whether one compatible scalar is greater than another.
The minimum of compatible quantities.
(gnome origin direction max-distance)How far from the gnome the focused camera stands, in blocks.
(focus session)Return FOCUS's desired CAMERA-POSE in SESSION, or NIL for an FOV-only cue.
(approval presence session)Return the cinematic pose for APPROVAL, or NIL.
The 50-degree vertical field of view used during modal focus.
(focus session)Notify FOCUS that SESSION has entered its interaction mode.
(gnome)(gnome)(focus session)Notify FOCUS that SESSION has left its interaction mode.
(gnome text)Start TEXT now, or queue it behind one asynchronous provider opening. In particular, first contact never performs DNS, TLS, or a WebSocket handshake on the canvas thread. It returns GNOME while opening, and a TURN when the provider was already installed.
(text &key agent)(presence owner)(focus session canvas event)Handle EVENT while FOCUS owns SESSION's modal player interaction.
A native destination with a lifetime and frame clock.
(session)(approval note)Return APPROVAL to its proposer with revision guidance.
(gnome text)(canvas)The text on the system clipboard, or NIL when there is none or the window system has no clipboard to ask.
You are a gnome: a small, cheerful, slightly gruff embodied agent in luvcraft, a block world running inside a live Common Lisp image. A player is talking to you. Your tools are the game's own commands. Coordinates are integer block cells: x and z are horizontal, y is up; you stand at the cell given below. To talk…
(&key (session luvcraft:*session*)
(model *default-agent-model*)
(commands *default-agent-tools*)
(instructions *default-instructions*)
(reasoning-summary "auto")
reasoning-effort
(api-key (openai:default-api-key)))Open Luvcraft's thin WORLD-AGENT specialization for SESSION. Connection setup performs network I/O; call this from SLY or a setup worker, never from the canvas thread. Once open, ASK itself always returns at once.
(gnome)(gnome)(overlay session)Publish any complete pending render state for OVERLAY at a frame boundary.
(gnome note)(agent condition &optional (context "Agent"))A MuPDF context: its allocator, its store, and its error stack.
Logical negation of one test or raw truth value.
(presence agent observer)(agent function)The most recently made Luvcraft WORLD-AGENT for REPL convenience.
(agent)Detach AGENT and initiate its provider close exactly once. Terminal state is visible before this function returns. A dedicated lifecycle thread promptly sends the provider's non-destructive close frame so an active receive can wake; it never executes on the caller or application canvas. The sole FIFO worker rejects…
(presence owner condition)(presence owner candidate)Install CANDIDATE iff OWNER still owns PRESENCE's opening. Return the installed provider and the pending prompts in arrival order. A candidate that loses to release or another publication is detached and closed.
(agent function)(presence provider prompts)(presence owner)(presence)(presence)(name (&rest lambda-list) documentation &body body)The APPLICATION-AGENT whose CLIM command is executing dynamically.
A pane that paints nothing but its text: the view shows through.
(gnome)((pane lobby-hud-pane) region)An explicitly owned AVFrame.
(text columns)(sheet x1 y1 x2 y2 &rest options
&key (radius 7) (filled t) &allow-other-keys)A direct McCLIM surface mounted in the presentation HUD.
(overlay)(overlay)(overlay session pass surface-texture)Encode OVERLAY into SESSION's open scene PASS for SURFACE-TEXTURE.
(session frame-class &rest initargs)A McCLIM frame manager constrained by luv's current native host.
The shared conservative billboard and GPU resources for one SDF agent.
The gnome's SDF body overlay.
(overlay)The live shader pipelines OVERLAY owns, so the session can count them among its own; none by default.
(overlay)(pass-encoder pipeline)(pass-encoder slot buffer &key (offset 0))(pass-encoder index bind-group)(pass-encoder vertex-count
&optional (instance-count 1) (first-vertex 0) (first-instance 0))(overlay)Release resources owned by an object attached to luvcraft.
(artifact)(handle)Logically invalidate HANDLE immediately. Native teardown may be deferred until submitted work which captured HANDLE has completed.
(agent role label &key (class 'sdf-agent-body-overlay))(device descriptor)Asks the DEVICE for a handle to newly created instance of some object fulfilling the DESCRIPTOR.
(&key role (stage :fragment) vertex-role label device layout vertex-module
vertex-buffers target-format target-blend primitive depth-stencil)Create and install a live mathematical render pipeline. VERTEX-MODULE is borrowed when VERTEX-ROLE is NIL and STAGE is not :VERTEX. Every module compiled from ROLE or VERTEX-ROLE is owned by the returned artifact and retired on replacement or explicit release.
The linear HDR attachment format shared by every scene-stage pipeline.
(gnome)How wide a bubble is in blocks.
How far above the hat the newest bubble's centre floats, in blocks.
The vertical distance between stacked bubbles, in blocks.
How many bubbles stay up before the oldest is dropped.
How long after a turn ends its bubbles stay.
(frame)(call &optional (columns (- *agent-hud-columns* 2)))Characters per wrapped line at the body text size.
(albedo height)(stream lines top &key (ink *hud-output-ink*)
(indent 0) (size *cassette-text-size*)
(face :roman))(queue swapchain image-index
&key (wait-semaphores #()) present-id present-stage time-domain-id
target-time target-time-domain-present-stage)A direct McCLIM surface mounted in the 3D scene.
(overlay session)(vector scale)(context)Return CONTEXT's configured drawable extent as (WIDTH HEIGHT), or NIL.
(overlay session width height)(overlay)(gnome item)(gnome)(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.
(gnome)(gnome item)(gnome note)(overlay session seconds)Advance OVERLAY's simulation state by SECONDS at the frame boundary.
Test whether one compatible scalar is at least another.
(body world seconds)(body)(class &key (session luvcraft:*session*) x y z)Spawn an embodied agent of CLASS at integer cell X,Y,Z and return it. With no coordinate, choose an empty cell a few steps ahead of the player and stand the agent on the first supporting block. The cell names its discrete place while its position and velocity continuously realize travel between places.
The live game session in this Lisp, or NIL.
(player)(player)(player)(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…
(&key (session luvcraft:*session*) x y z)An agent that is only a websocket is a chat window with extra steps. The point of doing this inside luvcraft is that the agent can be somewhere: a presence object with a position and a facing, so look, walk and place are presentation-typed commands relative to it, and its transcript is the terminal wall it is…
The body (#5JDNKF) is deliberately skew to the block field. A gnome or cat belongs to *agents*, not *critters*, and Spawn Gnome or Spawn Cat chooses an empty supported cell ahead of the player without editing terrain. Its integer (x y z) is the public, intentional place; continuous position and velocity are the…
Intent. An embodied agent acts in places rather than holding a WASD key: Move To (x y z) is one discrete, nearby destination and one terminal result. Intent does not flatten physics. The body has a continuous position and velocity, accelerates through the same collision motor as the player, falls under gravity,…
The gnome: an agent with a body (#5JDNKF), not a block (#V9DHV5).
A gnome occupies a discrete world cell but is not a block. The cell is semantic state -- where this agent stands -- while its animated, camera-facing figure is an independently rendered scene object. Focusing it is how you talk to it: the view leans in the way it does for a wall, the keys become a prompt line at the bottom of the screen, and RET asks. The gnome then thinks, and its thinking shows above its head as a bubble: a matte rounded cassette standing in the world, drawn through McCLIM the way the Telegram panel is (a world widget, in the scene, with relief). Each tool call is the next cassette, and pushes the ones before it upward. When the gnome talks -- the SAY command, which is a tool like any other -- it is not a cassette but a title at the bottom of the view, the way an NPC line is subtitled.