Mine Chris: a voxel game as a ChrisOS integration workload¶
About this chapter Input, windows and applications
In this chapter
- Mine Chris: a voxel game as a ChrisOS integration workload
- Runtime structure
- Main loop and modes
- State representation
- Voxel world generation
- Player movement and camera
- Block interaction
- Bow and projectiles
- Actors and AI
- Rendering
- Day, night and weather
- Menus, HUD and inventory
- Progression
- Save and checkpoint model
- Audio
- Why Mine Chris belongs in the OS documentation
- Current limitations
Mine Chris is a first-person voxel game implemented in ChrisC and distributed as GAMES/MINE/MINE.CLV. In the documentation curriculum it is significant less as a standalone game than as an integration workload: one program exercises the CLVM runtime, input, voxel storage, software 3D, simulation, audio, filesystem persistence, UI and application loop.
The reviewed source is modular at the ChrisC level. MINE.CC includes shared simulation/graphics libraries and game-specific state, generation, sky, persistence, AI, play and UI modules. MINE.LST, however, contains only GAMES/MINE/MINE.CC; the included files are pulled transitively by the source itself.
Runtime structure¶
MINE.CLV
|
+-- input -------- keyboard + relative/captured mouse
+-- simulation --- actors + collision + voxel queries
+-- world -------- voxel generation + block edits
+-- rendering ---- camera + world + mesh actors + HUD
+-- environment -- clock + daylight + rain
+-- audio -------- tone + PCM
+-- persistence -- MINE.SAV
+-- UI ----------- menu + pause + inventory + HUD
The game is useful as a systems test because these paths must work together frame after frame.
Main loop and modes¶
main() requests an 800×600 viewport, initializes graphics state and starts with g_mode = 0. The loop runs until mode 9.
Mode 0 displays the menu. Gameplay uses mode 1, mode 2 is pause, mode 3 is inventory and mode 5 is used after the tower completion condition. Escape-like and inventory keys switch between these states. During active gameplay, play_step() updates the simulation, then paint_world() draws the scene and ui_hud() overlays game state.
This is a direct state-machine architecture rather than a general scene framework.
State representation¶
STATE.CC defines a compact Actor structure with position, velocity, yaw, pitch, kind, state, timer and bit-field flags for ground, water, bow and alive state. The global actor pool contains 16 entries. Entry zero is the player; the remaining slots are reused for world actors, pickups and projectiles.
The game also keeps a 16-entry inventory, resource counters, environmental flags, scene/physics handles, palette and audio buffers, plus a snapshot used for checkpoint-style respawn.
Fixed-size state is a deliberate property of this revision. Mine Chris does not establish an unbounded entity-component system.
Voxel world generation¶
GEN.CC constructs a bounded authored voxel world. putb() rejects coordinates below 1 and above x/z 126 or y 60 before calling voxel(). gen_world() fills a region with terrain, water, structures, trees and special blocks, then sets g_built so generation is performed once for the current game state.
The world is therefore generated procedurally by deterministic placement code, but it is not an infinite procedural terrain generator. The source describes a finite designed play area.
Player movement and camera¶
spawn_player() searches downward for solid terrain and positions actor zero above it. play_step() reads mouse deltas and keyboard state, updates yaw/pitch and applies movement velocity relative to yaw. Pitch is clamped between -50 and +50 degrees.
The current source explicitly documents its convention: positive screen-space mouse Y increases pitch because the 3D forward-vector convention uses negative sine for vertical direction.
Movement is passed through sim_move(). Ground state is recomputed with sim_blocked(), while water is detected through voxel_get() and reduces horizontal velocity.
The game uses mouse capture and relative motion during gameplay, making Mine Chris a practical consumer of the input-routing mechanisms documented earlier in this volume.
Block interaction¶
The game can remove and place voxels. break_block() samples a point in front of the player at a reach of 2.2 units, validates the target and replaces the voxel with zero. Valid block IDs are credited to the inventory. place_block() maps selected hand slots to block IDs, checks inventory quantity and places a block only into an empty target cell.
This path is important architecturally because rendering is not the only consumer of the voxel world: game logic reads and mutates the same world representation.
Bow and projectiles¶
shoot() converts accumulated charge into a bounded scale between 0.4 and 2.2. It finds a free actor slot, decrements the arrow count and creates a projectile actor with velocity derived from player yaw and pitch. The action also uses tone/PCM output.
A high charge can additionally harvest certain nearby voxel types before the projectile is allocated. If no actor slot is free, no projectile is created.
The fixed actor pool therefore creates a visible resource limit in gameplay and simultaneously exercises bounded runtime state.
Actors and AI¶
boot_actors() initializes the 16-slot pool, creates the player and seeds several actors/pickups at fixed world coordinates. AI.CC updates non-projectile/non-pickup actors using a small state machine based on actor kind, rain, game phase, distance to the player and a timer.
Movement is deliberately simple. Actors choose small x/z velocity components and perform voxel occupancy checks before movement. This is not pathfinding over a navigation mesh; it is a compact behavior system suitable for exercising simulation primitives.
Rendering¶
paint_world() sets the camera from actor zero, renders the sky and voxel world, then iterates through the remaining actor slots. Active actors are rendered through draw_mob() with state-dependent vertical animation and color selection.
CUBE.CC defines eight vertices for a small box-like actor mesh, initializes an identity transform and submits the mesh through meshf(). This provides a minimal mesh workload alongside the voxel world renderer.
Mine Chris therefore connects higher-level gameplay state to lower-level geometry and rasterization facilities rather than treating 3D output as a pre-rendered asset.
Day, night and weather¶
SKY.CC derives an in-game hour from ticks() plus g_bias. The clock cycles over 24 values. Hours 6 through 17 are treated as day, while rain is enabled from hour 16 through 18.
The sky path changes light parameters and background fill according to day/night/rain state. It also updates a texture offset from the tick counter. sky_flip() shifts the time bias to move between day and night ranges.
This is a deterministic environmental model, not a meteorological simulation.
Menus, HUD and inventory¶
UI.CC implements pointer-tested buttons for the main menu and pause menu. The main menu offers play, continue and exit. Continue initializes the world if needed and then attempts save_read().
The pause UI exposes continue, checkpoint, inventory and exit-from-phase actions. The inventory displays item counts plus arrows, wood and pearls. The HUD displays in-game hour, phase, weather state, transient notifications, crosshair, hand slots and FPS.
The UI is rendered directly with primitives such as fillrgb(), text(), line() and pixel() rather than through a large widget toolkit.
Progression¶
The reviewed gameplay code has explicit phase transitions. The initial state is phase 1. Collecting enough wood and entering the relevant region advances to phase 2; collecting enough pearls and reaching the far side advances to phase 3. Reaching a designated high block sets mode 5, for which the HUD displays the tower-completed message.
These rules are hard-coded game logic and should not be generalized into a quest engine.
Save and checkpoint model¶
SAVE.CC maintains two different persistence concepts. g_snap is an in-memory player snapshot used by respawn(). MINE.SAV is a filesystem save.
save_pack() writes a compact byte representation containing a marker value, phase, integer-converted player position/yaw, resource counts and 16 inventory entries. save_write() writes 40 bytes to MINE.SAV; save_read() reads 40 bytes and accepts the data only when the first byte equals 77.
This format is intentionally small. The reviewed code does not establish versioning, checksums, atomic replacement, schema migration or robust corruption recovery. It also does not persist the complete mutable voxel world or all actor state.
Audio¶
Gameplay calls tone() for short event feedback and pcm_write() when firing. Mine Chris therefore exercises both simple tone generation and a PCM-facing path. The small g_pcm[64] buffer is initialized during graphics/game bootstrap.
Audio here is functional integration rather than a full mixer or asset-streaming engine.
Why Mine Chris belongs in the OS documentation¶
Mine Chris crosses many ChrisOS subsystem boundaries in one executable:
input -> game state -> simulation -> voxel mutation
|
v
camera / geometry
|
v
graphics
ChrisFS <-> save data audio <- gameplay events
A kernel or runtime feature can appear correct in isolation and still fail when combined with input capture, continuous simulation, filesystem calls, rendering and audio. A game creates sustained cross-subsystem pressure that small unit demonstrations do not.
Current limitations¶
The reviewed revision uses a fixed 16-actor pool, a finite authored voxel region, small hard-coded AI state machines, direct numeric input bindings, fixed inventory arrays and a compact non-versioned save format. The source does not establish networking, multiplayer, streaming terrain, a general ECS, sophisticated pathfinding or complete persistence of arbitrary world mutations.
These limits are part of what makes Mine Chris useful pedagogically: the complete path from input to simulation to rendering remains small enough to inspect while still exercising a substantial portion of the ChrisOS application stack.