maniator / maniator/verticopolis
[Bug][P1]: every shaft written after an EXPRESS slot is lost by the 1994 game
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 5
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
Isolated on the Wine harness 2026-07-31 while fixing the spanned-floor payload stride.
What happens
In a .TDT we export, the retail 1994 game loads the first express shaft correctly (it renders, with its stop settings) and then loses every elevator written after it. Shafts written BEFORE the express are unaffected.
Isolation (minimal two-shaft towers, one screenshot each)
| tower | slot 0 | slot 1 | result |
|---|---|---|---|
| CHAIN | express 1-30, 27 skips | standard 30-45 | slot 1 lost |
| CHAIN3 | express 1-30, no skips | standard 30-45 | slot 1 lost |
| CHAIN2 | standard 1-30, 27 skips | standard 30-45 | both render |
| CHAIN4 | standard 30-45 | express 1-30 | both render |
So it is not stop-skipping (CHAIN2 skips 27 of 30 floors and is fine) and not span. It is the express record itself.
What it is NOT
The obvious guess is that an express slot's built-shaft payload is a different size than 194 + 3140 + 324 * spannedFloors + 348. Six byte-level probes on CHAIN3 (splicing the express payload only) all still lost the following shaft:
- longer: +348, +9,720 (324 x 30), +29,160 (324 x 90, i.e. a full 120-floor block)
- shorter: -348 (no car block), -3,140 (no fixed block), -9,720 (no per-floor entries)
Six misses across that range suggests the game is rejecting the express entry and abandoning the rest of the table, rather than mis-sizing it. If so the defect is in a HEADER field of the express record, not its length. Candidates to bisect next: the capacity byte (we write 42), the width/x (express is 8 tiles wide in our engine), the car count, the 56-byte schedule block, and the serviced bitmap for a whole-tower span.
Impact and current mitigation
This is why the owner's 4-star tower rendered only a handful of its 23 shafts: its express sits in slot 5, so slots 6-22 were lost, and floors served only by those shafts became unreachable.
Mitigated in tdtEncoder.ts by writing express shafts LAST (stable sort). Measured on the owner's tower: shaft count recovered from a handful to a dozen-plus. A tower with ONE express now keeps every other shaft; a tower with TWO or more still loses everything after the first express, so this stays open until the express record itself is understood.
Story id: tdt-express-desync
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in tdtEncoder.ts and reproduce the minimal CHAIN3 two-shaft case against the retail 1994 game. Compare the express record's header fields, including capacity, width/x, car count, schedule block, and serviced bitmap, rather than changing payload length. Done means shafts after an express remain loadable, including when a tower has multiple express shafts.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- game-dev, reverse-engineering
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100