luvcraft/blocks.lisp
Light behavior is distinct from collision: opacity is how much a cell costs propagating light, emission seeds the propagated blocklight field, and surface emission is the material's own visible radiance. One glowing crystal may configure both emissions, but they are different facts.
A class prototype -- which CLIM's presentation dispatch asks for, and which a class redefinition updates through here -- has no slots at all and is not a block kind anyone defined; leave it alone.
How strongly block attenuates propagated light, 0..15.
The blocklight level block seeds into its own cell, 0..15.
block's own linear material radiance, independent of
propagated light.
Project corner onto face's plane as tile-local UV coordinates.
The rule is read from the face's own outward normal rather than its name: horizontal faces map world X,Z straight across the tile, and lateral faces keep the world-horizontal axis as U while flipping world Y into V so tiles hang upright.
The film reel a player loads with a YouTube code; see luvcraft/tape.lisp.
A class of its own rather than a name test, so activating one is a method on the kind and no other block's activation has to know about tapes.
A block that throws things: a fountain of water, a well of lava. What it throws is decided by its name in luvcraft/balls.lisp; the class is what lets placing and removing one be a method rather than a name test.
Define name while preserving current's identity across live redefinition.
class is the block kind class to make; a current of another class is
replaced rather than reinitialized, since its methods would be the wrong
ones.
Define the complete ordered block vocabulary.
Each definition is (variable NAME &rest BLOCK-KIND-INITARGS), optionally
followed by a variable documentation string. Re-evaluation updates existing
objects in place, so resident worlds and live inventories observe the new
definition.
The Martian computer: a white planet sigil on a near-black field, the tenth quickbar material, reached by the 0 key at the end of the number row.
A blank film reel. Focus it and it asks for a YouTube code; when the download lands it has become a film, which is a block that can be picked up and carried. See luvcraft/tape.lisp.
A stone basin that throws water into the air, drop by drop; see luvcraft/balls.lisp for what the drops do.
A slate well of lava that spits glowing gobbets which cool where they land; see luvcraft/balls.lisp.
Meadow grass in bloom: a grass block whose top carries small bright flowers. The birthday meadow freckles its lawns with these.
ensure-block-kind preserves identities across live redefinition, so
deleting a source definition alone would leave an old image offering
the retired material. Agents no longer inhabit this vocabulary.
Return the numbered material palette used by luvcraft and its tools.
Return the shared block kind whose durable semantic name is name.
When error-p is true, signal an error rather than returning NIL for an
unknown name. Save files and other external descriptions refer to block
kinds through this vocabulary instead of printing CLOS object identities.
Painted tiles fill a prefix of a renderer-owned atlas. Capacity is a live
policy rather than mesh meaning: refresh-block-atlas replaces textures when
this changes, while vertices retain their mapping-scoped tile offsets.
The replaceable interpretation of atlas tile identities as dense offsets.
Re-evaluating this definition constructs a new domain. Existing offsets stay closed by the old domain; atlas refresh and later publication explicitly adopt the new one instead of pretending a vocabulary is materialized only once.
Return tile's dense offset under the explicitly supplied atlas domain.
Return the semantic tile identity at offset under atlas domain.
Return the 0..255 surface height of atlas tile tile at tile-local X,Y.
Like the colour, each named tile is one EQL method, so a live image can re-sculpt a single material's micro-surface and rebuild both atlases without touching the rest of the palette.
See #CHUKWD for why relief and normals are generated beside colour rather than arriving as authored assets.
Fine colour grain modulated by tile's shared procedural relief.
Return 0..1 distance from X,Y to the centre of its width by height plate.
The same bond block-atlas-brick-mortar-p reads as a mask, read as a shape
instead: zero in the middle of a panel and one along its boundary, so a
plated surface can be both coloured and domed from one expression.
Return the packed rgba pixel of atlas tile tile at tile-local X,Y.
Each named tile is one EQL method, so a live image can repaint a single material and rebuild the atlas without touching the rest of the palette.
Grass top.
Grass side: a green fringe over dirt.
Dirt.
Stone, with sparse bright flecks.
Wood bark, with vertical grain stripes.
Wood end grain: concentric rings around the tile centre.
Leaves: a strong checker so the canopy reads as foliage.
Sand, with sparse darker grains.
Snow, with sparse glints.
Blue crystal, with bright diagonal facets.
Terminal graphite: a quiet face with a raised per-block bezel.
Gravel: mixed cool and warm stones.
Clay: cool compact earth with faint horizontal bands.
Mud: dark wet clods with occasional glossy pockets.
Moss: dense green cushions mottled across the face.
Cactus side: vertical ribs dotted with pale spines.
Cobblestone: irregular grey stones divided by dark joints.
Fired red bricks with warm variation and deep mortar.
Sawn planks with horizontal seams and wandering grain.
Slate: dark blue-grey layers with fine pale cleavage lines.
Not every atlas tile is a material the player places. The last three belong to the animals which walk over the terrain rather than to the terrain itself: a critter model is built from small textured boxes drawn by the ordinary block surface pipeline, so its hide is painted by exactly the same per-tile arithmetic as stone or moss. See CRITTERS.LISP.
A critter tile is stretched across a box face a fraction of a cell wide rather than tiled over a whole block, so its pattern is deliberately several times finer than a terrain material's: roughly three scutes across a shell rather than two plates across a wall.
Turtle carapace: small staggered scutes with dark keratin joints.
Turtle skin: dark olive hide pebbled with paler flecks.
Whether X,Y lies in the straight seam between two belly plates.
Turtle plastron: pale horn plates in a straight, unstaggered bond.
Colour is only half of what a material looks like. The other half is its micro-surface: whether it is granular, grooved, tufted, or faceted. The normal atlas carries that as a height field and the unit normal derived from it, painted by the same per-tile arithmetic that paints the colour. The block shader reads that normal directly to perturb its shading normal.
Smooth 0..255 clumping at period, so a material can read as tufted.
A plausible default: fine grain, so a new material is never dead flat.
Grass top: blades clumped into tufts.
Grass side: a ragged fringe over dirt clods.
Dirt: rounded clods with grit between them.
Stone: granular, cut by a couple of shallow cracks.
Wood bark: deep vertical grooves with grain between them.
Wood end grain: raised concentric rings.
Leaves: overlapping lobes with gaps between them.
Sand: fine wind ripples over a soft dune.
Snow: soft drifts with the odd crystal glint standing proud.
Terminal graphite: flat glass inside a raised per-block bezel.
Gravel: sharply varying grains at nearly every texel.
Clay: compressed layers with very little loose grain.
Mud: rounded wet clods interrupted by sunken pockets.
Cactus side: strong vertical ribs with standing spines.
Cobblestone: proud stones separated by recessed irregular joints.
Stone bricks: shallow-cut mortar around worn faces.
Fired bricks: deeper joints and rougher faces than stone masonry.
Planks: recessed seams over gently ridged grain.
Sandstone: broad sediment layers with granular faces.
Slate: thin raised sheets divided by sharp cleavage.
Turtle carapace: each scute domes up out of the joint around it.
Turtle skin: small tight pebbles all over the hide.
Turtle plastron: flat belly plates with narrow sunken seams.
The player's own body and what it holds are drawn the same way as the animals -- textured boxes on the block surface pipeline -- and paint their hide, sleeve, and gadgets from the same atlas. See BODY.LISP.
Player skin: warm hide with the faintest knuckle mottling.
Player sleeve: a knitted teal cuff, ribbed along the arm.
Phone body: matte dark metal, one even tone with no visible grain.
Whether X,Y lies on one of the app icons in the phone screen's grid.
The tile is stretched over the whole screen, so its sixteen rows are the screen's height: a status bar along the top row, three rows of four icons, and a dock row at the bottom.
Phone screen: a lit wallpaper gradient with a grid of little app icons.
Player skin: soft, barely textured.
Player sleeve: knitted ribs along the arm.
Phone body: bead-blasted flat, the least relief a tile is allowed.
Phone screen: glass, flat but for the faintest bow across the pane.
The urbit material arrived after the gadget and reel tiles, so its tile offset sits past them: tile order is history, not palette order, and the vocabulary domain alone decides which dense atlas lane a tile gets.
Urbit: the sigil stands proud of a matte face.
--------------------------------------------------------------------- The tape: a film reel, drawn flange-on and rim-on.
A reel flange: dark corners, a bright rim, wound film showing between
three spokes, a hub with a spindle. label-p paints a paper label on the
film.
The canister the reel sits in.
Wound film: dark sepia, faint concentric rings.
Tape flange: an empty reel, film wound dark behind its windows.
Reel rim: two bright flanges with the wound film's edge between them.
The film's edge, striated along the winding.
Film flange: a loaded reel with a paper label across the film.
Tape flange: the rim and hub stand proud, the windows sink.
The birthday meadow's blooming grass. One tile: the grass top scattered with small four-petal flowers. Each bloom belongs to one 4x4 texel cell, so blooms never collide and the tiling stays unobtrusive.
Return the bloom part covering texel X,Y, or NIL for plain grass.
Each 4x4 cell may host one five-texel flower: four petals around a warm centre, jittered inside its cell and coloured per cell.
Blooming grass top: little bright flowers over the meadow green.
Blooming grass top: the grass top's tufts, each flower standing proud.
Return the little world's horizontal RGBA8 atlas as packed pixel words.
rgb is the material's procedural colour and A is opaque coverage. The
array spans the full tile capacity; tiles past the painted count stay
zero, waiting for a material to claim them.
Read tile's relief with coordinates clamped to its own boundary.
Pack a signed tangent-space normal and its source height into RGBA8.
pack-block-atlas-rgba supplies opaque alpha; replace it with the
inspectable height after reusing its channel encoding.
Return tile's packed tangent-space normal at X,Y.
The normal is the central difference of the exact procedural relief painted beside the colour. Boundary reads clamp to the tile, so neither the generated map nor later texture filtering can borrow a neighbouring material's shape.
Return the relief-correlated tangent-space normal atlas as packed RGBA8.
rgb is a linear encoded unit normal and A is the procedural height from which
it was derived. This is a derived materialization, not an authored asset.
A standard class whose annotated slots retain quantity declarations. Slot access and instance representation remain ordinary CLOS. The metaclass only makes definition-time meaning inspectable and inheritable. #OXBSAY
((block block-kind) slot-names &key)Logical conjunction of tests and raw truth values.
Test whether two compatible scalars are equal.
Test whether one compatible scalar is at most another.
(block)(block face)(block)BLOCK's own linear material radiance, independent of propagated light.
(name neighbor corners)(face corner)Project CORNER onto FACE's plane as tile-local UV coordinates. The rule is read from the face's own outward normal rather than its name: horizontal faces map world X,Z straight across the tile, and lateral faces keep the world-horizontal axis as U while flipping world Y into V so tiles hang upright.
Logical negation of one test or raw truth value.
Subtraction or unary negation.
Logical disjunction of tests and raw truth values.
The film reel a player loads with a YouTube code; see luvcraft/tape.lisp. A class of its own rather than a name test, so activating one is a method on the kind and no other block's activation has to know about tapes.
A block that throws things: a fountain of water, a well of lava. What it throws is decided by its name in luvcraft/balls.lisp; the class is what lets placing and removing one be a method rather than a name test.
(current name &key face-tiles categories
(display-color '(0.5 0.5 0.5)) (placeable-p t)
(light-opacity 15) (light-emission 0)
(surface-emission 0.0) (class 'block-kind))Define NAME while preserving CURRENT's identity across live redefinition. CLASS is the block kind class to make; a CURRENT of another class is replaced rather than reinitialized, since its methods would be the wrong ones.
(&body definitions)Define the complete ordered block vocabulary. Each definition is (VARIABLE NAME &rest BLOCK-KIND-INITARGS), optionally followed by a variable documentation string. Re-evaluation updates existing objects in place, so resident worlds and live inventories observe the new definition.
((name symbol) (type (eql 'arithmetic-operator)))(name &optional (error-p t))Return the shared block kind whose durable semantic name is NAME. When ERROR-P is true, signal an error rather than returning NIL for an unknown name. Save files and other external descriptions refer to block kinds through this vocabulary instead of printing CLOS object identities.
(session)How many tiles wide a newly materialized block atlas texture is.
The replaceable interpretation of atlas tile identities as dense offsets. Re-evaluating this definition constructs a new domain. Existing offsets stay closed by the old domain; atlas refresh and later publication explicitly adopt the new one instead of pretending a vocabulary is materialized only once.
(members)Return an immutable keyword domain preserving MEMBERS' order exactly. Duplicate or non-keyword members are rejected. The resulting mapping is appropriate for dense runtime columns and for explicit persisted vocabulary tables; the keyword is semantic identity and its offset is only meaningful under this domain.
(&optional (domain *block-atlas-tile-domain*))(domain)Return the exact number of sites in finite DOMAIN. This deliberately says nothing about coordinate or offset representation. Those mappings belong to concrete domain protocols and are added only when a client needs to traverse them.
(tile &optional (domain *block-atlas-tile-domain*))(domain keyword &optional (error-p t))Return KEYWORD's dense offset under DOMAIN. When ERROR-P is false, return NIL for a keyword outside the domain.
(offset &optional (domain *block-atlas-tile-domain*))(domain offset)(tile x y)Return the 0..255 surface height of atlas tile TILE at tile-local X,Y. Like the colour, each named tile is one EQL method, so a live image can re-sculpt a single material's micro-surface and rebuild both atlases without touching the rest of the palette. See #CHUKWD for why relief and normals are generated beside…
(value)The maximum of compatible quantities.
The minimum of compatible quantities.
(red green blue)(x y tile)Addition over compatible quantities.
The non-negative remainder of integer division.
Multiplication and scalar scaling.
(red green blue &optional (variation 0))(x y brick-width course-height)(x y width height &key (stagger-p t))Return 0..1 distance from X,Y to the centre of its WIDTH by HEIGHT plate. The same bond BLOCK-ATLAS-BRICK-MORTAR-P reads as a mask, read as a shape instead: zero in the middle of a panel and one along its boundary, so a plated surface can be both coloured and domed from one expression.
Division of two represented quantities.
The componentwise absolute value of a raw value.
(tile x y)Return the packed RGBA pixel of atlas tile TILE at tile-local X,Y. Each named tile is one EQL method, so a live image can repaint a single material and rebuild the atlas without touching the rest of the palette.
Test whether one compatible scalar is less than another.
(x y salt)Test whether one compatible scalar is greater than another.
(x y salt period)The componentwise square root of a raw value.
Extract the unsigned bit field (BYTE SIZE POSITION) of one unsigned scalar.
Convert one scalar float or unsigned value to a 32-bit float.
(x y)Whether X,Y lies on one of the app icons in the phone screen's grid. The tile is stretched over the whole screen, so its sixteen rows are the screen's height: a status bar along the top row, three rows of four icons, and a dock row at the bottom.
Test whether one compatible scalar is at least another.
(x y)(x y)(x y label-p)A reel flange: dark corners, a bright rim, wound film showing between three spokes, a hub with a spindle. LABEL-P paints a paper label on the film.
(x y)Return the bloom part covering texel X,Y, or NIL for plain grass. Each 4x4 cell may host one five-texel flower: four petals around a warm centre, jittered inside its cell and coloured per cell.
()Return the little world's horizontal RGBA8 atlas as packed pixel words. RGB is the material's procedural colour and A is opaque coverage. The array spans the full tile capacity; tiles past the painted count stay zero, waiting for a material to claim them.
(tile x y)(x y z height)(tile x y)Return TILE's packed tangent-space normal at X,Y. The normal is the central difference of the exact procedural relief painted beside the colour. Boundary reads clamp to the tile, so neither the generated map nor later texture filtering can borrow a neighbouring material's shape.
()Return the relief-correlated tangent-space normal atlas as packed RGBA8. RGB is a linear encoded unit normal and A is the procedural height from which it was derived. This is a derived materialization, not an authored asset.
Colour is only half of what a material looks like. The other half is its micro-surface: whether it is granular, grooved, tufted, or faceted. luvcraft's atlas was already generated arithmetic rather than an asset, one paint-block-atlas-tile method per numbered tile, so the honest place for that half is the same…
The semantic block vocabulary and its procedural texture atlas.
Blocks and faces are ordinary CLOS objects so the interesting semantic choices stay inspectable and redefinable at the REPL. The material palette here is what the player places, what the mesher shades, and what the shader lab browses; the atlas is generated arithmetic, not an asset.