Metadata-Version: 2.4
Name: arme2cosmos
Version: 0.1.0
Summary: Artemis 2.8 XML mission -> Artemis Cosmos MAST migration assistant
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# arme2cosmos

A migration tool that ports legacy **Artemis 2.8** XML missions (`MISS_*.xml`) to
**Artemis Cosmos**. It produces a runnable Cosmos mission and leaves a clear, per-item
punch-list (`MIGRATION_NOTES.md`) for the handful of things a human must decide.

On the reference a28 corpus it converts **26 of 27 missions with zero leftover TODOs**;
all 27 compile under the real MAST compiler and **run headless in both output styles**.
The few remaining TODOs are genuine source issues (a name that references an object the
mission never created) — not tool gaps. See [`docs/coverage.md`](docs/coverage.md).

It can produce the mission in either of two styles (`--target`):

- **`mast`** (default) — an idiomatic MAST scaffold: the 2.8 event model translated
  into MAST tasks/routes.
- **`amd`** — a **declarative quest-tree** mission (`story.amd` + a thin `story.mast`):
  2.8 objectives, win/lose, and story beats become Cosmos quests with a live objectives
  log. See [`docs/amd_target.md`](docs/amd_target.md).

- **No dependencies** — Python 3.10+ is all you need to *run the tool*. (The missions it
  generates depend on the `a2x` layer in `sbs_utils` and the LegendaryMissions addons at
  Cosmos *run* time — never at the tool's build time.)
- Every translatable command becomes a real call; everything else is a `# TODO` with the
  original XML preserved inline.

---

## Install

Run it directly from the folder:

```sh
python -m arme2cosmos --help
```

Or install it to get the `arme2cosmos` command:

```sh
pip install .
arme2cosmos --help
```

---

## The three commands

| Command | What it does | Writes files? |
|---|---|---|
| `report`  | Shows how much of a mission maps to Cosmos | No |
| `artmap`  | Builds the ship-hull crosswalk (`hullmap.json`) | `hullmap.json` |
| `convert` | Scaffolds a full Cosmos mission folder | Yes (`out/<name>/`) |

### Typical workflow

```sh
# 1. (once) Build the hull crosswalk from the two game data files.
arme2cosmos artmap \
    --vesseldata /path/to/Artemis2.8/dat/vesselData.xml \
    --shipdata   /path/to/Cosmos/data/shipDataBB.json \
    --out hullmap.json

# 2. See how much of a mission (or a whole folder) maps.
arme2cosmos report /path/to/Artemis2.8/dat/missions/MISS_TheEndOfPeace

# 3. Scaffold it, using the hullmap for real ship art.
arme2cosmos convert /path/to/Artemis2.8/dat/missions/MISS_TheEndOfPeace \
    --hullmap hullmap.json --out out/
#    ...or emit a quest-tree mission with an objectives log:
#    arme2cosmos convert <path> --target amd --hullmap hullmap.json --out out/

# 4. Open out/<name>/MIGRATION_NOTES.md and finish the TODOs by hand.
```

Every command accepts a single `.xml` file, a single `MISS_*` mission folder, or a parent
directory full of them (it recurses and skips `~` editor backups).

---

## `report` — see what maps

```sh
arme2cosmos report <path> [--json] [--summary] [--detail]
```

Classifies every command/condition in a mission. For one mission it prints a per-kind
breakdown; for many it prints a one-line summary per mission plus a corpus total.

Each item is rated:

| Status | Meaning |
|---|---|
| `full`    | Translated mechanically, high confidence |
| `partial` | Translated, but leaves a `# TODO` (closest-fit) |
| `manual`  | Needs you to wire it (a few object properties, GM keys) |
| `unknown` | Not recognized (shouldn't normally happen) |

Options: `--json` (machine-readable), `--summary` (skip the per-kind detail for one
mission), `--detail` (corpus mode: also print each mission's breakdown).

---

## `artmap` — ship art crosswalk

```sh
arme2cosmos artmap --vesseldata <vesselData.xml> --shipdata <shipDataBB.json> [--out hullmap.json]
```

Artemis 2.8 and Cosmos name their ship hulls differently, so this builds a best-effort
map between them by matching each 2.8 vessel (race + class) to the closest Cosmos hull.

It prints how many vessels matched and writes `hullmap.json`. Hand that file to
`convert --hullmap` so converted ships use real Cosmos art instead of placeholders.
Vessels it couldn't match confidently are listed under `unmatched` in the file — those
will use a placeholder you can swap later.

---

## `convert` — scaffold a mission

```sh
arme2cosmos convert <path> [--out out] [--target mast|amd] [--lib-version v1.4.0] [--hullmap hullmap.json]
```

Creates a ready-to-open Cosmos mission folder:

```
out/<name>/
├── story.mast           # the translated mission (thin, on --target amd)
├── story.amd            # (--target amd) the quest tree: objectives, win/lose, story beats
├── scans.amd            # recovered 2.8 scan_desc as declarative science scans (if any)
├── script.py            # standard Cosmos entry-point boilerplate
├── story.json           # the sbslib + LegendaryMissions addons the mission needs
├── description.yaml     # mission browser entry
├── __lib__.json         # library version marker
└── MIGRATION_NOTES.md   # your punch-list of TODOs / things to verify
```

Options:
- `--out` — where to write (default `out/`).
- `--target` — the output style, `mast` (default) or `amd` (see **Two output styles** below).
- `--lib-version` — the library version tag written into `story.json`
  (default `v1.4.0`; set it to match the libraries installed with your Cosmos).
- `--hullmap` — a `hullmap.json` from `artmap`, for real ship art.
- `--event-model` — how 2.8 events are generated (**`mast` target only**; `amd` builds a
  quest tree instead):
  - `hybrid` (default) — flag-chained "scene" events stay one readable sequence;
    independent events run concurrently, and the ones the engine can push
    (respawn-on-destroy, dock, flag) become event-driven routes instead of polling.
    Matches how 2.8 checks all events every tick, without always-on tasks where avoidable.
  - `linear` — force every event into a single sequential chain (simplest to read /
    hand-edit; use for missions you know are strictly sequential).
  - `a28_compatible` — every event becomes its own continuous polling task, exactly
    like 2.8's flat-event model. No classification, no chain, no routes: the worst-case
    faithful fallback to reach for if a `hybrid` conversion behaves wrong.

### Two output styles (`--target`)

- **`mast`** (default) — the classic scaffold: 2.8 events translated into MAST tasks and
  routes, controlled by `--event-model`. Best when you want to read/hand-edit the mission
  as MAST.
- **`amd`** — a **declarative quest-tree** mission. Instead of hand-wiring the event
  machinery, it emits a `story.amd` where 2.8 objectives, win/lose, and narrative become
  Cosmos **quests** the LegendaryMissions `quest_driver` runs — so the port gets a live
  **objectives log** for free. It builds: kill / reach / dock / scan objectives, a
  `Win`/`Lose`/`Critical` end-game tree, timed and flag-driven **reveal chains**, "protect"
  objectives for friendly targets, and **story-beat** quests for narrative moments. The
  `story.mast` it emits is thin (spawn the start block, tag roles, grant the quests, carry
  the imperative bits as `//signal` routes). See [`docs/amd_target.md`](docs/amd_target.md).

Both targets compile the full a28 corpus; both recover 2.8 `set_ship_text scan_desc`
(→ science scans) and `hailtext` (→ a Hail comms button).

### What it translates for you

Positions are converted automatically (2.8 and Cosmos use mirrored coordinates — you
don't have to think about it). Translated mechanically:

- **Spawns** — players, enemies, neutrals, stations, monsters, black holes, anomalies.
  Named objects are remembered, so later commands that reference them by name still work.
- **Terrain** — nebula / asteroid / mine fields.
- **Messages** — comms text, big chapter titles, audio messages, and console warnings.
- **AI** — common enemy/monster behaviors (chase player, chase station, attack, …).
- **Movement** — `direct` to a point or a target; `destroy`.
- **Story flow** — events become a step-by-step sequence; "when" conditions become real
  waits (distance, sphere, fleet destroyed, docked, object exists, timers).
- **Comms buttons** — become a comms menu (`//comms` route).
- **Game Master buttons** — become a Game-Master comms menu.
- **Ship text** — name / race / class / description; a ship's `scan_desc` is recovered as
  a declarative **science scan** (`scans.amd`) and its `hailtext` as a **Hail** comms button.
- **Tags** — preserved as object data, with notes on rebuilding the tag gameplay.
- **Objectives (`--target amd`)** — the mission's win/lose and objective structure become a
  Cosmos quest tree with a live objectives log (see **Two output styles** above).

### What you finish by hand

Nearly every 2.8 command and property now maps to a real call. What's left as a `# TODO`
(with the original XML next to it, and listed in `MIGRATION_NOTES.md`) is:

- Ship art where no confident hull match was found (a placeholder is used).
- A handful of 2.8-specific features with **no Cosmos equivalent** (marked as engine-stub
  notes, non-blocking): mission music volume, per-object mine immunity, free-velocity drift.
- Genuine source issues — e.g. a command that references an object the mission never
  created (a dead reference / typo in the original XML).
- GM key/click interactions (2.8 GM hotkeys become GM comms buttons instead).

Treat the output as a strong first draft: the structure, spawns, positions, orientation,
objectives, and story flow are in place; you polish the few details the notes call out.

### How the port is verified

Two layers back the conversion (both need a Cosmos checkout with `sbs_utils` +
LegendaryMissions):

- **Conformance** — `A2xTestRange` (a standalone test mission) has ~28 maps that assert
  the *runtime behavior* of every emitted `a2x_*` call in the engine.
- **Mock run** — every converted mission is run headless in both targets; the whole
  corpus passes. The tool's own logic is covered by stdlib unit tests
  (`python -m unittest discover -s tests`).

See [`docs/coverage.md`](docs/coverage.md) for the full command/condition status.

For the full command-by-command coverage (what's finished vs. what needs a human
decision), see [`docs/coverage.md`](docs/coverage.md); property mappings are detailed in
[`docs/property_map.md`](docs/property_map.md).

---

## Running the converted mission

1. Copy the `out/<name>/` folder into your Cosmos `data/missions/` directory.
2. Make sure the libraries listed in its `story.json` are installed with your Cosmos
   (adjust `--lib-version` when converting if your version differs).
3. Start Cosmos, host a server, and pick the mission from the list — or smoke-test it
   headless if you have the Cosmos dev tools.

"Close enough to the original" is the goal — expect to playtest and tweak.
