luvcraft/world.lisp
Coordinate values are deliberately distinct even though all three carry integer components. World, chunk, and domain-local addresses are not interchangeable. World and chunk coordinates may be negative; local coordinates are checked by a particular chunk domain.
A primitive direction is a displacement, not any of the affine coordinate kinds above. The six shared instances are safe to retain indefinitely; temporary coordinates translated by them may instead be DYNAMIC-EXTENT.
Translate a world cell address by one primitive direction.
Translate a chunk address by one primitive direction.
Map a discrete cell coordinate through space's explicit metric extent.
Decompose a world site into chunk and local scalar components.
Return CHUNK-X, CHUNK-Y, CHUNK-Z, LOCAL-X, LOCAL-Y, and LOCAL-Z without
constructing coordinate objects. Euclidean division keeps every local
component non-negative, including for negative world coordinates. This is
the dense traversal counterpart of world-coordinate-chunk-and-local.
Decompose coordinate by Euclidean division in space.
The local result is always non-negative, including for negative world coordinates.
A chunk domain gives one resident materialization a stable site identity and owns the checked local-coordinate <-> dense-offset correspondence. X is the contiguous axis: x + width * (y + height * z).
Map scalar local coordinates to a dense offset without a row object.
Return the world coordinate of local in domain.
Map a dense offset to local scalar components without a row object.
Map local scalar components to world scalar components without objects.
Use the checked offset operation as the single local-bounds authority.
Execute body for one primitive step from local inside domain.
offset, DESTINATION, and CROSSING are bound as by step-chunk-domain-site, but
DESTINATION has dynamic extent and must be copied before body retains it. The
compiler-visible lifetime keeps rejected adjacency probes off the heap. #E4T0PD
Step from one local site in a primitive face direction.
Return the destination OFFSET and wrapped LOCAL-COORDINATE, followed by
direction when the step crosses into that adjacent chunk or NIL when it stays
inside domain.
Resolve world site X,Y,Z through window.
Return (VALUES MATERIALIZATION OFFSET AVAILABILITY). AVAILABILITY is :AVAILABLE or :UNAVAILABLE; field and subsystem policy must interpret that fact rather than making the spatial protocol call absence air, solid, zero, or open sky. Implementations keep their existing aggregate representation.
Execute body for one domain step continued through window when necessary.
DESTINATION has dynamic extent. MATERIALIZATION and AVAILABILITY are selected
through locate-chunk-window-site only for a boundary crossing. #YUBB7X
Execute body for the DIRECTIONS neighboring LOCAL through WINDOW.
DIRECTIONS is the caller's explicit neighborhood policy. DESTINATION has
dynamic extent on each iteration and must be copied before body retains it.
Interior steps remain domain arithmetic; window dispatch occurs only at an
actual chunk crossing. #E4T0PD
Execute body for the DIRECTIONS neighboring the site at SITE-OFFSET.
This is the trusted-scope counterpart of do-chunk-window-neighbors for a
site already proved to belong to DOMAIN, such as one popped from a packed
frontier. DOMAIN and SITE-OFFSET are validated once; the shape's dimensions
and the site's components are then bound as fixnums, and each direction is a
primitive step with no coordinate object and no repeated bounds or type
check. offset is the destination's dense offset, CROSSING the direction when
the step leaves DOMAIN, and MATERIALIZATION with AVAILABILITY are selected
through locate-chunk-window-site only for a crossing. Public stepping keeps
its checks; this scope pays them once per visited site. #FGT96H
Step local and resolve window only when the step crosses domain.
Return the destination OFFSET, wrapped LOCAL-COORDINATE, and crossing as
step-chunk-domain-site does, followed by the neighboring MATERIALIZATION and
its AVAILABILITY. A local step returns NIL and :local for the last two values.
The one generic window decision therefore occurs only at an aggregate
boundary, never for every site in a dense traversal. #L84JCX
Execute body for every site in DOMAIN, in dense storage order.
LOCAL is a DYNAMIC-EXTENT LOCAL-COORDINATE and must not be retained after
body returns. This gives dense algorithms a nominal coordinate without one
heap allocation per site. See #B3UEVE.
Execute body for every site on DIRECTION's boundary face in DOMAIN.
LOCAL is a DYNAMIC-EXTENT LOCAL-COORDINATE and must not be retained after
body returns.
Block content is a narrow semantic field. The presentable value is a shared Lisp object (or NIL for air); the physical column is a dense u16 offset under the world's block vocabulary. A site is an offset in a domain, not an object with an identity or allocation of its own. Computational code should borrow the aggregate storage below and dispatch once per chunk. Single-site world access still resolves through coordinate descriptors and a chunk key; it is for inspectors, sparse interaction, and other genuinely row-shaped work.
The block vocabulary is the finite domain a content column's indices are closed by: an append-only, world-wide ordering of block objects with NIL (air) at offset zero. One world has one vocabulary, so every chunk's u16 columns mean the same thing, snapshots need no translation, and per-kind tables can be materialized once per vocabulary revision rather than once per chunk. Membership grows only when a never-seen block is placed; offsets never move, so a shape change leaves every existing column and derived product valid. See #CPCZDB.
An append-only finite domain of block objects; NIL is always offset 0.
MEMBERS is the adjustable vector interpreting every dense offset; borrowing it as a palette is the ordinary way whole-domain code reads block identity.
Return a vocabulary with NIL at offset 0 followed by members in order.
Return the block object interpreted by offset under vocabulary.
Return block's dense offset, appending it when intern-p and it is new.
Return NIL for an unknown block when intern-p is false.
Return a u16 vector mapping every source offset to its target offset.
target interns any member it lacks, so the translation is always total.
Return the vocabulary's member vector interpreting column's indices.
Make a content column over domain under vocabulary.
Bind column's transferred storage to the resident domain and vocabulary.
The caller owns column's storage: when its vocabulary differs from the
target, the indices are translated in place so the same dense array serves
under the new interpretation.
Return DOMAIN, palette, and INDICES borrowed from chunk without copying.
This is the ordinary entry point for whole-domain computation. Generic dispatch chooses a representation once; the caller then traverses the dense specialized arrays rather than describing individual cells through CLOS.
Execute body with the three borrowed block-content storage values.
-X, +X, -Y, +Y, -Z, +Z. A derived product for one chunk depends on only the opposing boundary revision of each neighbor, not on arbitrary edits in that neighbor's interior.
The chunk's derived voxel light, revised independently from block content. NIL until a lighting solver publishes a field.
Make a chunk over domain, binding content (or fresh air) to vocabulary.
Read one dense site from chunk without constructing a coordinate object.
Return chunk's revision for the boundary facing direction.
Set one dense site while retaining chunk and boundary invalidation.
The hook receives the edited site so derived domains such as lighting can react to the cell, not merely the chunk.
Describe each site to function as BLOCK and LOCAL-COORDINATE.
This row-shaped convenience protocol is for presentation and irregular local
work. Whole-domain algorithms should use with-block-content-storage.
function may retain LOCAL, so pass it an indefinite-extent copy.
A block world is the resident environment, not the complete world description. Its residency revision changes only when chunks enter or leave; its general revision includes residency and content changes; and each chunk has its own content revision.
The one vocabulary every resident chunk's content column is closed by.
Derived-domain subscriptions. The cell hook receives (CHUNK X Y Z) in world coordinates after an authored content change; the residency hook receives (X Y Z EVENT) with EVENT :ARRIVED or :DEPARTED in chunk coordinates after residency publication.
Call function and coalesce all world changes into one general revision.
Chunk and residency revisions retain their ordinary precision. The outermost
transaction advances world's general revision once if any change occurred,
including when function exits non-locally after making a partial change.
Return the resident chunk at chunk coordinate X,Y,Z and whether it exists.
Return the resident chunk at CHUNK-COORDINATE and whether it exists.
Return the resident chunk at X,Y,Z, creating an all-air chunk if absent.
Install transferred block-content storage as a newly resident chunk.
The caller gives world ownership of content and must not mutate it afterward.
content is a block-content-column. Installation rebinds that aggregate to the
authoritative resident domain and world's vocabulary, translating its indices
in place if it was produced under another vocabulary, and publishes it in one
single-writer step.
Remove a resident chunk. Return the chunk and whether it was present.
A removed chunk may outlive its residency in an inspector or cache, but it no longer owns the right to invalidate this world.
Return resident chunks in deterministic chunk-coordinate order.
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 with-block-content-storage instead.
Set block at one resident world site and return block.
This follows the same sparse coordinate-resolution path as world-block-at.
It signals chunk-not-resident rather than materializing absent terrain, and
retains chunk revision, boundary revision, and world invalidation semantics.
Sparse edits are an overlay on a materialized world, not another dense chunk field. NIL is a meaningful stored value (an explicitly removed block), so hash-table presence distinguishes it from no edit.
Record block as the explicit value for world site X,Y,Z.
Return the edited value at X,Y,Z and whether an edit is present.
Apply every edit in overlay addressed to resident chunk.
Ray traversal is expressed in continuous lattice coordinates: integer planes are cell boundaries, independently of the physical cell extent. The traversal stops at absent terrain rather than silently seeing air.
Trace a ray through world's resident lattice.
Return a BLOCK-RAY-HIT and :HIT, NIL and :ABSENT when traversal reaches a
non-resident chunk, or NIL and :MISS. origin and direction are vec3 values
in continuous cell coordinates. The caller owns and must supply the maximum
ray distance appropriate to its interaction.
(x y z)(x y z)(x y z)(dx dy dz)Logical conjunction of tests and raw truth values.
Test whether two compatible scalars are equal.
Addition over compatible quantities.
The componentwise absolute value of a raw value.
(coordinate direction)(coordinate direction)(direction)Subtraction or unary negation.
(&key (width 16) (height 16) (depth 16))A canonical product of symbolic base dimensions raised to rational powers.
(extent)(vector)(x y z)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
(&key (id (gensym "VOXEL-SPACE-"))
(chunk-shape (make-chunk-shape))
(cell-extent 1d0))(space coordinate)Multiplication and scalar scaling.
(space x y z)Decompose a world site into chunk and local scalar components. Return CHUNK-X, CHUNK-Y, CHUNK-Z, LOCAL-X, LOCAL-Y, and LOCAL-Z without constructing coordinate objects. Euclidean division keeps every local component non-negative, including for negative world coordinates. This is the dense traversal counterpart of…
(space coordinate)Decompose COORDINATE by Euclidean division in SPACE. The local result is always non-negative, including for negative world coordinates.
(space chunk local)Test whether one compatible scalar is less than another.
Logical negation of one test or raw truth value.
(space coordinate)(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.
(domain)(domain)(domain local)Test whether one compatible scalar is at most another.
(domain local)(domain x y z)(domain offset)(domain offset)(domain local)(domain local-x local-y local-z)((offset destination crossing) domain local direction &body body)Execute BODY for one primitive step from LOCAL inside DOMAIN. OFFSET, DESTINATION, and CROSSING are bound as by STEP-CHUNK-DOMAIN-SITE, but DESTINATION has dynamic extent and must be copied before BODY retains it. The compiler-visible lifetime keeps rejected adjacency probes off the heap. #E4T0PD
(domain local direction)Step from one local site in a primitive face direction. Return the destination OFFSET and wrapped LOCAL-COORDINATE, followed by DIRECTION when the step crosses into that adjacent chunk or NIL when it stays inside DOMAIN.
(window x y z)Resolve world site X,Y,Z through WINDOW. Return (VALUES MATERIALIZATION OFFSET AVAILABILITY). AVAILABILITY is :AVAILABLE or :UNAVAILABLE; field and subsystem policy must interpret that fact rather than making the spatial protocol call absence air, solid, zero, or open sky. Implementations keep their existing…
((offset destination crossing materialization availability)
window domain local direction
&body body)Execute BODY for one DOMAIN step continued through WINDOW when necessary. DESTINATION has dynamic extent. MATERIALIZATION and AVAILABILITY are selected through LOCATE-CHUNK-WINDOW-SITE only for a boundary crossing. #YUBB7X
((offset destination crossing direction materialization availability
window domain local directions &optional result)
&body body)Execute BODY for the DIRECTIONS neighboring LOCAL through WINDOW. DIRECTIONS is the caller's explicit neighborhood policy. DESTINATION has dynamic extent on each iteration and must be copied before BODY retains it. Interior steps remain domain arithmetic; window dispatch occurs only at an actual chunk crossing.…
((offset crossing direction materialization availability
window domain site-offset directions &optional result)
&body body)Execute BODY for the DIRECTIONS neighboring the site at SITE-OFFSET. This is the trusted-scope counterpart of DO-CHUNK-WINDOW-NEIGHBORS for a site already proved to belong to DOMAIN, such as one popped from a packed frontier. DOMAIN and SITE-OFFSET are validated once; the shape's dimensions and the site's components…
(&key (code t))(site)(site)(site)Headings, paragraphs, figures and their IDs, mentions, marks.
Logical disjunction of tests and raw truth values.
(window domain local direction)Step LOCAL and resolve WINDOW only when the step crosses DOMAIN. Return the destination OFFSET, wrapped LOCAL-COORDINATE, and crossing as STEP-CHUNK-DOMAIN-SITE does, followed by the neighboring MATERIALIZATION and its AVAILABILITY. A local step returns NIL and :LOCAL for the last two values. The one generic window…
((offset local domain &optional result) &body body)Execute BODY for every site in DOMAIN, in dense storage order. LOCAL is a DYNAMIC-EXTENT LOCAL-COORDINATE and must not be retained after BODY returns. This gives dense algorithms a nominal coordinate without one heap allocation per site. See #B3UEVE.
((offset local domain direction &optional result) &body body)Execute BODY for every site on DIRECTION's boundary face in DOMAIN. LOCAL is a DYNAMIC-EXTENT LOCAL-COORDINATE and must not be retained after BODY returns.
An append-only finite domain of block objects; NIL is always offset 0. MEMBERS is the adjustable vector interpreting every dense offset; borrowing it as a palette is the ordinary way whole-domain code reads block identity.
An append-only finite domain whose semantic members have EQ identity. MEMBERS is the adjustable vector interpreting every dense offset. Appending a new identity increments REVISION without moving any old offset, so retained dense columns stay meaningful. Clients borrow MEMBERS rather than copying it; snapshots which…
(&key members)(vocabulary)(vocabulary)(vocabulary)(vocabulary offset)(domain offset)(vocabulary block &optional (intern-p t))Return BLOCK's dense offset, appending it when INTERN-P and it is new. Return NIL for an unknown block when INTERN-P is false.
(domain member &optional (intern-p t))(source target)Return a u16 vector mapping every SOURCE offset to its TARGET offset. TARGET interns any member it lacks, so the translation is always total.
One top-level defining form of a source file.
((agent application-agent) &key)(representation)Return the finite site domain bound to REPRESENTATION.
(materialization field-name)Return the definition object retained by MATERIALIZATION for FIELD-NAME.
(materialization field-name)Return MATERIALIZATION's retained representation for FIELD-NAME.
(domain &key vocabulary indices)(column domain &optional vocabulary)Bind COLUMN's transferred storage to the resident DOMAIN and VOCABULARY. The caller owns COLUMN's storage: when its vocabulary differs from the target, the indices are translated in place so the same dense array serves under the new interpretation.
(column offset)(chunk)Return DOMAIN, PALETTE, and INDICES borrowed from CHUNK without copying. This is the ordinary entry point for whole-domain computation. Generic dispatch chooses a representation once; the caller then traverses the dense specialized arrays rather than describing individual cells through CLOS.
(scheme)((domain palette indices) chunk &body body)(column block)(column offset block)(domain &key change-hook (incarnation 0) content
vocabulary)(chunk x y z)(chunk offset)(direction)(chunk direction)(chunk x y z)(function chunk)Describe each site to FUNCTION as BLOCK and LOCAL-COORDINATE. This row-shaped convenience protocol is for presentation and irregular local work. Whole-domain algorithms should use WITH-BLOCK-CONTENT-STORAGE.
(world function)Call FUNCTION and coalesce all WORLD changes into one general revision. Chunk and residency revisions retain their ordinary precision. The outermost transaction advances WORLD's general revision once if any change occurred, including when FUNCTION exits non-locally after making a partial change.
((world) &body body)(&key (id (gensym "BLOCK-WORLD-"))
(chunk-width 16)
(chunk-height 16)
(chunk-depth 16)
(cell-extent 1d0)
source)(x y z)(world x y z)(world coordinate)(world domain &key content)(world x y z event)(world x y z)(world x y z content)Install transferred block-content storage as a newly resident chunk. The caller gives WORLD ownership of CONTENT and must not mutate it afterward. CONTENT is a BLOCK-CONTENT-COLUMN. Installation rebinds that aggregate to the authoritative resident domain and WORLD's vocabulary, translating its indices in place if it…
(world x y z)(world)(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…
(world x y z)(overlay)(overlay block x y z)(overlay x y z)(left right)(overlay world chunk)(name-and-options &body slot-descriptions)Define an ordinary structure whose annotated slots publish quantity meaning. The runtime representation and accessors are still those of DEFSTRUCT. #FLRFU8
(world origin direction occupied-p &key max-distance)Trace a ray through WORLD's resident lattice. Return a BLOCK-RAY-HIT and :HIT, NIL and :ABSENT when traversal reaches a non-resident chunk, or NIL and :MISS. ORIGIN and DIRECTION are VEC3 values in continuous cell coordinates. The caller owns and must supply the maximum ray distance appropriate to its interaction.
The componentwise square root of a raw value.
Division of two represented quantities.
The minimum of compatible quantities.
Test whether one compatible scalar is greater than another.
A local domain can say that a step crossed its boundary. A chunk window answers what spatial materialization, if any, can continue the query: The window reports availability; the subsystem interprets it. Lighting may distinguish open sky, closed world, and unknown terrain. Meshing may treat an absent sample as air,…
A chunk-domain should be the one place that knows the finite patch's local shape and storage order. Its useful operational vocabulary is approximately: step-domain-site should report either another local site or a boundary crossing. It should not decide that crossing the east face reaches air, stone, open sky, an…
Intent: preserve checked public domain stepping while avoiding the same bounds and coordinate type validation for each of a trusted worklist site's six neighbors. The packed frontier already proves its entry and offset; adjacency should validate that site once, then keep primitive steps inside the checked scope.…
Intent: expose the shared aggregate operation already visible in the live world, resolved meshing neighborhood, immutable halo snapshot, and light-region atlas. Give those four concrete representations a small protocol for locating a world site or resolving a domain crossing, while keeping availability distinct from…
SBCL's stack-allocation rules make defstruct a good fit for the small spatial values in this layer. A user-defined structure can be stack allocated when its defstruct constructor was declared inline before the definition and the receiving binding is declared dynamic-extent. The declaration is a lifetime promise, not…
Intent. Replace the per-chunk palette with one append-only vocabulary per block-world, so that every chunk's u16 column means the same thing, a mesh snapshot needs no palette translation, a block placement is a hash lookup rather than a linear scan, and per-kind tables can in time be materialized once per vocabulary…
Discrete world coordinates, finite chunk domains, and resident block data.