Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions eech-campaign/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ The M2 reference scenario (retail Lebanon, observed as Tacview and
structured observations, and checked): [`docs/m2-reference.md`](docs/m2-reference.md).
M3's first slice, one campaign → world → campaign resupply loop observed
through the public path: [`docs/m3-resupply-loop.md`](docs/m3-resupply-loop.md).
A SUPPLY aircraft destroyed in flight, and what the campaign did next:
[`docs/m3-supply-loss.md`](docs/m3-supply-loss.md).

## The campaign kernel spike

Expand Down
93 changes: 93 additions & 0 deletions eech-campaign/docs/m3-supply-loss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# M3: a SUPPLY aircraft destroyed, and what the campaign does next

This record is part of M3 ([#27](https://github.com/flying-dice/eech_source_code/issues/27)). It answers one question: **when a SUPPLY aircraft is destroyed during an active supply task, does that physical loss alter campaign progression and lead to a subsequent campaign response?**

**Answer: yes, the loss altered campaign progression, and the campaign carried on with what it had left:**
- the SUPPLY group permanently lost half its strength;
- its task ended, with the survivor turning back at the moment of the loss and landing back at its base. No keysite delivery by the group was observed, and a delivery to a group would not be observable in any case;
- the campaign later re-tasked the reduced group, which delivered fuel elsewhere on its next task.

**What the public observations cannot show:** what happened to the cargo aboard the lost aircraft, and who the task's receiver was. By elimination the receiver was a group in the field, not a keysite. So whether that receiver's shortfall was later made good is not observable.

The loss occurred naturally in the accepted reference run; no adverse scenario was manufactured. The evidence is that run's retained observations ([`reference/m3-resupply-loop/observations.jsonl.gz`](../reference/m3-resupply-loop/observations.jsonl.gz), from #66): the same file, byte for byte. No new run was needed and no runtime file changed. Everything was read through `eech-world.exe` → `campaign.lua` → `require ("eech_dc")` → `engine:objects ()`.

## The chain

Group 87567 is callsign **"Wolfpack"**: two red **Mi-17 Hip** helicopters, units 87568 and 87581, based at Beirut International.

| t (s) | Fact | Status |
|---|---|---|
| 899.83 | No red keysite has fuel at or below 75 (the request threshold) | observed (keysite snapshot) |
| 921.82 | Both aircraft's primary task becomes **TASK_SUPPLY** | observed |
| 1,043.79, 1,044.79 | Beirut's fuel drops one crate in each of two consecutive samples (63.2 → 53.2 → 43.2). 87581 is 54 m and then 19 m over Beirut; 87568 is 423 m and then 363 m away. | observed |
| 1,044.79 – 1,584.66 | Both fly south-southwest, *Performing Task*, at about 60 m | observed |
| 1,576.66, 1,577.66 | Two blue **MIM-72G Chaparral** missiles are launched: by M48A1 "Banshee" (air defence 82114) and M48A1 "Apollo" (vehicle 84435) | observed |
| **1,584.66** | **Mi-17 87568 dies**, 32 km from Beirut, 62 m up. In the same sample it leaves its group, and both Chaparrals vanish with their last positions 351–354 m from it | death observed; the hit inferred |
| 1,584.66 | The survivor, 87581, is at its farthest point from Beirut: it turns back at the moment of the loss, still *Performing Task* | observed |
| 1,619.65 | Group 87567 has one member, 87581. **No replacement joins it for the rest of the run.** | observed |
| 2,116.45 | 87581's task ends (no task, *Landing*), 455 m from Beirut. **No keysite delivery by the group** between the loss and this point. | observed (a drop-off to a group leaves no observable trace) |
| 2,187.34 | The wreck of 87568 is removed | observed |
| **3,619.24** | The campaign assigns the one-aircraft group **TASK_SUPPLY** again | observed |
| **4,013.67** | 87581 delivers fuel to **Power Station 3**: 66.5 → 100 (the complete chain from #66) | observed |

In the 30 minutes after the loss, four other SUPPLY groups (87621, 87686, 87714, 87742) pass within 1.4–4.1 km of the loss point. The campaign kept routing SUPPLY traffic through the area; nothing more is claimed about that.

## Observed, inferred and not observable

| Observed: in the public observations | Inferred: from observations and the code, or by elimination | Not observable through the public path |
|---|---|---|
| The aircraft, its group, TASK_SUPPLY, *Performing Task*, its position and the sample of its death | That the Chaparrals hit it: they vanish at it in the sample it dies | Crates, so whether 87568 carried one. Two were picked up, but crates are not reported. |
| The two Chaparrals' types, launch times and launchers, and their disappearance in the death sample | **The receiver was a group in the field.** When the task was assigned, no red keysite had fuel at or below 75, and keysites request only then (`keysite.c`); the other requester kind is a group (`group.c` `assess_group_supplies`) | Which group requested it, and that group's supply level: group supply is not reported |
| The two one-crate pickups at Beirut, and how far each aircraft was | | The task's own supplier and receiver: the task record is not reported |
| | | Whether any crate reached the receiver: a drop-off to a group changes nothing that is reported. The survivor turned back at the loss point, but whether a drop-off waypoint lay there is unknown. |
| The group shrinking from two to one, with no replacement | | The request message; why the survivor turned back (the AI's reason) |
| The survivor turning back, its task ending at Beirut, no delivery | | Whether the receiver's shortfall was later made good |
| The wreck's removal | | |
| The group's next SUPPLY assignment and its delivery to Power Station 3 | | |

**Code reading:**
- a crate goes aboard the aircraft that reaches the pick-up waypoint (`mb_msgs.c` `response_to_waypoint_pick_up_reached`);
- a crate aboard a destroyed helicopter is destroyed with its wreck (`hc_dstry.c` `destroy_local_family`, when the wreck is removed).

So if 87568 carried a crate, it was never delivered and was destroyed at 2,187.34 s. The observations cannot say whether it did.

## What the loss changed in campaign progression

- **The group's strength:** Wolfpack flew all its later SUPPLY tasks with one aircraft (observed), where it had two.
- **The task:** it ended with the aircraft back at its base and no keysite delivery (observed). Whether anything reached the group requester is not observable.
- **Supply:** two crates of Beirut's fuel left its stock (observed). Neither is observed being delivered on this task. Which aircraft carried them is not observable. If the survivor landed still carrying one, the carried-over-crate finding from #66 would apply.
- **The next decision:** the campaign re-tasked the reduced group about 25 minutes after its return (observed). Its next delivery went to Power Station 3, a keysite, not to the group that had requested the lost task's supply. Whether that group was resupplied later is not observable.

## Checks and results

| Check | Command | Result |
|---|---|---|
| Loss chain | `tools/loss-chain-check.py reference/m3-resupply-loop/observations.jsonl.gz --unit 87568` | PASS: the loss, the group's response and its next assignment are all observed ([`reference/m3-supply-loss/loss-chain.json`](../reference/m3-supply-loss/loss-chain.json)) |
| The checker requires those links | `tools/loss-chain-check-selftest.py … --unit 87568` | Removing the death, the survivor's task events after it, or its later SUPPLY assignment each makes the check fail |
| The run's other SUPPLY losses | same report | Four more are listed, not analysed: a red Mi-6 en route (1,790.61 s, 14.8 km away, no weapon found at it) and three blue transports destroyed on the ground while *Waiting* (10,011–10,234 s) |
| M1, M2 and #66 evidence | — | Unaffected: this slice changes only `tools/`, `docs/` and `reference/m3-supply-loss/`. No script or binary the runs use changed, and no run was repeated. |

## What this does not establish

- **Any other adverse outcome.** A delivery to a *keysite* lost in flight, where the receiver's shortfall would be observable, did not occur in this run. Supplier or receiver captures and destroyed keysites did not occur either.
- **A campaign response aimed at the lost supply.** No re-request or re-tasking toward the same receiver is observable.
- **That the campaign adapts.** SUPPLY traffic kept passing the loss area; no avoidance is claimed or denied.
- **Host interchangeability.** The loss, the campaign and the physical world are all inside `eech_dc.dll` (M5).
- **Cargo physics.** Crates are not observed. What happens to them comes from the code.
- **M3 acceptance.** This is one slice.

## Retained evidence

In [`reference/m3-supply-loss/`](../reference/m3-supply-loss/):

| File | What it is |
|---|---|
| `loss-chain.json` | The checker's report on the retained observations |
| `loss-events.jsonl` | The records behind each link (2,674 lines): the two aircraft's task and track events from 900 to 4,300 s; the death and the wreck's removal; the two Chaparrals and their launchers; Beirut's pickups; Power Station 3's delivery; and the red keysites' snapshot at 899.83 s |

The run's Tacview recording is M2's [`reference/lebanon-3h/recording.zip.acmi`](../reference/lebanon-3h/recording.zip.acmi) (byte-identical). It was not visually reviewed for this chain.

```sh
python tools/loss-chain-check.py reference/m3-resupply-loop/observations.jsonl.gz --unit 87568 --report loss-chain.json
python tools/loss-chain-check-selftest.py reference/m3-resupply-loop/observations.jsonl.gz --unit 87568
```
256 changes: 256 additions & 0 deletions eech-campaign/reference/m3-supply-loss/loss-chain.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
{
"observations": "../m3-resupply-loop/observations.jsonl.gz",
"loss": {
"t": 1584.66,
"aircraft": 87568,
"type": "Mi-17 Hip",
"side": "red",
"group": 87567,
"callsign": "Wolfpack",
"task": "TASK_SUPPLY",
"state": "Performing Task",
"task_state_since_t": 1044.79,
"position": [
30110.2,
61.5,
81769.4
],
"at_death_sample": {
"group": null,
"task": null,
"state": null
},
"weapons_vanished_at_it": [
{
"weapon": 83584,
"type": "MIM-72G Chaparral",
"side": "blue",
"launched_t": 1576.66,
"launcher": {
"id": 82114,
"kind": "air_defence",
"type": "M48A1 Chaparral",
"callsign": "Banshee"
},
"last_seen_m_from_aircraft": 354
},
{
"weapon": 98390,
"type": "MIM-72G Chaparral",
"side": "blue",
"launched_t": 1577.66,
"launcher": {
"id": 84435,
"kind": "ground_vehicle",
"type": "M48A1 Chaparral",
"callsign": "Apollo"
},
"last_seen_m_from_aircraft": 351
}
]
},
"group": {
"members_before": [
87568,
87581
],
"members_before_snapshot_t": 1559.67,
"members_after": [
87581
],
"members_after_snapshot_t": 1619.65,
"replacements_later_in_run": [],
"supply_period_started": 921.82
},
"cargo": {
"pickups_this_period": [
{
"t": 1043.79,
"supplier": {
"id": 80752,
"name": "Beirut International",
"type": "KEYSITE_AIRBASE"
},
"resource": "fuel",
"level": [
63.2,
53.2
],
"aircraft_over_supplier": [
{
"aircraft": 87568,
"horizontal_m": 423
},
{
"aircraft": 87581,
"horizontal_m": 54
}
]
},
{
"t": 1044.79,
"supplier": {
"id": 80752,
"name": "Beirut International",
"type": "KEYSITE_AIRBASE"
},
"resource": "fuel",
"level": [
53.2,
43.2
],
"aircraft_over_supplier": [
{
"aircraft": 87568,
"horizontal_m": 363
},
{
"aircraft": 87581,
"horizontal_m": 19
}
]
}
],
"lost_aircraft_wreck_removed_t": 2187.34
},
"response": {
"survivors": [
{
"aircraft": 87581,
"states_after_loss": [
"Performing Task"
],
"farthest_from_supplier": {
"t": 1584.66,
"m": 31915,
"seconds_after_loss": 0.0
},
"task_ended": {
"t": 2116.45,
"task": null,
"state": "Landing",
"nearest_keysite": {
"name": "Beirut International",
"type": "KEYSITE_AIRBASE",
"m": 455
}
}
}
],
"deliveries_by_group_before_task_end": []
},
"receiver": {
"resource": "fuel",
"keysites_requesting_at_assignment": [],
"snapshot_t": 899.83,
"status": "inferred: a group",
"why": "no red keysite other than the supplier had fuel at or below 75 when the task was assigned (keysites request only then, keysite.c); the other requesters are groups (group.c assess_group_supplies), whose supply levels are not reported"
},
"subsequent": {
"group_next_supply_assignment": {
"t": 3619.24,
"aircraft": 87581,
"state": "Repairing"
},
"its_first_delivery": {
"delivery_t": 4013.67,
"receiver": "Power Station 3",
"receiver_type": "KEYSITE_POWER_STATION",
"resource": "fuel",
"level": [
66.5,
100.0
]
},
"other_supply_groups_within_5km_in_next_30min": [
{
"group": 87621,
"closest_m": 3004,
"t": 1585.66
},
{
"group": 87686,
"closest_m": 2042,
"t": 1630.65
},
{
"group": 87714,
"closest_m": 4108,
"t": 1749.62
},
{
"group": 87742,
"closest_m": 1355,
"t": 1799.61
}
]
},
"other_supply_losses_in_run": [
{
"t": 1584.66,
"aircraft": 87568,
"type": "Mi-17 Hip",
"side": "red",
"group": 87567,
"state": "Performing Task"
},
{
"t": 1790.61,
"aircraft": 87622,
"type": "Mi-6 Hook",
"side": "red",
"group": 87621,
"state": "En route"
},
{
"t": 10011.35,
"aircraft": 84284,
"type": "C-130J Hercules II",
"side": "blue",
"group": 84283,
"state": "Waiting"
},
{
"t": 10198.61,
"aircraft": 84312,
"type": "C-17 Globemaster III",
"side": "blue",
"group": 84311,
"state": "Waiting"
},
{
"t": 10234.47,
"aircraft": 84316,
"type": "C-130J Hercules II",
"side": "blue",
"group": 84315,
"state": "Waiting"
}
],
"classification": {
"observed": [
"the aircraft, its group, TASK_SUPPLY and its state, its position and death, and the sample of its death",
"the weapons that vanished at that sample within 1 km of it, their types, launch times and launchers",
"the one-crate drops at the supplier with the group over it, and the distance of each aircraft",
"the group's membership before and after, and the absence of replacements",
"the survivors' task and state, their farthest point from the supplier, the end of their task and any delivery",
"the keysite levels of the resource at the snapshot before the assignment",
"the group's next SUPPLY assignment and its first delivery"
],
"inferred": [
"that the weapons hit the aircraft (they vanished at it in the sample it died)",
"the receiver, from the keysite levels and the code (see receiver.why)"
],
"not_observable": [
"crates, and so whether the lost aircraft carried one (crates are not reported)",
"the task's own supplier and receiver",
"a group requester's identity and supply level, and whether a crate reached it (a drop-off to a group changes nothing reported)",
"the request message itself, and why the survivors turned back"
],
"code": [
"a crate goes aboard the aircraft that reaches the pick-up (mb_msgs.c response_to_waypoint_pick_up_reached)",
"a crate aboard a destroyed helicopter is destroyed with its wreck (hc_dstry.c destroy_local_family)"
]
},
"pass": true
}
Loading
Loading