MACH//BREAK

Dev log · pre-alpha · greybox · concept boards

Experiments

Every consequential change is an experiment: hypothesis, implementation, telemetry, result, keep or remove. This page is generated from those records, so it is as honest as the numbers in it.

Generated 2026-08-29 by website/build_updates.py from the project's experiment log and milestone notes. Internal engineering shorthand is translated to in-game vocabulary; anything that cannot be published verbatim is left out rather than paraphrased.

Gameplay experiments

EXP-10 · 2026-08-29

Rally off the route, the way home by known enemies, two escorts, side intercepts, air fightingkeep

Hypothesis
EXP-9's carriers died in the enemy wave staged on their own approach; move the rallies off the routes, let carriers pick the way home by what the team knows, give them two escorts and side-intercepting chasers, and bots cap. Then (owner feedback from a live match) bots must fight and chase in the air and while gliding. Implementation (bot_brain.gd, bot_team.gd; main's EXP-11 / EXP-11b lateral jet control merged in before measuring): - Rally 90 m off the attack route, on the side with terrain cover from the enemy stand (LOS test from 2 m above it), off the stand-to-stand line, on flat ground (both rallies come out "covered" on both maps); the rally route is its own A*. - Two ways home per team (front: entry side; back door: exit side, where 75 m out is not a flank); the carrier picks at the grab and again inside 300 m of home by the known enemies (marked for us or within 150 m of a live teammate) within 80 m of the last 250 m of each way. Carriers burn the descents to 40 m/s. - Waves of four (breaker, runner, two escorts); an escort with a known enemy inside 120 m of the carrier stands 20 m out between them (one each flank of that line), shooting. - Chasers and (now) both defenders intercept 35 m off the carrier's route on their own side, ahead of it, never inside 60 m of their own rally; pursuit, interception and escort burn below 24 m/s. - Fighting: with an enemy inside 60 m a bot never holds: it strafes across the enemy's line (side swapped every 0.7 s, downhill side preferred), keeps the objective's pull, closes outside 35 m and opens inside, and jets the strafe (lateral jet control). Design-review rules: (1) lead is the intercept from target velocity and flight time (as before), aimed a touch high-side when both are airborne, and a burn for a small altitude edge over an airborne enemy; (2) energy as a state machine: engage above 40 % of the tank in 0.3 s bursts, panic below 15 % (jets off, glide for speed, no fire) until back above 40 %; (3) disengage on geometry: panic energy, the enemy 6 m+ higher and closing at 5 m/s while we are under 40 %, or a second enemy inside 60 m; exit downhill on a glide out of their cone, no fire. - Tick cost: the terrain LOS test per target is cached 5 ticks, and a bot thinks every other tick (repeating its input on the off tick) except in the precision moments (run-in, inside a ring, the Matches (16 bots, 240 s, four in parallel). EXP-9 final = the "before" row. the ring) and 2/2 on Tallow. Time to the rally 45-73 s. are in range (28 / 27; 12.3 / 11.2 m/s against the 12 m/s target, one seed short); the cap targets still fails: pursuing by air (10-35 m away): the air pursuit works, on both sides, and a Strider that has just burned out of the ring (energy 9-12) has nothing left for the duel. The carrier that got clear capped after a 94 s trip. - Tallow: all waves grab and clear (4/4 per match) but only one carrier per match gets up its home ramp; the others still meet the enemy wave at 60-80 m (the 90 m rally offset sits inside the 100 m fire range) or run out of energy on the pad blend. Kills stay under 12 because the teams meet only there and at the stands; combat speed is dragged down by the defenders holding on the stand (25-31 % of the combat samples are under 4 m/s, almost all of them stand and shelf defenders with an attacker at 40-60 m).
Decision
keep (caps from 0 to 1 per match everywhere, tick cost under target, no regressions). Next: the carrier's energy budget through the gate (arrive with 40+ and take the exit on a glide, not a burn) so it can duel the pursuit; a defender who moves on the stand instead of holding a point; the rally 120+ m off the route on Tallow.

16 lines of internal measurement detail omitted from this entry.

EXP-11b · 2026-08-29

Lateral share numbers from the design review

Grok: keep the per-frame lateral lever, no free air-strafe; Strider 1.10 / Ranger 0.72 / Bulwark 0.48; shape by speed (full below 35 m/s, easing to a floor of 0.75 / 0.55 / 0.35 at 75 m/s); ticks 0–2 off the ground ×0.4 to stop hop wobble; lateral thrust costs the normal jet energy. Applied as lateralJetControl / lateralJetFloor. A/B for the next playtest: (A) these numbers, (B) Strider 1.0 with a 10% lateral energy discount.

EXP-11 · 2026-08-29

Lateral jet control per frame (first deliberate departure from the reference)

Feedback (Chris, after winning a match on Tallow): a Strider needs too much effort to move left/right with the jets; heavier frames may stay stiff.

Hypothesis
the reference vectoring (horizontal share tapered by forward speed, vertical-only for 9 ticks after leaving the ground) gives no lateral authority at speed.
Implementation
the part of the move input perpendicular to the velocity gets the frame's horizontal share × lateralJetControl (Strider 1.0, Ranger 0.7, Bulwark 0.5) from the 3rd tick off the ground and is not tapered by forward speed; the forward part is unchanged. Tests: movement_acceptance M7 lateral cases; reference traces unchanged (jet_forward 2.35, Glide 1.73, run_up 0.81 — forward-only inputs).
Decision
ship for the next playtest; tune the three numbers on feel.

EXP-9 · 2026-08-29

Grab at speed, glide only along the fall line, the way home by the rampkeep

Hypothesis
EXP-8's two diagnosed causes (the glide rule slides bots off every traverse; the runner arrives on foot and spends 5 s at 5-10 m from two defenders) are what stops caps; fix them, then make the defenders beatable, and bots cap. Implementation (bot_brain.gd, bot_nav.gd, bot_team.gd, new harness tests/grab_check.gd; mach_world.gd, mach_movement.gd, the map generator and the ring defenders + 1 chaser + 5 attackers): - Glide (jump held) only when the slope under the bot runs along the direction of travel and down (gradient from normal_at, dot with the move direction > 0.6); flats as before; never on a traverse or a climb (run + burn with a 20/6 reserve). A glide has no steering at all (no traction, no air control without jets), so it is also released whenever the velocity is more than ~25 degrees off the wanted heading. Routes price sidehill cells (bot_nav.gd: +2x by the steepness measured over +-24 m), so they keep ~24 m inside bench edges. - Grab at speed: the runner lines up on the entry axis 60 m out (Tallow: 25 m past the ramp foot, 79 m), then the run-in owns the controls: along the axis with jet-vectored lateral tracking (run key when > 2.5 m off, > 1 m inside 35 m), glide keeps the speed, jets pulse below 22 m/s and lift straight through at speed; 90 degrees apart (Tallow) run via a turn point 3 m out on the exit axis. Committed inside 40 m (no retreat to the line-up point). Exit gate, 110 m out, then home. - Waves: the runner goes when the wave launches (no breaker stage; it never got to the Tallow ring in 40 s), holds only while >= 2 healthy enemies are within 25 m of the stand (30 s at most); a wave launches only for a free flag; the wave's escort leads the carrier by 25 m. - Found on the way, each worth more than the headline changes: (1) bots impulse-jumped themselves to 26 % health (a self-impulse is 0.5 x the frame's 1.5 Impulse scale = 0.74) so every attacker arrived at the stand one hit from death: off. (2) Nearest-waypoint pursuit steered bots back to the waypoint behind them on every slope (breakers hunted between two route points on the pad blend for 40 s): the route index is monotonic now. (3) The 16 m A* never sees an 8 m ramp: a route home ended against the 12 m bunker wall; the escape route now ends line-up (20 m before the foot) → foot → gate → stand with damped axis tracking, and comes in by the exit-side ramp when the ground 75 m out there is not a flank (Tallow team 2). (4) Rally points on a slope (both Tallow rallies sat on the bar's flank; attackers slid 30-66 m to the floor) are now scored by steepness. (5) Carriers crawled the Tallow floor at 12 m/s on a full tank, saving it for a home climb that is a runnable ramp: they burn below 24 m/s the whole way. (6) A 55 degree step read as a wall; the pad blend is runnable: 63 degrees. (7) Stand defender chases only inside 40 m; the shelf one never. Harness (godot --headless --path game -s res://tests/grab_check.gd -- --map=M --team=T [--defenders=2] [--runs=N] [--trace]: one attacker dropped at its rally with the wave already running, traced to the After: Matches (16 bots, 240 s, --seed=N, four in parallel; "before" is EXP-8's final brain on this branch): Tallow 55-77 s (target 60 s; Tallow seed 2's team 1 spawns furthest from its rally). at the end; Tallow 0), and Tallow kills (7-9) are below 20; grabs and clears are up a lot (Tallow: go through the ring in 1-2 s and mostly unhurt). What still fails, from the carry endings in the telemetry (x,y,z are Godot): - Tallow: every carrier dies 90-170 m from home, at 5-25 m/s, with 2-3 enemy attackers 13-60 m away: the enemy's rally point is 120-180 m from our stand on the attack route, which is our way home, so the carrier runs into the next enemy wave staging on our own pad approach (seed 1: bot 1003 died 88 m from home with 1006/1008/1012 at 49-63 m; bot 1010 113 m from home with three at 21-37 m). The exit-side route home (75 m back door) does not clear that group on team 1's side, where the exit ramp faces a 45 degree flank. The escort leads by 25 m but one Strider does not stop three. home) and the stand defender still gets its one point-blank shot at the gate (3-4 "runner died" per match, always inside 2 s of the grab). - Kills on Tallow stay under 10: the teams only meet at the stands and at the rally-side approach. above the 4 ms target; the defenders' 120 m scans and the per-tick normal_at for the glide rule are the additions since EXP-8.
Decision
keep (grabs, clears, route and ramp fixes are strictly better and combat_check holds); caps stay open. Next: put the rally 60-80 m off the attack route (it is the enemy carrier's route home), route a carrier around a staged enemy group, and give the carrier a two-escort wave; on

28 lines of internal measurement detail omitted from this entry.

EXP-8 · 2026-08-29

Bot team coordinator: waves through the ring (Spot → Close → Soften → Secure)keep

Hypothesis
EXP-7's solo grabbers die to two defenders within seconds; a team that spots, closes together, softens the defence and secures the exit should cap. Implementation (bot_team.gd new, bot_brain.gd): - Coordinator per team (one object per world/team, updated once per tick by the first bot that thinks). Roles are dealt at every spawn from live teammates only: 2 defenders (heavy frames first), 1 chaser, the rest attackers. A rally point is the attack route's waypoint 120–180 m short of the enemy stand. - Waves. When ≥ 2 attackers are at the rally (30 m) with > 60 % energy and > 60 % health (after 10 s, whoever is there; a third attacker is waited for up to 15 s as escort) a wave launches: the healthiest is the runner, the next one with impulse rounds the breaker, the rest escorts. Breaker: stands off the ring's entry gap at 16 m, strafes, holds the spot key ("spot": true, marks the nearest defender for the team; marked enemies count 30 m nearer in everyone's target choice) and shells the ring. Runner: closes along the route to 100 m, holds until 2 s after the breaker is inside 50 m (or dead), then enters gate → centre → flag and leaves through the far gap; escorts trail the runner by 20 m; once the flag is up, every attacker within 200 m escorts the carrier. Between waves attackers regroup at the rally; an attacker with an empty launcher walks back to a station. Waves end on a death, a grab that clears 120 m, or 40 s. - Ring geometry from terrain.struct_meta["rings"] (Godot vectors): entry gap = the gap nearest the enemy bearing, exit = the other, shelf = the tower lip. Tallow bunkers add ramp feet (probed along the gap axes: a smooth drop of > 10 m within 80 m) so the way up is ramp foot → gate → centre. Canonical team routes: attack_path (stand → stand, its tail replaced by foot/gate/centre), rally_path (up to the rally), escape_path (centre → exit gap → 70 m out → A* home); a bot that strays > 100 m rejoins the route at its nearest waypoint instead of re-planning from a snapped origin. - Defenders: one on the stand (patrol inside the ring, facing the entry gap), the second on the shelf; both engage at 120 m (fire inside 100 m) and pre-aim at marked enemies they cannot see; the stand defender chases a carrier only inside 80 m. Chaser: v3 route-ahead intercept, and body-blocks the exit gap while an intruder is inside the ring and the chaser is within 60 m of home. - Nav fixes found on the way: route goals other than the stands were snapped to a 160 m grid, so bots parked on a snapped route end (a roof, a pocket) 80 m from their target (_route(..., exact_goal)); walls are now a step of > 2.2 m within 1.5 m, so Tallow's 45° flanks are climbed (runnable, jet-assisted) instead of waited out as walls; arrival at a ring gate is on foot (the 6 m gap cannot be taken at 26 m/s airborne). Telemetry (16 bots, 240 s, --server --bots=16 --duration=240 --seed=N --telemetry; the "4x" rows ran four matches in parallel on one machine, which inflates the tick times by ~0.5 ms): attackers at the rally with full tanks), the breaker reaches the entry gap and holds it for 10–30 s, the runner enters on foot through gate → centre, grabs, and leaves through the far gap; the escort trails it. Grabs per match (a grab is about three flag events) are 1–4, as in v3, waves carry spot marks (58–118 mark events per match, was 0 from bots), kills sit at 28–37 (target 30–80: met), and the tick cost is 3.3–3.9 ms single-run (v3: 3.25; the target of < 3.5 is marginal, the extra is the defenders' 120 m target scans and per-tick mark lookups; the coordinator itself is a few tens of microseconds).
Result
acceptance for caps (≥ 3) is not met on either map. Where it fails: defenders (kill <runner> by <defender> at the stand in every wave of both seeds). The ring is 8 m across with 6 m gaps; a runner on foot spends ~5 s at 5–10 m from a defender who kills a Strider in two impulse hits. Softening does not happen: the breaker at the gap trades with defenders that have 1.1–1.32 damage frames and the shelf, so the "defence soft" go condition almost always falls back to the 12 s timer. The one carrier that got 80 m out (seed 2, t5759) was killed by a defender firing at range, which is the posture the task asked for. Two defenders in a ring beat any wave of Striders that must enter on foot; the next lever is not coordination but the ring's geometry or the defenders' frames/ammo (an experiment on base_ring.py: wider gaps or a lower wall so the runner can take the gap at speed). - Tallow: attackers reach the rally in 50–200 s, so 1–4 waves per match. The route from spawn to the enemy bench is ~950 m with two 45° flanks; bots that fall off the route re-plan from a snapped origin and A* with a 6x slope penalty sends them 900 m along the valley floor instead of 100 m up the flank (bot 1007, t3s2: within 36 m of the rally, then a 950 m loop east). The rally now follows the canonical attack route and strays rejoin it, which cut the loops but the flank climb itself still costs a tank of energy per attempt. Kills 14–18 (below 30): the teams rarely meet. for 76 s per match); no change since EXP-7.
Decision
keep the coordinator and the nav fixes (grabs and marks up, kills in range, no regressions in combat_check on either map); caps remain open. Next experiment: ring geometry (EXP-9), then re-measure. ### EXP-8 follow-up · Tallow reachability (rings regenerated with 10 m gaps on main) Changes: A* uphill cost capped (bot_nav.gd: d * (1 + min(slope, 1.5) * 1.5), was 1 + 6*slope + 8 above 0.9, which priced a 100 m flank above a 900 m valley detour; the stand-to-stand route is now 1034 m for a 926 m straight line and runs along the bench); staged ramp approach (to the ramp foot, then straight up the 8 m axis to the gate, back to the foot when 5 m off the axis; 6 m route lookahead inside 110 m of a ramped stand); grab at speed when lined up with the entry axis (jets on, no on-foot arrival), carrier burst to 60 m out; flank climbs burn with a 20/6 energy reserve instead of waiting for a 75 % tank; the coordinator logs time-to-rally and approaches (BOT_TEAM_DEBUG=1). Measured (16 bots, 240 s, four parallel processes): Not met: the 60 s time-to-rally, and no approach at all. What the traces show (bot 1006, seed 1): the canonical route leaves the bench along x = -160 for 560 m; attackers Glide or jet off the bench edge onto the 45° flank within the first 15 s, slide to the floor 200–300 m east of the route, and every re-plan from the floor to the rally (exact goal) is a fresh A* that crosses the valley floor sideways (x from +177 to -164 and back) around the bar; a bot that climbs back onto the bench slides off again. The flank is runnable in isolation (a Strider walks 90 → 170 m in 8 s in MachMovement, see the flank probe), so the loss is steering: the Glide/glide policy holds the jump key whenever the ground ahead falls away, which on a 45° flank means no traction and no turning until the floor. Map parameter, if changed: the valley flank angle is set in tools/gen_tallow_reach.py by the bench band BENCH_A0, BENCH_A1 = 360.0, 400.0 against FLOOR_HALF = 200.0 (line 164: the flank is a smoothstep over BENCH_A0 - FLOOR_HALF = 160 m for an 88 m rise, so its mid-slope is ~45°). BENCH_A0 = 460 would make it a 260 m, ~27° flank that the glide rule tolerates (EXP-1/2 hills are ≤ 30°); the bases stay where they are because the bunker pads are placed by BASE_U/BASE_A, not by the band. The alternative without a map change is a bot-side "no Glide on slopes steeper than 35°" rule plus a route that stays 30 m inside the bench edge; neither was done in this pass.

18 lines of internal measurement detail omitted from this entry.

EXP-7 · 2026-08-29

Bot brain v3 (roles, routes, stand defence, carrier escape)keep

Hypothesis
the 8v8 bot match is dead because the server deals roles by global index while teams alternate (team 1 all cappers, team 2 all defenders/chasers), bots pile into building walls and tower pockets, defenders and chasers loiter at their spawn, and carriers die inside the enemy base. Implementation (bot_brain.gd, new bot_nav.gd): roles re-dealt per team with heavier frames defending (3 cappers, 2 defenders, 2 chasers, 1 escort); A* with 4 m sub-sampled edges that prices building walls as detours, a binary-heap open list and a height cache (33/9/20/11 ms per base-to-base route, was 79/78/98/40); one route kept per bot, origins and moving goals snapped so 16 bots share cached routes; wall avoidance, height-aware waypoint choice, a progress-based stuck breaker, and a bounded "recharge, then climb" rule for unavoidable walls; defenders patrol the stand roof within 15 m facing the route's entry gap and return dropped flags; chasers intercept on the base-to-base route ahead of the carrier; escort trails the carrier, or leads the capper in at the enemy stand to draw the defenders' fire; refit at friendly stations (health < 50 % or no primary ammo, 60 s cooldown, only stations at the bot's level); carriers burn out through the back gap, save energy for the home climb, jet-cushion hard falls and jink under fire; cappers grab at speed; aim error 3 deg and 30 % lead misjudgement (the exact lead hit 41 % of Impulse Launcher shots). Telemetry (16 bots, 240 s, --server --bots=16 --duration=240 --telemetry): Intermediate v3 runs during tuning: 35 kills / 0 caps, 29 kills / 12 stand approaches, 23 kills / 1 cap, so kills sit at 18–35 by seed. Bot cost: brain 2.1 ms/tick of which nav 0.3 ms (was 8.3 / 6.1 before the route fixes). All 16 bots leave their spawn point inside 5 s in every run (min displacement 3–10 m; a defender that spawns at its own stand stays by design).
Result
loitering at spawn is gone and the roof defence, interception and refits work as specified, but the acceptance targets for caps (>= 3) and kills (30–80) are not met, and two bots still average under 8 m/s: - Caps. Both stands sit on a ground-level plateau between two 17 m blocks, open on two sides; the route enters through one gap and both defenders patrol within 15 m of the stand facing it. Cappers now reach the stand 10–19 times a match (was 1–2) but every grabber dies on the plateau within 1–9 s of the grab, at 0–10 m from a defender, having arrived with 60–90 % damage (Impulse hits, 0.385 each; two kill a Strider). A solo capper cannot survive two Vector Cannon at 10 m for the ~5 s a grab takes. The escort-leads tactic did not draw enough fire. Next: coordinated waves (cappers rally and enter together), or a defender posture that engages from range instead of point-blank. - Kills. Fewer point-blank executions of runners, more fire at range with 3 deg aim error; 18–35 by seed. - Speed. The Bulwark (7.5 m/s run cap) and Ranger defenders average 3–7 m/s: a heavy patrolling a 15 m circle cannot average 8 m/s, and one heavy chaser per match is still trapped in the pocket south of the team-2 tower (engine 56, 264) after spawning on the tower roof and falling in: its damaged frame recharges at ~0.3 energy/s, so it cannot jet out and the pocket's only exit is behind it. Next: move the tower spawn off the roof or pathfind the pocket exit at 8 m resolution.
Decision
keep v3 (strictly better traffic and no spawn loitering); caps need the coordination pass above.

5 lines of internal measurement detail omitted from this entry.

EXP-6 · 2026-08-29

Lag compensation for hitscan and meleekeep

Implementation
the server keeps 16 ticks (512 ms) of player positions; each input carries the server tick the client was rendering remote players at (render delay 4 ticks); Lance and Shock Lance rays test targets at that tick. Projectiles are not rewound (they are visible and lead-able).
Test
a target moving 15 m/s hit at its 190 ms-old position with rewind, missed without. Remote players are extrapolated up to 3 ticks along their last velocity when a snapshot is late; corrections above 20 m are classified as teleports (respawns), not prediction error.
Decision
keep; fairness cap = 512 ms.

EXP-5 · 2026-08-29

Redundant inputskeep

Hypothesis
residual error at 100–150 ms with 2–3% loss is lost input packets starving the queue.
Implementation
each input packet carries the last 4 [seq, input] pairs; the server queues unseen seqs.
Telemetry
16p/32p at 100 ms + 2% loss + 20 ms jitter — movement p95 0.77 / 1.20 m, 38 rubber-bands/min → 0.000 m, 0.7/min.
Decision
keep. Bandwidth per peer measured 11 KB/s (16p) / 20 KB/s (32p), snapshots 830 B mean.

EXP-4 · 2026-08-29

Server input queue instead of latest-input-per-tickkeep

Hypothesis
prediction error under jitter comes from the server duplicating/dropping client inputs while the client re-simulates exactly one tick per input.
Implementation
per-client FIFO consumed one input per tick (6-tick cap, repeat last when starved); weapon state machine replicated in the per-recipient block and re-run for in-flight inputs during reconciliation.
Telemetry
bench cell 4 clients, 20 ms RTT, 5 ms jitter — movement correction p95 1.2 m / 67 rubberbands per min → 0.000 m / 0; local bot brawl mean 0.165 → 0.001 m.
Decision
keep. ADR-3 amended.

EXP-3 · 2026-08-28

Predicted weapon fire and self-impulsekeep

Hypothesis
impulse jump snap-back is the largest visible correction.
Implementation
local single-player world for forward prediction; impulses logged by input seq and re-applied on reconciliation.
Telemetry
bot brawl with periodic impulse jump, mean correction 11.4 cm → 7.2 cm.
Decision
keep.

EXP-2 · 2026-08-28

Ground-impact damage only after real airtimekeep

Hypothesis
hop-cycle landings on 8 m heightfield creases register as impacts.
Implementation
impact damage requires ≥ 8 ticks airborne before landing plus the 45 m/s normal-speed threshold.
Result
complaint gone in the same playtest.
Decision
keep; revisit when terrain collision becomes triangle-exact.

EXP-1 · 2026-08-28

Ground contact while climbingkeep

Hypothesis
forward drive felt weak on hills because contact was dropped when moving upward.
Implementation
contact = at surface and not moving away along the surface normal.
Telemetry
reference uphill run trace (run_up): error 13.5 → 0.8 m/s; live playtest.
Result
"much better" (Chris).
Decision
keep.

Milestone notes

Milestone notes · 2026-08-28

Phase 2

  • Internet net hardening — after the first friend playtest (binary snapshots and input validation already in). Predicted weapon fire, local projectiles and self-impulses DONE 2026-08-28: the client runs a single-player MachWorld forward (same code as the server), logs each predicted self-impulse by input seq and re-applies it during reconciliation; server projectiles/effects owned by the local player are hidden. Bot brawl with periodic impulse jump: mean correction 11.4 cm → 7.2 cm (--no-predict-fire for the baseline). Still to do: delta/interest snapshots, Vector Cannon lag compensation, jitter buffer, remote extrapolation on loss.
  • Vehicles — not before a year.

6 blocks of internal measurement detail omitted from this note.

Milestone notes · 2026-08-28

Phase 1: movement fit

Pipeline

  • game/tests/replay_drive.gd: replays each segment through MachMovement + MachTerrain with the recorded inputs and prints RMSE of horizontal speed, vy, energy, position.

Known gaps

  • Move direction in the replay must come from the teleport yaw, not peak velocity.
  • Hop phase: vy rmse 5-8 on hop segments is timing drift of the hop cycle, not amplitude.

Next

  • Re-check vy handling on landing (jump_rest / jet_vertical vy error is on touchdown).
  • Then medium/heavy captures (same drive program, frame switch server-side).

Combat and BreakFlag (MachWorld, 2026-08-28)

Measured in the sim: standing light impulse jump = +47 m/s, 38 m peak, 0.5 damage (76% of 0.66); Impulse Launcher on a light at 40 m = 0.5 damage (survives at 24%), pushed 22 m/s; 7 Vector Cannon shots in 1.5 s, 0.101 per hit.

Still approximate:

  • Explosion point is the projectile hit point (no projectile radius offset); projectiles start at the eye, not the weapon mount; Vector Cannon spread is a two-axis random rotation.
  • calcExplosionCoverage reduced to a terrain line-of-sight test (no interiors yet).
  • The shooter is skipped for activateDelayMS (200 ms) after firing.
  • Flags sit on the terrain at the mission x,y (no base structures in the slice).
  • Team review 2026-08-28 reconciled in research/2026-08-28-phase1-review-reconciled.md.

Networking (Phase 1 slice)

net.gd (RPC endpoint), net_server.gd (authoritative MachWorld, latest-input-per-tick, full snapshot every tick via ENet unreliable-ordered), net_client.gd (32 ms input sampling, local prediction with the same MachMovement, re-simulation of unacked inputs on each snapshot, remote-player interpolation over 2 ticks). Solo play = listen server with the local client short-circuited. tests/net_check.sh runs 15 bots + 1 scripted client headless and reports server tick cost and client correction error. Snapshots are a binary quantised codec (snapshot_codec.gd, ~1 KB for 16 players + 40 projectiles, stale ticks dropped); client inputs are validated (MachServer.sanitize_input); remote entities render 4 ticks behind from a tick-indexed buffer. Not predicted yet: weapon fire and self-impulses (impulse jump arrive as corrections; 3.7 cm mean over a 40 s bot match on LAN).

20 blocks of internal measurement detail omitted from this note.