Repository navigation
Conversation
About half of the alttpr races of the past year ran on DR or OWR ROMs, which the game check refused for their DR/OR titles. Their race flag sits where vt's does, so the probe and its fail-closed answer stay the same.
…nd shops DR 1.5.6, which most DR races of 2026 ran, adds locations vt has none of. A script reads them from DR's own tables (never its ROM bytes), so the tracker can count and autotrack them as the seed's settings make them.
…slots Outside Race Mode the ROM tells DR's door, drop, pottery and shop settings and whether it is a Mystery seed. The three tables DR keeps beside the save are v2.0's locations only in modes that shuffle them, so each is read behind a switch the run's own settings turn on.
…nd shops DR seeds now take run types of their own, whose settings say which pots, enemies and shop items are locations: they join the Checks list and the dungeon counters, and autotracking reads their tables only while those settings shuffle them. What the tracker cannot model yet is named.
Most DR races roll their seeds there, not on alttpr.com. A permalink's meta names every DR setting; a Hyrule Town Hall patch writes the bytes the ROM decoder reads, so neither needs the seed generated. Fixtures are cut to those bytes by a script, never holding where an item is.
…read The tracker's DR data is 1.5.6's, while races run 1.5.2 to 1.5.8: the readout says so when a seed's version differs. Its tables' bits are listed for the run's own locations only.
…ce reads The pack README is where each address, table and source is cited; the rules and the share doc say where the new state lives and how links carry it, so the next phase (DR's own logic) starts from them.
Its settings' selects, its key pots in the Checks list and the map's note are new UI: the browser test holds them to every width and to axe, and the import's placeholder now fits a phone's field.
The form now names avianart.games and Hyrule Town Hall beside alttpr.com: the browser test still asked for the old words.
Contributor
🔍 CI Results
📊 Test Coverage
✅ All checks passed! Updated at 2026-10-30T23:47:06.829Z |
A DR run's review reads DR's own log, which is neither alttpr.com's JSON nor anything sniffed so far: its text opens with its version line, and its JSON leads with entrance and door lists that may fill any head. Name the format so the ALttPR pack can route it.
A DR log names items as DR's Items.py does, which differs from the entrance randomizer's table: a price after the code, events as code 999, a dungeon byte after a prize's sprite bytes, and pickups vt has no item for. Join them to vt's classes on the ROM code by the same importer, so the names stay generated.
Reviewing a DR run needs DR's own log, text or JSON, as DR 1.5.6's Spoiler writes it: names with the dungeon a door shuffle moved them to and an enemy's note, the pack's DR locations for key drops, pots, drops and shops, a meta keyed by player, and the seed as the ROM's title states it, so a run autotracked from the ROM binds to it. The fixtures are real spoiler races' logs, recorded by a script, since avianart keeps a race seed's placements to itself.
…rules-core.mjs The Door Randomizer's Rules.py descends from the entrance randomizer's: its port reuses the same walk and translation under its own dialect (settings, items, methods, helper prefix). The entrance randomizer's rules.json comes out byte-identical.
A DR log binds to the run by the seed in the ROM's title (or avianart's hash for a run started from a link), by which randomizer wrote it and by the settings the ROM states exactly. Its key drops, pots, enemy drops and shop items are known places of the board and read "taken, not timed", since the timeline never dates them. The waits are not shown for a DR log: the pack has none of DR's rules yet, and alttpr.com's would say "in logic" from rules the seed was not made with.
The binding evidence, the new hidden reason and what a DR place reads in the Run tab, for developers and for players.
DR's logic needs its own regions, doors and wiring, not the entrance randomizer's: import-dr now also writes src/door-rando/world/ (913 regions, 1,200 doors with their logic flags, 25 portals and the connection tables) from Regions.py, Doors.py and the shuffle modules, read as data, every entry with its line.
…(stage B) DR's world needs DR's own rules. They go through the entrance randomizer's walk under a DR dialect (Open, Standard and Inverted as settings, DR's items and methods); crystal reads, door flags, the dry trench paths and the bunny's side are data the world gives. What is code stays listed in unported with its line, held by rules.spec.ts, which compiles every rule.
…drops and pots DR builds those rules in code from its sprites, enemy stats and damage table, so they are computed as EnemyLogic.py does and handed to the walk where set_rules calls them. A random.choice tie is followed every way and anded (none in vanilla); health that depends on the world's side reads it through derived settings. js-yaml reads the damage table.
…ixtures (stage C) DR's world will be held to its own unit tests and customizer seeds. The cases are read at 1.5.6, the harness at 626691a, where upstream made the suite run again; the everything-but pool comes from ItemList.py's lists. Every file is listed pending in upstream.json until the world is built.
# Conflicts: # packs/alttpr/test/manifest.ts # packs/alttpr/upstream.json
…anilla tests DR's rules are now a world the engine solves: its regions linked as DR's vanilla world links them (overworld, entrances with the Inverted swaps, doors and portals), the flute and mirror exits it makes in code, the Menu's save-and-quit exits, the bomb shop's case, the derived settings the connections decide and the bunny's paths. The fact solver moves to facts.ts, which the entrance randomizer's world shares. DR's four vanilla test files are held: 572 of 573 cases, the last one waiting on the key analysis. Barriers and key doors stay maybe until the dungeons are ported.
…s dungeons The dungeons now run as DR's traversal does: each region a node per crystal state some path brings it in, barriers passing their colour only, switch doors both. Key doors stay strict-safe until the key analysis is ported: every key of the dungeon (the chests' and the vanilla drops', swept as DR sweeps its forced keys) or maybe, never no; big key doors and chests ask the big key, Mire's barriers their two-key alternative. DR's eleven dungeon test files are held: of the 181 cases upstream fails itself, 169 are listed with the reason its own rules give, 12 wait on the key analysis.
…ted tests The world builder already swapped Inverted's entrances; it now also takes the connections to build on, which the tests use to show where DR's own vanilla Inverted world differs from the old expectations: it never links the Dark Sanctuary's exit, and it names the castle's entrance Agahnims Tower whatever it leads to. Four inverted files are held (51 cases listed with why); Turtle Rock's tests are all disabled upstream and the bomb rules test holds no case, so those two stay pending.
…as code Standard's world gains its save-and-quit to Uncle and Zelda's way back from her cell, the rules of the first path DR finds, set on the tapestry and her drop-off. Murahdahla joins a triforce hunt, a boss's items wait on its map and compass when restricted, and Mire's spikes' pot asks the spikes once pots shuffle. A fact reached at maybe only now reads maybe, so a maybe key door no longer turns what lies past it into no; the escape's big key drop stands for the item DR's rules read.
DR's key rules come from its analysis of each dungeon (KeyDoorShuffle.py), which walks the dungeon's doors without item rules and records, for each set of key doors a player may have opened, what lies behind them. This ports that walk on the vanilla world: the overworld only a dungeon reaches (find_inaccessible_regions) and its logical doors, each dungeon's start regions (determine_entrance_list and vanilla_key_logic's enabling loop, Python's rstrip quirk in _find_portal_for_region kept), ExplorationState's key paths and create_key_counters. Not wired into the world yet; the rules come next. Held: the start regions and inaccessible regions per mode, each dungeon's counters (chest keys, forced drops, counters, keys spent at most), the max counter reaching every location. DR contract unchanged (not wired).
The rule DR gives each key door: the counter that spent the most keys elsewhere and still gains from the door sets its worst case, create_rule its partial number, check_for_self_lock_key and bk_restricted_rules the alternatives a placement may grant, then the swap of a big key alternative that asks more and vanilla_key_logic's adjustments (the escape's doors, Palace of Darkness's front door, Mire's blue barriers, Ganons Tower's alternates). The fill-side placement rules are left out: they choose where keys go, never what a door asks. Held to KeyDoorShuffle.py's own validate_vanilla_key_logic, which no DR code calls, now imported as test/dr-upstream/vanilla-key-logic.json (python.mjs reads set displays): every rule and big key restriction it checks holds in each mode but three Ganons Tower doors, listed with why (the port asks one key more; DR's own GT adjustment outdates two of its location sets). DR contract unchanged (not wired yet).
Each key door of DR's world now asks what DR's analysis gives it, partial logic's number (strict with wild keys: every chest key; dangerous read as partial), instead of every key of its dungeon. What a placement grants beside it (the key in the one location behind a door, the big key behind it) is maybe; with the keys in their dungeons a door short of its number is maybe, never no. Misery Mire's two-key alternative to its blue barriers is maybe only: DR's code grants it, its own key logic seeds refuse what lies behind it. Other connections than the vanilla ones keep the strict-safe rule (portals may be unknown). Soundness: key-model.spec.ts draws placements of the dungeons' keys DR's fill may make and plays them out with DR's own rule for each; the model never says yes where the play does not reach (Open and Standard with the keys in their dungeons, Open and Inverted with wild keys), and a model one key short or one taking a placement's alternative for granted is found unsound. Contract, per suite (pass / held cases, upstream's own failures listed): - vanilla: 573/573 (was 572, KEY_PENDING 1: Mimic Cave now holds) - dungeons: 302/483, STALE 181 = upstream's 181 failures (was 169 + 12 KEY_PENDING: AT Dark Maze now holds; 11 upstream fails itself, its key rule counting drop keys TestDungeon never sweeps; AT's Dark Maze without weapons is DR's bombs) - inverted: 615/666, STALE 51 (unchanged) - KEY_PENDING: 13 -> 0, the list removed - suite seeds, false => not yes, now held: partial 3/3, partial_2 5/5, partial_3 34/34 (1 a big key only bk_restricted forbids), strict 5/5, default (dangerous) 3/3; true => yes 4/4, 2/2, 67/79, 2/2, 2/9
… game refuses it The DR review (4bc460a) renamed what the refusal calls an ALttPR log, since DR's logs are A Link to the Past's too, but the Super Metroid and SMZ3 review specs and their browser tests still expected "alttpr.com spoiler log": the unit specs failed in the full run. The e2e files are updated untried (no e2e run under machine load).
Setting the bag on reset the bombs to none, even after the player had recorded a +10 upgrade, which in a bag seed is the bag itself: sound, but the find was lost without a word. Each +10 beyond the start of 10 now carries over as a bag.
Each door, entrance or overworld note builds DR's world again, key analysis included, inside the click; only the vanilla-door solve had a budget. A fully noted crossed shuffle at intensity 3 now rebuilds under 150 ms (50 ms measured), so a slower build cannot creep in unseen.
LogicNote and the tricks dialog each kept their own copy of the same "A, B and C" joiner, and the DR map note needs it too.
Door shuffles had a sentence over the map; the fork's whirlpools, flute spots, crossed edges and Mixed flips had none, so a Mixed run with nothing noted read everything out of logic with no word of why. The map's note now names the shuffles and points to the Overworld tab.
…lain The quick control unmounts once it has noted every kind it listed, so its focus fell to the page's start and a keyboard or screen reader user had to find their place again in a list of a hundred rows (WCAG 2.4.3). Focus now moves to the summary the control just changed.
The 67 Edges rows, and their selects' names, read the fork's internal
codes ("Kakariko Fortune ES - Kakariko Pond WS"), which no player can
map to the overworld. Each row now names its two screens as the tracker
does, and the part of the edge where two screens meet more than once;
a spec holds each edge's screen to the pack's data.
…the game The game's entrance ids were mapped to targets from the entrance randomizer's pools alone, which never shuffle Link's House (entrance 1) or the Tavern's back (0x43). DR and its fork do, so walking out of a moved Link's House left its door unnoted (bench seed c0PDd2qiJ). Both now map to their targets; a pool that never offers them still drops the reading, so alttpr.com runs read as before.
… unset Lite's and Lean's kept caves read both: defaulting them to off and none kept a fairy cave or the Good Bee Cave where a seed may have moved it. Unstated, each now may move, so its cave waits for a note.
The Overworld Randomizer's door contract reads its logs as DR's does, on its own release's data: the reading moves to test/dr-doors.ts, taking the data bundle, and DR's contract holds the same answers on it.
A seed was read over the current run's settings, so a DR Crosskeys seed loaded after an OWR Mixed District run kept District, Mixed, bonk drops and the fork's prize and follower shuffles (bench seeds c0PDd2qiJ then toInhuUYy): every check read maybe. A spoiler's meta now names the whole seed, what it leaves out unset or DR's default; a ROM read keeps the run's hand-set settings, but none of the fork's on a seed of DR itself.
Under a door shuffle every key door asked all its dungeon's keys, though DR analyses each layout it builds. Where the notes tell all that analysis reads (intensity 1 or 2, coupled doors, vanilla entrances, the layout linked and its kinds known, its starts certain), the world now runs DR's own analysis on it; elsewhere, where DR's starts rest on random portal choices, strict-safe stays.
The logic note said a key door always asks every key of its dungeon, which no longer holds below intensity 3 with coupled doors and vanilla entrances: once a dungeon is noted whole, DR's own key analysis counts its keys. The note and the guide now say when it runs and why not otherwise.
DR builds Skull Woods from its holes and the castle from its rat path as from a lobby (dungeon_drops). A room joined only to Skull Pinball kept its vanilla dungeon, so its key doors counted another dungeon's keys; an OWR partitioned seed puts Swamp's map ledge in Skull Woods that way.
…ptions In a crossed shuffle each door's select lists every door it may lead into, so Ganon's Tower's 104 rows held some 6,800 options, measured at 440 ms (150 on a quieter run, long tasks of 54 and 94 ms) between picking the dungeon and its first paint. A row now shows the target noted alone and its options come in a render React defers: about 40 ms, no long task, held under 200 ms by a browser test.
The search said nothing of how many doors it showed, left bare headings when none matched and kept its words across dungeons; lobbies read "Ganons Tower entrance" beside "Ganon's Tower"; at 390 px the noted target was cut off; the kind placeholder read "? Kind" where every other select says "? Not known", and the keys field's "?" was faint.
The door model was held to DR 1.5.8's seeds only. Nine avianart seeds of the Overworld Randomizer's door shuffle (basic, partitioned and crossed, with Mixed, crossed entrances, decoupled doors, Inverted, Standard) now hold it on the fork's data both ways, each door noted from the log.
… pairs With eight flute spots ticked the other boxes turned disabled with no word beside them, the count living far above; the hint that describes each box now says why. A forced whirlpool pair read "(always)" alone, where a sighted player looked for a select: it now says no note is needed.
Unlike a chest, a bonk pin had no tooltip, so a mouse or touch player got no name or state, and a review never said what its drops held. It now has the chest's text tooltip and a held line. Its round shape was nearly invisible at 24 px, the chest's square tile clipped: a ring draws it.
The noted analysis reads a pool dungeon's chest keys from its own key doors (calc_max_chests), never from the player's count. On the six seeds it analyses, each layout's count now must equal the small keys the log's fill placed for that dungeon, 76 layouts in all.
CLAUDE.md, the data rule, the pack README, the review and the guide still said the app solves only vanilla doors and entrances, OWR not at all or with its overworld vanilla, Swapped not modelled, no Standard seed held; the review's reasons lacked doors and overworld and bonk drops; several comments saw only whirlpools and flute spots. The guide's one 2,500-word paragraph is split, and names the static key logic cause it left out.
…alone Timed with the other browser tests running, the first paint came within reach of its budget (144 ms of 200). The options a dungeon shows at first paint cannot be blurred by load: 725 now, some 6,800 before.
… data The fork's door shuffle is now held to its seeds, so a door-shuffled OWR run takes the fork's world instead of showing every check maybe. The Doors tab read DR's door data for every run; it now reads the run's release's (the fork's has the bosses' Spoils rooms), from its solver's module, so an OWR run never loads DR's data.
Read on the 390 px screenshot, a door's two selects both said "? Not known" one above the other, which told the link from the kind only by their accessible names. The kind's now says "? Kind not known".
The Doors tab now reads the fork's own data for an OWR run, so the browser test notes a lobby from the keyboard and a link there, keeps them across a reload, and holds the tab at four widths.
The tab now loads its release's world data on demand, which took longer than a query's wait under coverage; loaded once before the tests, none races the import.
Every door note rebuilt the world and ran DR's key analysis again on all thirteen noted layouts, though a note moves one. Each analysis is now kept by all it reads (its layout's links, kinds and dests, its starts, the run's settings), the inaccessible regions by mode: a fully noted crossed world rebuilds in about 30 ms after a note instead of 75 to 90, with the same answers.
Brings every OWR entrance shuffle, OWR Standard and the door shuffle on the fork's data beside the Swapped partners, District picker, small keys only and DR's key analysis on noted layouts. Reconciled: - owrEntrancePool: the fork's pool for any mode (owrShuffled(shuffle, ...), dungeon split, Insanity decoupled), Swapped keeping its derived partners, District alone narrowed to its district's targets. - owrNotedConnections: every mode, Swapped's told partners linked; a target a partner tells no longer counts as unplaced, as a note's. - import-dr --owr writes both the pool tables apart (entrances.json) and the districts (districts.json); each side's importer, run again, gives the merged files. - poolOf routes every OWR run to owrEntrancePool with the worlds' and towers' readings District and Swapped need. - The doors note names DR's key analysis for DR runs only: the analysis reads DR's data alone, so an OWR door shuffle's key doors stay strict-safe (guide too). - Tests: the OWR pool settings in A's specs gain the run's fields, the District follow test keeps one district's doors, the e2e helper takes a settings change.
The fixes of the review of steps 5-7 on top of both DR branches. Each reading kept the stricter side; reconciled: - Coupling unset reads as decoupled (H1): the doors note promises DR's key analysis only for a coupling stated off, as the pack's gate reads it; A's note test states the coupling. - OWR release and overworld unset (H2, M1): an OWR run's Mixed not stated leaves the start house, the towers' trade and District's worlds not known (poolOf); A's and B's OWR tests state the fork's overworld and release, and every recorded OWR seed is held to carry 0.8.0.2. The pool's bonk drops and take-any caves stay B's reading (unstated may move), the world's bonk drops C's (unstated shuffled). - A spoiler or ROM read drops the fork-only settings on a DR seed (B defect): A's nearbyItems is one of them. - Every reviewed maybe yes once the keys are held (L-S2): held on B's OWR logs too, Standard's escape and Insanity's exits named as no key opens them; B's door-only copy of the check is gone. - The Doors tab's deferred options (M7) on the run's own release data; the share table appends A's then C's options; the perf spec keeps both budgets (a fresh world's, a note with the analyses kept). - Docs no longer limit the fork's world to District and Swapped.
…unset Every DR and OWR release's meta names both (BaseClasses.py:2574, :2597 at 1.5.8; :2570, :2593 at 1.5.6; owr :3139, :3164), yet a meta without them read as none, DR's default: a guess the seed may contradict. Now each is left out, the ROM-like reading of the take-any caves unrecognized.
…mid as not known A spoiler's word this version does not know for one of the four, or a meta naming none, fell back to DR's default: an unknown enemy shuffle read as none, a newer pyramid option as auto, so the logic could say yes on a seed whose setting asks more. The four now have no default: the run types state DR's, a seed its own, and unset is a cause the map names (every check maybe) while the world reads it the stricter way.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Door Randomizer (DR, and its Overworld fork OWR) in full, as the 2026-10-29 study plans it: about half of the alttpr races over the past year. Draft until every step is in and green.
Done (study steps 1–3):
DR156_…) and OWR (OR…) ROMs. Their race flag is vt's pair at the same address (DR 1.5.6Rom.py:1113,1483-1484), so an unreadable flag keeps Race Mode on. Outside Race Mode it reads DR's and OWR's settings. "What I read" names the version and says when it is not 1.5.6, the pinned one.metaor a Hyrule Town Hall.bps. Fixtures come fromrecord-dr-seeds, cut to the bytes the decoder reads.import-dr, which writes no ROM bytes: 33 key drops, 812 pots, 714 enemies, 32 shop items and 9 take-any items. They show in the Checks list and the dungeon counters. Flags are read at$7F:6018/$7F:6268/$7F:64B8(z3 d0f4651sram.asm:390-392), each table behind a switch set from the run's settings. Race Mode reads a table only while its mode is shuffled (v2.0: "only considered locations in modes where they are shuffled"). Rooms and transitions are never read.To do: 4. DR's own logic with vanilla doors, including its key rules, held to DR's tests. 5. DR's entrance pools. 6. Door shuffle, with door notes. 7. The OWR overworld shuffles. 8. The review of DR spoiler logs.
Verified so far: lint, typecheck, test:coverage, check:docs, build, e2e (plus
door-randomizer.e2e.ts). Progress notes:~/alltp-handoff/dr-progress.md(local).