# Angular flight helpers and impact arithmetic

This pass executes original instructions against independent fixed-width arithmetic.
It does not yet run a complete flight/collision loop.

## Angular response

`tools/verify_flight_angular.py` checks 600 cases each for entries `83DF`, `83D4`
and `83BC`, plus all 65,536 angles through each of `83A4` and `23A0`.
The report is [angular-verification.json](../analysis/flight-physics/angular-verification.json).

The reference in that tool explicitly wraps words and uses signed products.
Important reconstruction details:

- `83BC` wraps target minus current angle to a signed word, then bounds it to
  **−10,241 through +10,240**. The asymmetric endpoint is intentional in the
  instructions: negative magnitudes use XOR with the sign word without subtracting
  that sign word. Multiplication by the timestep follows, then the gain stage.
- `83D4` forms a rounded signed gain/product shifted by eight, preserving word wrap.
- `83DF` doubles the timestep, applies damping to the old angular rate, and clamps
  the resulting rate to zero if its sign differs from the rate plus driving impulse.
  It then integrates using the old/new rate midpoint with signed-shift rounding.
- The product-to-word byte shuffles also add the high byte of the doubled timestep.
  That extra term is zero for ordinary timesteps below 128; it must not disappear
  from an exact implementation for larger steps. These are arithmetic boundary
  tests, not a claim that those large steps occur in normal play.
- `83A4` folds the angle according to its quadrant. `23A0` folds pitch outside
  the central half-turn by XOR with `7FFF`, while adding half a turn to heading
  and roll. This is not identical to replacing the XOR with angle negation.

Input smoothing, complete craft callback behavior, collision response and long
trajectories remain separate work. No constants were fitted to observed flight.

## Shared object impact

[Native impact results](../analysis/flight-physics/impact-damage-verification.json)
cover 144 strength/resistance/damage combinations through `CE26`, with active
object callbacks and nonzero definition resistance. The random angular kick at
`854E` is intercepted; execution stops before visual effect creation at `6815`.
Thus this verifies damage and the transition into expiry, not a complete impact.

Let `s` be the incoming strength byte and `r` the victim definition byte at `+8`.
For the tested branch, the increment to the object's word at `+64` is:

```
s <= r:       1
r < s < 2*r:  1 + 257 * floor(((s-r)*256 + r) / r)
s >= 2*r:     65536
```

Overflow of that word selects the death/expiry path. Consequently, a hit no
stronger than resistance still adds one; a hit at least twice resistance always
overflows. This is a damage accumulator, not a subtraction from conventional HP.
The zero-resistance and callback-zero branches are different and are excluded.
The upstream strength calculation also varies by weapon.

Separately, the incoming strength accumulates in byte `+57`; overflow sets the
whole `+56` word to `FFFF`. On fatal overflow, `+64` becomes `FFFF`, flag `+07`
bit `20` is set, and callback `+66` becomes `8DAA`. The native code also schedules
`+68` from the current clock and overflow-related arithmetic. Handling an object
already awaiting expiry remains outside these fixtures. The later list removal
and mission counter behavior is covered by [object completion](object-completion.md).
These findings must not be treated as the player's scenery-crash rules.

## Building state mutation

The small native span `67C1–67D5` was tested for all 256 incoming state bytes.
It adds `20h` with byte wrap, then increments counter `C221` if the **resulting**
state has bit 7 set. It neither ORs in a destruction bit nor saturates the state.
The type byte remains unchanged.

This is only the mutation after a caller has admitted a hit. It does not prove
that every building can be destroyed, that repeat hits always reach this code,
or that aircraft collisions use it. In particular, the observation that
lamppost crashes show a destroyed model remains to be connected to the actual
player collision path. The existing alternate-state asset links alone cannot
answer that question.

## Reproduction

```
PYTHONPATH=/tmp/darker-python python3 tools/verify_flight_angular.py
PYTHONPATH=/tmp/darker-python python3 tools/verify_impact_damage.py
```

Follow-up: [player collision and damage](player-collision-and-damage.md) now verifies the streetlight-specific crash mutation, controlled native geometric sweeps, and the exact limits of the player damage cheat. Earlier open questions on that response path are superseded by these tests.
