10 const and = (...predicates) => (...args) =>
11 predicates.reduce((acc, cur) => acc && cur(...args), true);
13 const or = (...predicates) => (...args) =>
14 predicates.reduce((acc, cur) => acc || cur(...args), false);
16 const when = (condition, then, otherwise) => (...args) =>
17 condition(...args) ? then(...args) : otherwise(...args);
19 const alwaysAvailable = () => true;
21 const neverAvailable = () => false;
23 const fromBool = b => (...args) => b(...args) ? 'available' : 'unavailable';
25 const isInverted = (config) => config.worldState === 'inverted';
27 const agaDead = (config, dungeons, state) =>
28 hasDungeonBoss(state, dungeons.find(d => d.id === 'ct'));
30 const countCrystals = (config, dungeons, state) => dungeons
32 (getDungeonPrize(state, dungeon) || 'crystal').endsWith('crystal') &&
34 hasDungeonPrize(state, dungeon)
37 const countRedCrystals = (config, dungeons, state) => dungeons
39 getDungeonPrize(state, dungeon) === 'red-crystal' &&
40 hasDungeonPrize(state, dungeon)
43 const hasRedCrystals = n => (...args) => countRedCrystals(...args) >= n;
45 const hasGTCrystals = (config, dungeons, state) =>
46 countCrystals(config, dungeons, state) >= getGTCrystals(config);
48 const countPendants = (config, dungeons, state) => dungeons
50 (getDungeonPrize(state, dungeon) || '').endsWith('pendant') &&
51 hasDungeonPrize(state, dungeon)
54 const hasGreenPendant = (config, dungeons, state) => dungeons
56 getDungeonPrize(state, dungeon) === 'green-pendant' &&
57 hasDungeonPrize(state, dungeon)
60 const hasPendants = n => (...args) => countPendants(...args) >= n;
64 const countBottles = (config, dungeons, state) =>
65 ['bottle-1', 'bottle-2', 'bottle-3', 'bottle-4'].filter(b => !!state[b]).length;
67 const hasBig = dungeon => (config, dungeons, state) =>
68 !config.wildBig || !!state[`${dungeon}-big-key`];
70 const hasBird = (config, dungeons, state) => !!state['bird'];
72 const hasBombos = (config, dungeons, state) => !!state['bombos'];
74 const hasBook = (config, dungeons, state) => !!state['book'];
76 const hasBoom = (config, dungeons, state) => !!(state['blue-boomerang'] || state['red-boomerang']);
78 const hasBoots = (config, dungeons, state) => !!state['boots'];
80 const hasBottle = n => (...args) => countBottles(...args) >= (n || 1);
82 const hasBow = (config, dungeons, state) => !!state['bow'];
84 const hasBugnet = (config, dungeons, state) => !!state['bugnet'];
86 const hasByrna = (config, dungeons, state) => !!state['byrna'];
88 const hasCape = (config, dungeons, state) => !!state['cape'];
90 const hasFireRod = (config, dungeons, state) => !!state['fire-rod'];
92 const hasFlute = (config, dungeons, state) => !!state['flute'];
94 const hasHammer = (config, dungeons, state) => !!state['hammer'];
96 const hasHookshot = (config, dungeons, state) => !!state['hookshot'];
98 const hasIceRod = (config, dungeons, state) => !!state['ice-rod'];
100 const hasLamp = (config, dungeons, state) => !!state['lamp'];
102 const hasMagicBars = n => (config, dungeons, state) => {
103 let bars = 1 + (state['bottle'] || 0);
104 if (state['half-magic']) {
107 if (state['quarter-magic']) {
110 return bars >= (n || 1);
113 const hasMirror = (config, dungeons, state) => !!state['mirror'];
115 const hasMMMedallion = (config, dungeons, state) =>
116 !!state['mm-medallion'] && !!state[state['mm-medallion']];
118 const hasMoonpearl = (config, dungeons, state) => !!state['moonpearl'];
120 const hasMushroom = (config, dungeons, state) => !!state['mushroom'];
122 const hasPowder = (config, dungeons, state) => !!state['powder'];
124 const hasQuake = (config, dungeons, state) => !!state['quake'];
126 const hasShovel = (config, dungeons, state) => !!state['shovel'];
128 const hasSmall = (dungeon, amount) => (config, dungeons, state) =>
129 !config.wildSmall || state[`${dungeon}-small-key`] >= (amount || 1);
131 const hasSomaria = (config, dungeons, state) => !!state['somaria'];
133 const hasSword = n => (config, dungeons, state) => state['sword'] >= (n || 1);
135 const hasTRMedallion = (config, dungeons, state) =>
136 !!state['tr-medallion'] && !!state[state['tr-medallion']];
140 const canBomb = () => true;
142 const canBonk = hasBoots;
144 const canDarkRoom = hasLamp;
146 const canShootArrows = hasBow;
148 const canFlipSwitches = or(
161 const canGetGoodBee = and(hasBugnet, hasBottle(), or(canBonk, and(hasSword(), hasQuake)));
163 const canLift = (config, dungeons, state) => state['lift'] >= 1;
165 const canHeavyLift = (config, dungeons, state) => state['lift'] >= 2;
167 const canActivateFlute = when(isInverted,
171 // partial copy of east light world
173 and(hasMoonpearl, or(and(canLift, hasHammer), canHeavyLift)),
179 const canFly = or(hasBird, and(hasFlute, canActivateFlute));
181 const canKill = damage => damage && damage < 6
182 ? or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1), canBomb, hasByrna)
183 : or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1));
185 const canMedallion = hasSword();
187 const canMeltThings = or(hasFireRod, and(hasBombos, canMedallion));
189 const canPassCurtains = hasSword();
191 const canSwim = (config, dungeons, state) => !!state['flippers'];
193 const canTablet = and(hasBook, hasSword(2));
195 const canTorch = or(hasFireRod, hasLamp);
197 const canTorchDarkRoom = or(canDarkRoom, canTorch);
201 const westDeathMountain = or(
203 and(canLift, canDarkRoom),
206 const westDarkDeathMountain = when(isInverted,
207 or(canFly, and(canLift, canDarkRoom)),
211 const eastDeathMountain = when(isInverted,
213 and(canHeavyLift, or(
214 // copy of eastDarkDeathMountain, to avoid circular reference
215 westDarkDeathMountain,
216 and(westDeathMountain, hasMoonpearl, hasHookshot, hasMirror),
218 and(westDeathMountain, hasMoonpearl, hasHookshot),
224 and(hasHammer, hasMirror),
229 const northDeathMountain = when(isInverted,
230 and(eastDeathMountain, hasMoonpearl, hasHammer),
235 and(hasHammer, hasHookshot),
240 const eastDarkDeathMountain = when(isInverted,
242 westDarkDeathMountain,
243 and(westDeathMountain, hasMoonpearl, hasHookshot, hasMirror),
251 const eastLightWorld = when(isInverted,
254 and(hasMoonpearl, or(and(canLift, hasHammer), canHeavyLift)),
255 and(canFly, canHeavyLift),
260 const westLightWorld = eastLightWorld;
262 const southLightWorld = eastLightWorld;
264 const eastDarkWorld = when(isInverted,
265 or(canFly, canSwim, hasHammer, and(hasMirror, eastLightWorld)),
268 and(hasMoonpearl, canHeavyLift),
269 and(hasMoonpearl, canLift, hasHammer),
273 const westDarkWorld = when(isInverted,
278 and(canLift, hasHammer),
280 and(eastDarkWorld, hasHookshot, or(canSwim, canLift, hasHammer)),
285 const southDarkWorld = when(isInverted,
289 and(eastDarkWorld, hasMoonpearl, hasHammer),
293 const mireArea = when(isInverted,
294 or(canFly, and(hasMirror, southLightWorld)),
295 and(canFly, canHeavyLift),
301 aga: or(hasBugnet, hasHammer, hasSword()),
303 hasSword(), hasHammer, canShootArrows, hasBoom,
304 and(hasMagicBars(4), or(hasFireRod, hasIceRod)),
305 and(hasMagicBars(2), or(hasByrna, hasSomaria)),
307 arrghus: and(hasHookshot, or(
310 and(or(hasMagicBars(2), canShootArrows), or(hasFireRod, hasIceRod)),
312 blind: or(hasSword(), hasHammer, hasSomaria, hasByrna),
313 helma: and(or(canBomb, hasHammer), or(hasSword(), canShootArrows)),
314 kholdstare: and(canMeltThings, or(
317 and(hasFireRod, hasMagicBars(3)),
318 and(hasFireRod, hasBombos, hasMagicBars(2), canMedallion),
321 hasSword(), hasHammer, canShootArrows, hasFireRod, hasIceRod, hasByrna, hasSomaria,
323 moldorm: or(hasSword(), hasHammer),
327 and(hasMagicBars(2), or(hasFireRod, hasSomaria, hasByrna)),
330 trinexx: and(hasFireRod, hasIceRod, or(
333 and(hasMagicBars(2), hasSword(2)),
334 and(hasMagicBars(4), hasSword(1)),
336 vitreous: or(hasSword(), hasHammer, canShootArrows),
339 const canKillBoss = dungeon => (config, dungeons, state) => {
340 const boss = getDungeonBoss(state, dungeons.find(d => d.id === dungeon));
341 return BOSS_RULES[boss](config, dungeons, state);
344 const canKillGTBoss = which => (config, dungeons, state) => {
345 const boss = getGTBoss(state, which);
346 return BOSS_RULES[boss](config, dungeons, state);
351 const canEnterHC = when(isInverted,
352 and(hasMoonpearl, eastLightWorld),
356 const canEnterCT = when(isInverted,
357 westDarkDeathMountain,
358 or(hasCape, hasSword(2)),
361 const canEnterGT = when(isInverted,
362 and(eastLightWorld, hasGTCrystals, hasMoonpearl),
363 and(eastDarkDeathMountain, hasGTCrystals, hasMoonpearl),
366 const canEnterEP = when(isInverted,
367 and(hasMoonpearl, eastLightWorld),
371 const canEnterDPFront = when(isInverted,
372 and(southLightWorld, hasBook),
373 or(hasBook, and(mireArea, hasMirror)),
375 const canEnterDPBack = when(isInverted,
376 and(canEnterDPFront, canLift),
377 or(and(canEnterDPFront, canLift), and(mireArea, hasMirror)),
380 const canEnterTH = northDeathMountain;
382 const canEnterPD = when(isInverted,
384 and(eastDarkWorld, hasMoonpearl),
387 const canEnterSP = when(isInverted,
388 and(southLightWorld, hasMirror, hasMoonpearl, canSwim),
389 and(southDarkWorld, hasMirror, hasMoonpearl, canSwim),
392 const canEnterSWFront = when(isInverted,
394 and(westDarkWorld, hasMoonpearl),
396 const canEnterSWMid = canEnterSWFront;
397 const canEnterSWBack = and(canEnterSWMid, hasFireRod);
399 const canEnterTT = when(isInverted,
401 and(westDarkWorld, hasMoonpearl),
404 const canEnterIP = when(isInverted,
405 and(canSwim, canMeltThings),
406 and(canSwim, canHeavyLift, hasMoonpearl, canMeltThings),
408 const rightSideIP = or(hasHookshot, hasSmall('ip'));
410 const canEnterMM = when(isInverted,
415 or(canBonk, hasHookshot),
423 or(canBonk, hasHookshot),
428 const canEnterTRFront = when(isInverted,
430 eastDarkDeathMountain,
445 const canEnterTRWest = when(isInverted,
446 and(eastDeathMountain, hasMirror),
449 const canEnterTREast = and(canEnterTRWest, or(hasHookshot, hasSomaria));
450 const canEnterTRBack = when(isInverted,
451 and(eastDeathMountain, hasMirror),
454 const laserBridge = or(
456 or(canEnterTRFront, canEnterTRWest, canEnterTREast),
467 const paradoxLower = and(eastDeathMountain, or(canBomb, hasBoom, canShootArrows, hasSomaria));
469 const canBridgeRedBomb = or(
470 and(hasMoonpearl, hasHammer),
471 and(agaDead, hasMirror),
474 const canRescueSmith = and(westDarkWorld, hasMoonpearl, canHeavyLift);
478 Logic.dungeonInterior = {
479 'hc-boom': fromBool(and(hasSmall('hc'), canKill())),
480 'hc-cell': fromBool(and(hasSmall('hc'), canKill())),
481 'dark-cross': fromBool(canTorchDarkRoom),
482 'sewers-left': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
483 'sewers-mid': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
484 'sewers-right': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
485 'ct-1': fromBool(canKill()),
486 'ct-2': fromBool(and(canKill(), hasSmall('ct'), canDarkRoom)),
487 'ct-boss-killable': fromBool(and(
488 canKill(), hasSmall('ct', 2), canDarkRoom, canPassCurtains, canKillBoss('ct'),
490 'gt-tile-room': fromBool(hasSomaria),
491 'gt-compass-tl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
492 'gt-compass-tr': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
493 'gt-compass-bl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
494 'gt-compass-br': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
495 'gt-torch': fromBool(canBonk),
496 'gt-dm-tl': fromBool(and(hasHammer, hasHookshot)),
497 'gt-dm-tr': fromBool(and(hasHammer, hasHookshot)),
498 'gt-dm-bl': fromBool(and(hasHammer, hasHookshot)),
499 'gt-dm-br': fromBool(and(hasHammer, hasHookshot)),
500 'gt-map-chest': fromBool(and(hasHammer, or(hasHookshot, canBonk), hasSmall('gt', 4))),
501 'gt-firesnake': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 3))),
502 'gt-rando-tl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
503 'gt-rando-tr': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
504 'gt-rando-bl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
505 'gt-rando-br': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
506 'gt-bobs-chest': fromBool(and(
507 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
510 'gt-ice-left': fromBool(and(
511 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
513 canKillGTBoss('bot'),
515 'gt-ice-mid': fromBool(and(
516 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
518 canKillGTBoss('bot'),
520 'gt-ice-right': fromBool(and(
521 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
523 canKillGTBoss('bot'),
525 'gt-big-chest': fromBool(and(
526 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
530 'gt-helma-left': fromBool(and(
535 canKillGTBoss('mid'),
537 'gt-helma-right': fromBool(and(
542 canKillGTBoss('mid'),
544 'gt-pre-moldorm': fromBool(and(
549 canKillGTBoss('mid'),
551 'gt-post-moldorm': fromBool(and(
556 canKillGTBoss('mid'),
557 canKillGTBoss('top'),
560 'gt-boss-killable': fromBool(and(
565 canKillGTBoss('mid'),
566 canKillGTBoss('top'),
570 'ep-big-chest': fromBool(hasBig('ep')),
571 'ep-big-key-chest': fromBool(canDarkRoom),
572 'ep-boss-defeated': fromBool(and(
573 canShootArrows, canTorchDarkRoom, hasBig('ep'), canKillBoss('ep'),
575 'dp-big-chest': fromBool(and(canEnterDPFront, hasBig('dp'))),
576 'dp-big-key-chest': fromBool(and(canEnterDPFront, hasSmall('dp'), canKill())),
577 'dp-compass-chest': fromBool(and(canEnterDPFront, hasSmall('dp'))),
578 'dp-map-chest': fromBool(canEnterDPFront),
579 'dp-torch': fromBool(and(canEnterDPFront, canBonk)),
580 'dp-boss-defeated': fromBool(and(
587 'th-basement-cage': fromBool(canFlipSwitches),
588 'th-map-chest': fromBool(canFlipSwitches),
589 'th-big-key-chest': fromBool(and(canFlipSwitches, hasSmall('th'), canTorch)),
590 'th-compass-chest': fromBool(and(canFlipSwitches, hasBig('th'))),
591 'th-big-chest': fromBool(and(canFlipSwitches, hasBig('th'))),
592 'th-boss-defeated': fromBool(and(
597 'pd-stalfos-basement': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
598 'pd-big-key-chest': fromBool(hasSmall('pd', 6)),
599 'pd-arena-bridge': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
600 'pd-arena-ledge': fromBool(canShootArrows),
601 'pd-map-chest': fromBool(canShootArrows),
602 'pd-compass-chest': fromBool(hasSmall('pd', 4)),
603 'pd-basement-left': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))),
604 'pd-basement-right': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))),
605 'pd-harmless-hellway': fromBool(hasSmall('pd', 6)),
606 'pd-maze-top': fromBool(and(canDarkRoom, hasSmall('pd', 6))),
607 'pd-maze-bottom': fromBool(and(canDarkRoom, hasSmall('pd', 6))),
608 'pd-big-chest': fromBool(and(canDarkRoom, hasBig('pd'), hasSmall('pd', 6))),
609 'pd-boss-defeated': fromBool(and(
610 canDarkRoom, hasBig('pd'), hasSmall('pd', 6), canShootArrows, hasHammer, canKillBoss('pd'),
612 'sp-map-chest': fromBool(and(hasSmall('sp'), canBomb)),
613 'sp-big-chest': fromBool(and(hasSmall('sp'), hasHammer, hasBig('sp'))),
614 'sp-compass-chest': fromBool(and(hasSmall('sp'), hasHammer)),
615 'sp-west-chest': fromBool(and(hasSmall('sp'), hasHammer)),
616 'sp-big-key-chest': fromBool(and(hasSmall('sp'), hasHammer)),
617 'sp-flooded-left': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
618 'sp-flooded-right': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
619 'sp-waterfall': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
620 'sp-boss-defeated': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot, canKillBoss('sp'))),
621 'sw-big-chest': fromBool(and(canEnterSWFront, hasBig('sw'))),
622 'sw-bridge-chest': fromBool(canEnterSWBack),
623 'sw-boss-defeated': fromBool(and(
624 canEnterSWBack, canPassCurtains, hasFireRod, hasSmall('sw', 3), canKillBoss('sw'),
626 'tt-attic': fromBool(and(hasBig('tt'), hasSmall('tt'), canBomb)),
627 'tt-cell': fromBool(hasBig('tt')),
628 'tt-big-chest': fromBool(and(hasBig('tt'), hasSmall('tt'), hasHammer)),
629 'tt-boss-defeated': fromBool(and(hasBig('tt'), hasSmall('tt'), canKillBoss('tt'))),
630 'ip-big-key-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
631 'ip-map-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
632 'ip-spike-chest': fromBool(rightSideIP),
633 'ip-freezor-chest': fromBool(canMeltThings),
634 'ip-big-chest': fromBool(hasBig('ip')),
635 'ip-boss-defeated': fromBool(and(
639 or(hasSmall('ip', 2), and(hasSomaria, hasSmall('ip'))),
642 'mm-lobby-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
643 'mm-compass-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
644 'mm-big-key-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
645 'mm-big-chest': fromBool(hasBig('mm')),
646 'mm-map-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
647 'mm-boss-defeated': fromBool(and(hasBig('mm'), canDarkRoom, hasSomaria, canKillBoss('mm'))),
648 'tr-roller-left': fromBool(and(hasFireRod, hasSomaria, or(
650 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
651 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
653 'tr-roller-right': fromBool(and(hasFireRod, hasSomaria, or(
655 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
656 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
658 'tr-compass-chest': fromBool(and(hasSomaria, or(
660 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
661 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
663 'tr-chomps': fromBool(or(
664 and(canEnterTRFront, hasSmall('tr')),
667 and(canEnterTRBack, canDarkRoom, hasSomaria),
669 'tr-big-key-chest': fromBool(and(hasSmall('tr', 4), or(
670 and(canEnterTRFront, hasSomaria),
673 and(canEnterTRBack, canDarkRoom, hasSomaria),
675 'tr-big-chest': fromBool(canEnterTREast),
676 'tr-crysta-roller': fromBool(or(
677 and(hasBig('tr'), or(
678 and(canEnterTRFront, hasSomaria, hasSmall('tr', 2)),
682 and(canEnterTRBack, canDarkRoom, hasSomaria),
684 'tr-laser-bridge-top': fromBool(laserBridge),
685 'tr-laser-bridge-left': fromBool(laserBridge),
686 'tr-laser-bridge-right': fromBool(laserBridge),
687 'tr-laser-bridge-bottom': fromBool(laserBridge),
688 'tr-boss-defeated': fromBool(and(
698 fallback: fromBool(alwaysAvailable),
699 aginah: fromBool(canBomb),
700 blacksmith: fromBool(canRescueSmith),
701 'blinds-hut-top': fromBool(canBomb),
702 'bombos-tablet': fromBool(and(southDarkWorld, hasMirror, canTablet)),
703 'bonk-rocks': fromBool(canBonk),
704 brewery: fromBool(and(westDarkWorld, canBomb, hasMoonpearl)),
705 'bumper-cave': fromBool(and(westDarkWorld, hasMoonpearl, canLift, hasCape)),
706 'c-house': fromBool(and(westDarkWorld, hasMoonpearl)),
707 catfish: fromBool(and(eastDarkWorld, hasMoonpearl, canLift)),
708 'cave-45': fromBool(and(southDarkWorld, hasMirror)),
709 checkerboard: fromBool(and(mireArea, hasMirror)),
710 'chest-game': fromBool(and(westDarkWorld, hasMoonpearl)),
711 'chicken-house': fromBool(canBomb),
712 'desert-ledge': fromBool(canEnterDPFront),
713 'digging-game': fromBool(and(southDarkWorld, hasMoonpearl)),
714 'ether-tablet': fromBool(and(northDeathMountain, canTablet)),
715 'floating-island': fromBool(
716 and(eastDarkDeathMountain, hasMoonpearl, canLift, canBomb, hasMirror),
718 'flute-spot': fromBool(hasShovel),
719 'graveyard-ledge': fromBool(and(westDarkWorld, hasMoonpearl, hasMirror)),
720 'hammer-pegs': fromBool(and(westDarkWorld, hasHammer, hasMoonpearl, canHeavyLift)),
721 hobo: fromBool(canSwim),
722 'hookshot-cave-tl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
723 'hookshot-cave-tr': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
724 'hookshot-cave-bl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
725 'hookshot-cave-br': fromBool(
726 and(eastDarkDeathMountain, hasMoonpearl, canLift, or(hasHookshot, canBonk)),
728 'hype-cave-npc': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
729 'hype-cave-top': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
730 'hype-cave-right': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
731 'hype-cave-left': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
732 'hype-cave-bottom': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
733 'ice-rod-cave': fromBool(canBomb),
734 'kak-well-top': fromBool(canBomb),
735 'kings-tomb': fromBool(and(canBonk, or(canHeavyLift, and(westDarkWorld, hasMirror)))),
736 'lake-hylia-island': fromBool(
737 and(canSwim, hasMirror, hasMoonpearl, or(eastDarkWorld, southDarkWorld)),
739 library: fromBool(canBonk),
740 lumberjack: fromBool(and(canBonk, agaDead)),
741 'magic-bat': fromBool(and(hasPowder,
742 or(hasHammer, and(westDarkWorld, hasMoonpearl, canHeavyLift, hasMirror)),
744 'mimic-cave': fromBool(and(canEnterTRFront, canBomb, hasSmall('tr', 2), hasMirror, hasHammer)),
745 'mini-moldorm-left': fromBool(canBomb),
746 'mini-moldorm-right': fromBool(canBomb),
747 'mini-moldorm-far-left': fromBool(canBomb),
748 'mini-moldorm-far-right': fromBool(canBomb),
749 'mini-moldorm-npc': fromBool(canBomb),
750 'mire-shed-left': fromBool(and(mireArea, hasMoonpearl)),
751 'mire-shed-right': fromBool(and(mireArea, hasMoonpearl)),
752 'old-man': fromBool(and(westDeathMountain, canDarkRoom)),
753 'paradox-lower-far-left': fromBool(paradoxLower),
754 'paradox-lower-left': fromBool(paradoxLower),
755 'paradox-lower-right': fromBool(paradoxLower),
756 'paradox-lower-far-right': fromBool(paradoxLower),
757 'paradox-lower-mid': fromBool(paradoxLower),
758 'paradox-upper-left': fromBool(and(eastDeathMountain, canBomb)),
759 'paradox-upper-right': fromBool(and(eastDeathMountain, canBomb)),
760 pedestal: fromBool(hasPendants(3)),
761 'potion-shop': fromBool(hasMushroom),
762 'purple-chest': fromBool(and(canRescueSmith, hasMoonpearl, canHeavyLift)),
763 pyramid: fromBool(eastDarkWorld),
764 'pyramid-fairy-left': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
765 'pyramid-fairy-right': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
766 'race-game': fromBool(or(canBomb, canBonk)),
767 saha: fromBool(hasGreenPendant),
768 'saha-left': fromBool(or(canBomb, canBonk)),
769 'saha-mid': fromBool(or(canBomb, canBonk)),
770 'saha-right': fromBool(or(canBomb, canBonk)),
771 'sick-kid': fromBool(hasBottle(1)),
772 'spec-rock': fromBool(and(westDeathMountain, hasMirror)),
773 'spec-rock-cave': fromBool(westDeathMountain),
774 'spike-cave': fromBool(and(
775 westDarkDeathMountain,
779 or(hasByrna, and(hasCape, hasMagicBars(2))),
781 'spiral-cave': fromBool(eastDeathMountain),
782 stumpy: fromBool(and(southDarkWorld, hasMoonpearl)),
783 'super-bunny-top': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
784 'super-bunny-bottom': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
785 'waterfall-fairy-left': fromBool(canSwim),
786 'waterfall-fairy-right': fromBool(canSwim),
787 zora: fromBool(or(canLift, canSwim)),
788 'zora-ledge': fromBool(canSwim),
789 ct: fromBool(canEnterCT),
790 gt: fromBool(canEnterGT),
791 dp: fromBool(or(canEnterDPFront, canEnterDPBack)),
792 th: fromBool(canEnterTH),
793 pd: fromBool(canEnterPD),
794 sp: fromBool(canEnterSP),
795 sw: fromBool(or(canEnterSWFront, canEnterSWMid, canEnterSWBack)),
796 tt: fromBool(canEnterTT),
797 ip: fromBool(canEnterIP),
798 mm: fromBool(canEnterMM),
799 tr: fromBool(or(canEnterTRFront, canEnterTRWest, canEnterTREast, canEnterTRBack)),
800 ...Logic.dungeonInterior,
804 fallback: fromBool(alwaysAvailable),
805 aginah: fromBool(and(southLightWorld, hasMoonpearl, canBomb)),
806 blacksmith: fromBool(and(or(canHeavyLift, hasMirror), westLightWorld)),
807 'blinds-hut-top': fromBool(and(westLightWorld, hasMoonpearl, canBomb)),
808 'blinds-hut-far-left': fromBool(and(westLightWorld, hasMoonpearl)),
809 'blinds-hut-left': fromBool(and(westLightWorld, hasMoonpearl)),
810 'blinds-hut-right': fromBool(and(westLightWorld, hasMoonpearl)),
811 'blinds-hut-far-right': fromBool(and(westLightWorld, hasMoonpearl)),
812 'bombos-tablet': fromBool(and(southLightWorld, canTablet)),
813 'bonk-rocks': fromBool(and(westLightWorld, hasMoonpearl, canBonk)),
814 'bottle-vendor': fromBool(westLightWorld),
815 brewery: fromBool(canBomb),
816 'bumper-cave': fromBool(and(canLift, hasCape, hasMoonpearl, hasMirror, westLightWorld)),
817 catfish: fromBool(or(
818 and(eastDarkWorld, canLift),
819 and(hasMirror, southLightWorld, hasMoonpearl, canSwim),
821 'cave-45': fromBool(and(southLightWorld, hasMoonpearl)),
822 checkerboard: fromBool(and(southLightWorld, hasMoonpearl, canLift)),
823 'chicken-house': fromBool(and(westLightWorld, hasMoonpearl, canBomb)),
824 'desert-ledge': fromBool(and(hasMoonpearl, canEnterDPFront)),
825 'ether-tablet': fromBool(and(northDeathMountain, canTablet)),
826 'floating-island': fromBool(and(eastDeathMountain)),
827 'flooded-chest': fromBool(and(southLightWorld, hasMoonpearl)),
828 'flute-spot': fromBool(and(southLightWorld, hasMoonpearl, hasShovel)),
829 'graveyard-ledge': fromBool(and(westLightWorld, hasMoonpearl)),
830 'hammer-pegs': fromBool(and(hasHammer, or(canHeavyLift, and(westLightWorld, hasMirror)))),
831 hobo: fromBool(and(southLightWorld, hasMoonpearl, canSwim)),
832 'hookshot-cave-tl': fromBool(and(
833 eastDarkDeathMountain,
835 or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
837 'hookshot-cave-tr': fromBool(and(
838 eastDarkDeathMountain,
840 or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
842 'hookshot-cave-bl': fromBool(and(
843 eastDarkDeathMountain,
845 or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
847 'hookshot-cave-br': fromBool(and(
848 eastDarkDeathMountain,
849 or(canBonk, hasHookshot),
850 or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
852 'hype-cave-npc': fromBool(canBomb),
853 'hype-cave-top': fromBool(canBomb),
854 'hype-cave-right': fromBool(canBomb),
855 'hype-cave-left': fromBool(canBomb),
856 'hype-cave-bottom': fromBool(canBomb),
857 'ice-rod-cave': fromBool(and(southLightWorld, hasMoonpearl, canBomb)),
858 'kak-well-top': fromBool(and(westLightWorld, hasMoonpearl, canBomb)),
859 'kak-well-left': fromBool(and(westLightWorld, hasMoonpearl)),
860 'kak-well-mid': fromBool(and(westLightWorld, hasMoonpearl)),
861 'kak-well-right': fromBool(and(westLightWorld, hasMoonpearl)),
862 'kak-well-bottom': fromBool(and(westLightWorld, hasMoonpearl)),
863 'kings-tomb': fromBool(and(westLightWorld, hasMoonpearl, canBonk, canHeavyLift)),
864 'lake-hylia-island': fromBool(
865 and(southLightWorld, hasMoonpearl, canSwim),
867 library: fromBool(and(southLightWorld, hasMoonpearl, canBonk)),
868 lumberjack: fromBool(and(westLightWorld, hasMoonpearl, canBonk, agaDead)),
869 'lost-woods-hideout': fromBool(and(westLightWorld, hasMoonpearl)),
870 'magic-bat': fromBool(and(westLightWorld, hasMoonpearl, hasPowder, hasHammer)),
871 'maze-race': fromBool(and(southLightWorld, hasMoonpearl, or(canBomb, canBonk))),
872 'mimic-cave': fromBool(and(
877 'mini-moldorm-far-left': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
878 'mini-moldorm-left': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
879 'mini-moldorm-right': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
880 'mini-moldorm-far-right': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
881 'mini-moldorm-npc': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
882 'mire-shed-left': fromBool(mireArea),
883 'mire-shed-right': fromBool(mireArea),
884 'mushroom-spot': fromBool(and(westLightWorld, hasMoonpearl)),
885 'old-man': fromBool(and(westDeathMountain, canDarkRoom)),
886 'paradox-lower-far-left': fromBool(and(hasMoonpearl, paradoxLower)),
887 'paradox-lower-left': fromBool(and(hasMoonpearl, paradoxLower)),
888 'paradox-lower-mid': fromBool(and(hasMoonpearl, paradoxLower)),
889 'paradox-lower-right': fromBool(and(hasMoonpearl, paradoxLower)),
890 'paradox-lower-far-right': fromBool(and(hasMoonpearl, paradoxLower)),
891 'paradox-upper-left': fromBool(and(eastDeathMountain, hasMoonpearl, canBomb)),
892 'paradox-upper-right': fromBool(and(eastDeathMountain, hasMoonpearl, canBomb)),
893 pedestal: fromBool(and(westLightWorld, hasPendants(3))),
894 'potion-shop': fromBool(and(eastLightWorld, hasMushroom, hasMoonpearl)),
895 'purple-chest': fromBool(and(or(canHeavyLift, hasMirror), westLightWorld, southLightWorld)),
896 pyramid: fromBool(eastDarkWorld),
897 'pyramid-fairy-left': fromBool(and(hasRedCrystals(2), hasMirror)),
898 'pyramid-fairy-right': fromBool(and(hasRedCrystals(2), hasMirror)),
899 'race-game': fromBool(and(westLightWorld, hasMoonpearl, or(canBomb, canBonk))),
900 saha: fromBool(and(eastLightWorld, hasGreenPendant)),
901 'saha-left': fromBool(and(eastLightWorld, hasMoonpearl, or(canBomb, canBonk))),
902 'saha-mid': fromBool(and(eastLightWorld, hasMoonpearl, or(canBomb, canBonk))),
903 'saha-right': fromBool(and(eastLightWorld, or(canBomb, canBonk))),
904 'secret-passage': fromBool(and(eastLightWorld, hasMoonpearl)),
905 'sick-kid': fromBool(and(westLightWorld, hasBottle(1))),
906 'spec-rock': fromBool(northDeathMountain),
907 'spec-rock-cave': fromBool(westDeathMountain),
908 'spike-cave': fromBool(and(
909 westDarkDeathMountain,
912 or(hasByrna, and(hasCape, hasMagicBars(2))),
914 'spiral-cave': fromBool(and(
918 'sunken-treasure': fromBool(and(southLightWorld, hasMoonpearl)),
919 'super-bunny-top': fromBool(eastDarkDeathMountain),
920 'super-bunny-bottom': fromBool(eastDarkDeathMountain),
921 tavern: fromBool(and(westLightWorld, hasMoonpearl)),
922 uncle: fromBool(and(eastLightWorld, hasMoonpearl)),
923 'waterfall-fairy-left': fromBool(and(eastLightWorld, hasMoonpearl, canSwim)),
924 'waterfall-fairy-right': fromBool(and(eastLightWorld, hasMoonpearl, canSwim)),
925 zora: fromBool(and(eastLightWorld, hasMoonpearl, or(canLift, canSwim))),
926 'zora-ledge': fromBool(and(eastLightWorld, hasMoonpearl, canSwim)),
927 hc: fromBool(canEnterHC),
928 ct: fromBool(canEnterCT),
929 gt: fromBool(canEnterGT),
930 ep: fromBool(canEnterEP),
931 dp: fromBool(canEnterDPFront),
932 th: fromBool(canEnterTH),
933 pd: fromBool(canEnterPD),
934 sp: fromBool(canEnterSP),
935 sw: fromBool(or(canEnterSWFront, canEnterSWMid, canEnterSWBack)),
936 tt: fromBool(canEnterTT),
937 ip: fromBool(canEnterIP),
938 mm: fromBool(canEnterMM),
939 tr: fromBool(or(canEnterTRFront, canEnterTRWest, canEnterTREast, canEnterTRBack)),
940 ...Logic.dungeonInterior,
943 export default Logic;