File size: 7,036 Bytes
537a3ef 3b0aae3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | # Game-QVM friction policies and velocity composition
RE-433–435 / F-184–186. [qvm-friction.json](qvm-friction.json) retains helper39988, the friction prefix of helper45461, nine file-backed initialized words, 342 shared-friction probes, 24 mode-prefix probes and eighteen staged caller compositions. Reproduce with `python3 scripts/analyze_qvm_friction.py`; verify with `python3 scripts/test_qvm_friction.py`.
This follows [command scale and acceleration](QVM_ACCELERATION.md). Results are bounded synthetic instruction evaluations; no complete QVM, original executable, native callee or collision/physics system executes. Square-root returns are supplied from ordinary finite math. The staged pipeline transfers only evaluated friction velocity into the previous partial caller. It supplies the identity basis, command/button/meter and timestep, and omits other state/callee/frame/collision effects.
## FRIC-001 — Initialized words and shared helper39988 (RE-433)
The collector verifies source-image bytes, file offsets and VM addresses for these words. These are an initialized image snapshot, not a proof of immutable constants or live configuration:
| VM address | Binary32 value | Observed use in these slices |
| --- | --- | --- |
| 21160 | 100 | Minimum control speed in ground-like drop |
| 21200 | 8 | Acceleration coefficient supplied to the new pipeline |
| 21208 | 4 | Ground-like/shared friction coefficient |
| 21212 | 1 | Frame-level-dependent drop coefficient |
| 21220 | 5 | Type/flag-dependent drop coefficient |
| 21224 | 3000 | Player-state flag-mask12 drop coefficient |
| 21348/21352/21356 | 0/0/0 | Vector copied by the mode-specific low-speed branch |
Helper39988 copies velocity from player-state+32/+36/+40 into a local vector. Nonzero global35023936 removes Z **only from the measured vector**, before requesting its length from target-107. The original velocity vector is not projected to a plane at this point.
If measured speed <1, it clears original X/Y velocity and returns, retaining original Z. Otherwise it accumulates drop with operation-level binary32 rounding. Ground/level/surface terminology below is provisional pending producers and consumers.
| Predicate | Term added to drop |
| --- | --- |
| Frame+212 <=1, global35023936 nonzero, global35023988 bit2 clear, player-state+12 bit64 clear | max(speed,word21160) * word21208 * dt |
| Frame+212 nonzero | speed * word21212 * float(frame+212) * dt |
| Player-state+12 mask12 nonzero | speed * word21224 * dt |
| Type at player-state+4 ==2 or player-state+220 bit2048 | speed * word21220 * dt |
After those additions, player-state+104 bit1 **replaces** accumulated drop with `dt *1000 * binary32(0.15)`; it does not add another term. The slice then computes `ratio = max(speed-drop,0)/speed` and scales all three original velocity components by the ratio. Thus a planar measured speed can determine scaling of original vertical velocity as well; the low-speed return is the separate exception described above.
342 probes vary supplied vectors, norm mode, frame levels, surface/PS bits, types, special flags, replacement flag and timesteps0/0.016/0.5. Independent rounded formulas verify measured sqrt requests, every drop/ratio/final vector, low-horizontal-speed vertical retention and replacement behavior. Numeric fields/flags, negative or unusual configuration ranges, callbacks and runtime behavior remain open.
## FRIC-002 — Mode-specific helper45461 prefix (RE-434)
The prefix45462–45647 first writes38 to player-state+164. It measures full XYZ speed, without the shared helper's optional planar measurement. A speed below1 copies the file-backed zero vector into **all three** velocity components, even when supplied dt is zero.
Other paths use an effective coefficient of `word21208 *1.5` (six under this image snapshot). Drop is `max(speed,word21160) * effective_coefficient *dt`, with rounding after each operation. It scales velocity by `max(speed-drop,0)/speed`.
This differs from shared helper39988 in norm selection, low-speed Z treatment and coefficient, and does not include its other drop terms/replacement branch. The two policies must not be merged into a single inferred friction rule.
24 probes cover tiny/exact-one/mixed/high/signed vectors with three timesteps. Independent full-norm and rounded drop/ratio formulas verify all velocity words, the+164 write and the square-root request. Earlier configuration/lifecycle and the field38 meaning remain unverified.
## FRIC-003 — Velocity-only bridge into the partial caller (RE-435)
Eighteen compositions evaluate the mode-specific friction prefix, then transfer its three velocity words into the prior helper45461 partial caller. That caller evaluates command scaling, wish-vector construction/normalization, helper40275 acceleration and unconditional position-tail updates. Source-image coefficient8 replaces the earlier report's explicitly supplied example coefficient10 in these new fixtures; the previous report retains its original defaults and scope.
The new fixtures cover three initial velocity vectors, zero/axis/diagonal commands and dt0.016/0.5. They use button256 and supplied meter11, identity basis and initial position10/20/30. Larger timestep probes are synthetic arithmetic cases, not asserted reachable within the recovered scheduler caps. Tests independently verify friction output, exact velocity handoff, coefficient/timestep propagation, acceleration and final position words.
Only velocity is transferred between the separately evaluated stages. This is not a full helper45461 call-frame composition: its other state words, earlier/callee effects, native sqrt/basis generation, collision and runtime context remain omitted. The shared partial-caller helper now accepts coefficient and dt parameters with unchanged defaults, preserving earlier report output.
## Validation and remaining work
Eight independent tests verify file bytes/values/provenance, all shared drop/ratio/vector outputs and sqrt requests, low-speed Z retention, replacement rather than addition, full-norm mode behavior/field write, staged velocity/acceleration/position propagation and explicit scope/boundaries. Prior report regeneration checks protect the partial caller's default behavior.
RE-432 remains open for complete policy/native/runtime recovery. RE-436 must trace coefficient/global writers and live configuration, ground/level/surface/PS-bit/type producers and legal ranges, native sqrt ABI, other callers' friction combinations, complete basis/frame/state/callee transfer and collision/simulation effects, then validate full mode/step/gameplay/macOS/Linux before Rust/Bevy/Solari compatibility claims. Packet/entity/player/snapshot/rendering milestones remain open.
Follow-up: [ground/content producers](QVM_GROUND.md) connects content sampling and a copied trace to level/walk/surface inputs, then bridges scalar outputs into friction. Native callbacks, omitted helper effects and full collision/state/runtime validation remain open.
|