acdream/docs/research/2026-07-25-slice-i4-flat-bsp-differential.md
Erik f7ff9f4eea feat(physics): add differential flat BSP traversal
Port every current containment, overlap, walkable, and six-path moving-collision query to immutable integer-indexed assets behind a graph-authoritative referee. Exact synthetic, installed-DAT, complete-resolver, and zero-allocation gates prove bit-identical behavior before connected dual publication.

Co-authored-by: OpenAI Codex <codex@openai.com>
2026-07-25 15:47:58 +02:00

3.7 KiB

Slice I4 - differential flat BSP traversal

Date: 2026-07-25

Scope: Modern Runtime Slice I4 only

Behavioral boundary: the new integer-indexed traversal is a shadow implementation. The parsed-DAT graph remains production-authoritative until the Slice I5 connected shadow gate and Slice I6 cutover.

Result

FlatBspQuery now ports every collision entry point used by the current runtime over immutable, integer-indexed nodes and polygon ranges:

  • point-in-cell;
  • sphere/cell overlap;
  • static sphere/polygon overlap;
  • swept sphere/polygon time-of-impact;
  • walkable polygon selection;
  • solid and solid-polygon traversal;
  • the complete six-path moving-collision dispatcher.

The port preserves retail's traversal order, strict comparisons, early returns, and mutable query state. The positive child remains first where retail visits it first; the negative child observes every valid-sphere, contact, path, slide, and candidate mutation made by the positive child. Only BSPQuery.PolygonHitsSpherePrecise, which is independent of graph storage, is shared with the existing graph oracle.

CollisionTraversal is the narrow temporary referee seam. Production starts in Graph mode. Tests can run a cloned complete resolver in Flat mode, and a missing flat asset fails explicitly instead of falling back to the graph. Slice I6 removes this representation switch after connected acceptance.

Retail oracle

The implementation follows the consolidated pseudocode and boundary table in 2026-07-25-slice-i-collision-layout-oracle.md, including:

  • BSPTREE::find_collisions at 0x0053A440;
  • BSPNODE::point_inside_cell_bsp at 0x0053C1F0;
  • BSPNODE::sphere_intersects_cell_bsp at 0x0053C260;
  • BSPNODE::sphere_intersects_poly at 0x0053CA30;
  • BSPNODE::sphere_intersects_solid at 0x0053CAF0;
  • BSPNODE::find_walkable at 0x0053CC80;
  • BSPNODE::sphere_intersects_solid_poly at 0x0053CD50;
  • BSPLEAF::find_walkable at 0x0053D6F0.

The same oracle records the cross-checks against ACE master 65f092... and Chorizite DatReaderWriter c535987.... Retail remains the authority where those references differ.

Differential evidence

The referee compares scalar results and all stateful outputs by exact float bits. It covers selected polygons, vectors, planes, path state, collision and object flags, contact-plane writes, final ResolveResult, persistent body state, and full cell membership.

Gate Executions Result
Null, on-plane, radius-equality, equal-candidate, multi-polygon, and deep-tree fixtures 4 focused fixtures 0 mismatches
Static and swept overlap randomized sweep 10,000 paired cases 0 mismatches
Walkable randomized sweep 5,000 paired cases 0 mismatches
Six dispatcher paths 6 complete transition fixtures 0 mismatches
Installed-DAT sweep across 0x8A02016E, 0x8A02017A, and 0xA9B4013F 7,500 randomized cases 0 mismatches
Complete graph/flat resolver sequences 1,200 frames 0 mismatches
Warmed flat traversal 10,000 iterations 0 managed bytes

The installed-DAT gate randomizes points, spheres, movement, insert paths, orientations, scale, and boundary values. No tolerance band is used.

Verification

  • focused differential tests: 13 passed;
  • complete Core suite: 3,276 passed / 2 skipped;
  • git diff --check: no whitespace errors;
  • full Release build: passed;
  • complete Release suite: 8,384 passed / 5 skipped.

No divergence-register row changes are required. This slice changes the storage representation exercised by the referee, not production gameplay behavior. Slice I5 next publishes the prepared flat assets alongside the current graph under one landblock generation and runs the connected shadow gate.