A step onto an occupied tile is now an attack: the geometry rule is checked
against terrain only and the target tile decides between move and bump.
Entities carry an attack stat; at zero hp they are removed. The sim reports
Attacked/Died through an event queue the game drains after every movement
window — the seam for sound, log, camera effects and spawns. Click-to-move
treats an occupied goal as a target but detours around entities in the way;
the player's death ends the game.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The camera target was the sim tile, which jumps 8 px per movement window,
and the follow was a constant-speed chase that stopped abruptly. Now the
target is the render-side lerp position and the camera closes the gap
exponentially, so it accelerates and settles smoothly. Also spawns the
first NPC and switches the game to World::blocked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The 64-entry per-chunk palette was a wire-format artifact and capped a chunk
at 64 distinct tiles. A Chunk is now Box<[u16; 1024]> with flags derived from
the id on lookup — the same layout a binary on-disk format would use.
Map path becomes the first CLI argument; assets/map_large is a generated
256×256 stress map (loads in ~0.5 ms release). The snapshot test takes
SNAPSHOT_MAP.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pbio moves to git.bnd.wtf/irrlicht/pbio.git branch truecolor16: the
framebuffer is now RGB565 u16, no palette. Assets are loaded from PNG via
the png crate and quantized to RGB565 on load; transparency comes from the
alpha channel as a per-tile opacity mask, so any color (black included) can
be opaque. The TGA loader and the palette-order fragility are gone.
overworld.png is the unmodified Mini-Medieval Overworld sheet (same 24-column
layout as the old TGA, so map tile ids are unchanged); entities.png holds the
player sprite extracted from the old entities.tga.
Adds an ignored snapshot test that renders the first frame headlessly to a
PNG for eyeballing the renderer without a window.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The client becomes the game: it owns a Sim instance and advances it with a
fixed-timestep accumulator (24 Hz ticks, rendering at frame rate). Rendering,
pathfinding and collision read the World directly instead of a chunk cache.
Sim::pending (window slot maps, late rule, horizon) is replaced by one intent
per entity for the next movement window — set_action replaces, executing the
window consumes. The whole client prediction/reconciliation machinery
(tick estimation, RTT lead, retraction, replay) is gone with the latency it
was built for; click-to-move now syncs the route against the sim position
after every window.
Removed: server, netsim, shared (wire types), client/net.rs. client renamed
to game. Headless tests cover the intent model.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>