# Weak-side defensive winger coverage — 2026-10-28-r4

jdc approved a first AI improvement, with a backup before changes. This is a
small native positioning change: it does not replace the game's whole AI.

## In play

On **Hard** only (difficulty 1 at F07A), when an opponent carries deep along one side, the AI winger on the
other side drops into the low slot. He covers a dangerous far-side receiver
from slightly inside and goal-side, with a short velocity-based look-ahead.
Without an eligible receiver he protects the weak post/low slot. The puck-side
winger keeps his native job. This applies equally to AI teammates and opponents.

The hook first requires Hard, then an opposing carrier, puck |X| 56..144, and defensive depth
-296..-160 in the defending team's attack coordinates. It scans five opposing
skaters, excluding the goalkeeper, puck carrier, unavailable/boxed/empty slots.
Receivers must be on the far side, |X| 16..88 and depth -260..-150. Danger cost:
`2*abs(predictedDepth+224)+abs(predictedX)`. Prediction adds velocity >>9;
target X is 3/4 of predicted X, clamped on the wing's side to |X| 16..64;
target depth is predicted depth minus 12, clamped -236..-180. Fallback is X ±32,
depth -216. Conversion back to world Y respects the player's native end flag.

**Normal and Easy retain native positioning.** Humans, animation-locked/unavailable actors, whistles, replay views, shootouts,
loose/invalid puck, own-team possession, central/up-ice carries, centers,
defenders and goalkeepers retain the native behavior. No ratings, timers,
speed, RNG, goalie reach, shot odds, controls or save layout are changed.
Native assignment selection, steering, skating and checking still run.

## Code and rollback

- `experimental/ai_defence.s`: 482-byte 68000 routine at ROM **2D8400**.
- `experimental/ai_defence.py`: asserted free-space and original-opcode installer.
- Native **D086** replaces `LEA CF98(pc),A0; MOVE.W puckX,D2` with JSR + NOP.
  D0/D1 are the native target, A3 the skater; D3-D7/A1-A3 are preserved,
  A0 and D2 reproduce the displaced native instructions. No new RAM.
- `build_test.py --no-ai-defence --version 2026-10-28-r3` reproduces the exact
  preceding r3 ROM. The normal build includes the improvement.
- Requested verified backup: private
  `~/.config/retroarch/roms/claude/work/ai-improvement-20261028/backup-r3.zip`.
  It contains the preceding ROM, sources, documents/site and matching local
  controls/save files present at backup time, with MANIFEST.json. SHA256:
  `47afae7826970f2dd4b4e025eb98c01e9264ff169f40ffe5b7b61bcbd5b37f81`.
  Keep private; do not add duplicate current downloads or Bodin entries.

## Verification

The first all-difficulty prototype passed its 20-check gate privately. Before
release jdc requested connecting the new behavior to Hard. A new Hard-only
build and full gate supersede that prototype; it was never installed publicly.

Paired baseline r3 SHA256:
`c0bb6213131a4ce2daf763a3bfa06b740fe9a81e8dc252b6e2b32b78e0159738`.
Evidence: private `work/ai-improvement-20261028/`.

- **44 paired native target/guard cases** call the actual D00C wing-target
  path, observing only the final skateto arguments. Both teams, both ends,
  both wings, receiver motion/selection/exclusion, boundaries, human ownership,
  stopped/special scenes, preserved registers and unchanged RNG are checked.
- **19 paired live skating scenarios** run the actual game with idle-pad
  carrier/receiver and free defending AI. Nine initial setup frames settle
  the captured CPU/input state; the next 140 frames run without repeated
  position/velocity resets. Contacts and job changes remain native.
- Comparisons use identical elapsed frames 10..60 while both builds retain
  the original carrier and defensive-wing assignment. All 11 Hard cases improve
  mean distance to the receiver: **13.14..34.30 rink units**, average **26.82**.
  Both teams/ends/sides on Hard and all four period lengths. Eight paired
  Normal/Easy controls keep exactly the baseline mean coverage distance.
  The difficulty setting uses the captured native actors; this is not a full
  fresh-match difficulty/roster balance experiment.
- Setup initially inherited stale captured movement/one-player input state;
  fixing two-human assignment and settling the setup removed that artifact.
  Those failed fixture attempts are retained privately, not counted as passes.
- This establishes targeted positioning/approach, not a guaranteed win-rate,
  interception-rate or scoring improvement. No manual controller playtest is
  claimed; native checking/collisions can move receivers after setup.

The earlier HUD fixture failed because a timing-dependent high shot hit the
crossbar, not because the panel disappeared. Its close/open-net replacement
passes all eight cases (157 VRAM checks) on both r3 and r4; native shot/goal
physics and replay assertions are retained. Failed artifacts are kept privately.

The shared release gate now also requires these two AI suites; see TEST_PLAN.md
and QA_STATUS.json for the exact current-ROM report. Rebuilds with and without
the hook match their intended snapshots. The guarded r3-to-r4 diff is **483
bytes**, limited to the target hook, new routine and version/header checksum.
The IPS reconstructs the complete ROM from original v5.1W.

Release SHA256:
`e6c727618a252e962e5d120a7f945c25e2634f2a396382c90766386a2fe81c97`;
CRC32 **975E5D61**. Standard replacement/fresh-progress policy applies; keep
controller mappings. The private backup remains available for rollback.

## Research attribution

Native wing roles, target selection, attack direction, controller flags,
object layout and skating were checked against the actual v5.1W instructions
and [abdulahmad / NHL94Genesis](https://github.com/abdulahmad/NHL94Genesis)
(`assign94.asm`, `equals.inc`). Tickenest's
[NHL94MatchViewer mechanics research](https://github.com/nhl94dotcom/NHL94MatchViewer/blob/main/docs/GENESIS_MECHANICS.md)
helped locate the existing assignment/awareness behavior. The new coverage
routine and tests are this project's addition, not a claim to those authors'
engine work. See CREDITS.md for inherited base-game/mod credits.
