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(hasMoonpearl, eastLightWorld)),
271 and(canLift, hasHammer),
276 const westDarkWorld = when(isInverted,
281 and(canLift, hasHammer),
283 and(eastDarkWorld, hasHookshot, or(canSwim, canLift, hasHammer)),
288 const southDarkWorld = when(isInverted,
292 and(eastDarkWorld, hasMoonpearl, hasHammer),
296 const mireArea = when(isInverted,
297 or(canFly, and(hasMirror, southLightWorld)),
298 and(canFly, canHeavyLift),
304 aga: or(hasBugnet, hasHammer, hasSword()),
306 hasSword(), hasHammer, canShootArrows, hasBoom,
307 and(hasMagicBars(4), or(hasFireRod, hasIceRod)),
308 and(hasMagicBars(2), or(hasByrna, hasSomaria)),
310 arrghus: and(hasHookshot, or(
313 and(or(hasMagicBars(2), canShootArrows), or(hasFireRod, hasIceRod)),
315 blind: or(hasSword(), hasHammer, hasSomaria, hasByrna),
316 helma: and(or(canBomb, hasHammer), or(hasSword(), canShootArrows)),
317 kholdstare: and(canMeltThings, or(
320 and(hasFireRod, hasMagicBars(3)),
321 and(hasFireRod, hasBombos, hasMagicBars(2), canMedallion),
324 hasSword(), hasHammer, canShootArrows, hasFireRod, hasIceRod, hasByrna, hasSomaria,
326 moldorm: or(hasSword(), hasHammer),
330 and(hasMagicBars(2), or(hasFireRod, hasSomaria, hasByrna)),
333 trinexx: and(hasFireRod, hasIceRod, or(
336 and(hasMagicBars(2), hasSword(2)),
337 and(hasMagicBars(4), hasSword(1)),
339 vitreous: or(hasSword(), hasHammer, canShootArrows),
342 const canKillBoss = dungeon => (config, dungeons, state) => {
343 const boss = getDungeonBoss(state, dungeons.find(d => d.id === dungeon));
344 return BOSS_RULES[boss](config, dungeons, state);
347 const canKillGTBoss = which => (config, dungeons, state) => {
348 const boss = getGTBoss(state, which);
349 return BOSS_RULES[boss](config, dungeons, state);
354 const canEnterHC = when(isInverted,
355 and(hasMoonpearl, eastLightWorld),
359 const canEnterCT = when(isInverted,
360 westDarkDeathMountain,
361 or(hasCape, hasSword(2)),
364 const canEnterGT = when(isInverted,
365 and(eastLightWorld, hasGTCrystals, hasMoonpearl),
366 and(eastDarkDeathMountain, hasGTCrystals, hasMoonpearl),
369 const canEnterEP = when(isInverted,
370 and(hasMoonpearl, eastLightWorld),
374 const canEnterDPFront = when(isInverted,
375 and(southLightWorld, hasBook),
376 or(hasBook, and(mireArea, hasMirror)),
378 const canEnterDPBack = when(isInverted,
379 and(canEnterDPFront, canLift),
380 or(and(canEnterDPFront, canLift), and(mireArea, hasMirror)),
383 const canEnterTH = northDeathMountain;
385 const canEnterPD = when(isInverted,
387 and(eastDarkWorld, hasMoonpearl),
390 const canEnterSP = when(isInverted,
391 and(southLightWorld, hasMirror, hasMoonpearl, canSwim),
392 and(southDarkWorld, hasMirror, hasMoonpearl, canSwim),
395 const canEnterSWFront = when(isInverted,
397 and(westDarkWorld, hasMoonpearl),
399 const canEnterSWMid = canEnterSWFront;
400 const canEnterSWBack = and(canEnterSWMid, hasFireRod);
402 const canEnterTT = when(isInverted,
404 and(westDarkWorld, hasMoonpearl),
407 const canEnterIP = when(isInverted,
408 and(canSwim, canMeltThings),
409 and(canSwim, canHeavyLift, hasMoonpearl, canMeltThings),
411 const rightSideIP = or(hasHookshot, hasSmall('ip'));
413 const canEnterMM = when(isInverted,
418 or(canBonk, hasHookshot),
426 or(canBonk, hasHookshot),
431 const canEnterTRFront = when(isInverted,
433 eastDarkDeathMountain,
448 const canEnterTRWest = when(isInverted,
449 and(eastDeathMountain, hasMirror),
452 const canEnterTREast = and(canEnterTRWest, or(hasHookshot, hasSomaria));
453 const canEnterTRBack = when(isInverted,
454 and(eastDeathMountain, hasMirror),
457 const laserBridge = or(
459 or(canEnterTRFront, canEnterTRWest, canEnterTREast),
470 const paradoxLower = and(eastDeathMountain, or(canBomb, hasBoom, canShootArrows, hasSomaria));
472 const canBridgeRedBomb = or(
473 and(hasMoonpearl, hasHammer),
474 and(agaDead, hasMirror),
477 const canRescueSmith = and(westDarkWorld, hasMoonpearl, canHeavyLift);
481 Logic.dungeonInterior = {
482 'hc-boom': fromBool(and(hasSmall('hc'), canKill())),
483 'hc-cell': fromBool(and(hasSmall('hc'), canKill())),
484 'dark-cross': fromBool(canTorchDarkRoom),
485 'sewers-left': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
486 'sewers-mid': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
487 'sewers-right': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
488 'ct-1': fromBool(canKill()),
489 'ct-2': fromBool(and(canKill(), hasSmall('ct'), canDarkRoom)),
490 'ct-boss-killable': fromBool(and(
491 canKill(), hasSmall('ct', 2), canDarkRoom, canPassCurtains, canKillBoss('ct'),
493 'gt-tile-room': fromBool(hasSomaria),
494 'gt-compass-tl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
495 'gt-compass-tr': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
496 'gt-compass-bl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
497 'gt-compass-br': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
498 'gt-torch': fromBool(canBonk),
499 'gt-dm-tl': fromBool(and(hasHammer, hasHookshot)),
500 'gt-dm-tr': fromBool(and(hasHammer, hasHookshot)),
501 'gt-dm-bl': fromBool(and(hasHammer, hasHookshot)),
502 'gt-dm-br': fromBool(and(hasHammer, hasHookshot)),
503 'gt-map-chest': fromBool(and(hasHammer, or(hasHookshot, canBonk), hasSmall('gt', 4))),
504 'gt-firesnake': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 3))),
505 'gt-rando-tl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
506 'gt-rando-tr': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
507 'gt-rando-bl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
508 'gt-rando-br': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
509 'gt-bobs-chest': fromBool(and(
510 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
513 'gt-ice-left': fromBool(and(
514 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
516 canKillGTBoss('bot'),
518 'gt-ice-mid': fromBool(and(
519 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
521 canKillGTBoss('bot'),
523 'gt-ice-right': fromBool(and(
524 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
526 canKillGTBoss('bot'),
528 'gt-big-chest': fromBool(and(
529 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
533 'gt-helma-left': fromBool(and(
538 canKillGTBoss('mid'),
540 'gt-helma-right': fromBool(and(
545 canKillGTBoss('mid'),
547 'gt-pre-moldorm': fromBool(and(
552 canKillGTBoss('mid'),
554 'gt-post-moldorm': fromBool(and(
559 canKillGTBoss('mid'),
560 canKillGTBoss('top'),
563 'gt-boss-killable': fromBool(and(
568 canKillGTBoss('mid'),
569 canKillGTBoss('top'),
573 'ep-big-chest': fromBool(hasBig('ep')),
574 'ep-big-key-chest': fromBool(canDarkRoom),
575 'ep-boss-defeated': fromBool(and(
576 canShootArrows, canTorchDarkRoom, hasBig('ep'), canKillBoss('ep'),
578 'dp-big-chest': fromBool(and(canEnterDPFront, hasBig('dp'))),
579 'dp-big-key-chest': fromBool(and(canEnterDPFront, hasSmall('dp'), canKill())),
580 'dp-compass-chest': fromBool(and(canEnterDPFront, hasSmall('dp'))),
581 'dp-map-chest': fromBool(canEnterDPFront),
582 'dp-torch': fromBool(and(canEnterDPFront, canBonk)),
583 'dp-boss-defeated': fromBool(and(
590 'th-basement-cage': fromBool(canFlipSwitches),
591 'th-map-chest': fromBool(canFlipSwitches),
592 'th-big-key-chest': fromBool(and(canFlipSwitches, hasSmall('th'), canTorch)),
593 'th-compass-chest': fromBool(and(canFlipSwitches, hasBig('th'))),
594 'th-big-chest': fromBool(and(canFlipSwitches, hasBig('th'))),
595 'th-boss-defeated': fromBool(and(
600 'pd-stalfos-basement': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
601 'pd-big-key-chest': fromBool(hasSmall('pd', 6)),
602 'pd-arena-bridge': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
603 'pd-arena-ledge': fromBool(canShootArrows),
604 'pd-map-chest': fromBool(canShootArrows),
605 'pd-compass-chest': fromBool(hasSmall('pd', 4)),
606 'pd-basement-left': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))),
607 'pd-basement-right': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))),
608 'pd-harmless-hellway': fromBool(hasSmall('pd', 6)),
609 'pd-maze-top': fromBool(and(canDarkRoom, hasSmall('pd', 6))),
610 'pd-maze-bottom': fromBool(and(canDarkRoom, hasSmall('pd', 6))),
611 'pd-big-chest': fromBool(and(canDarkRoom, hasBig('pd'), hasSmall('pd', 6))),
612 'pd-boss-defeated': fromBool(and(
613 canDarkRoom, hasBig('pd'), hasSmall('pd', 6), canShootArrows, hasHammer, canKillBoss('pd'),
615 'sp-map-chest': fromBool(and(hasSmall('sp'), canBomb)),
616 'sp-big-chest': fromBool(and(hasSmall('sp'), hasHammer, hasBig('sp'))),
617 'sp-compass-chest': fromBool(and(hasSmall('sp'), hasHammer)),
618 'sp-west-chest': fromBool(and(hasSmall('sp'), hasHammer)),
619 'sp-big-key-chest': fromBool(and(hasSmall('sp'), hasHammer)),
620 'sp-flooded-left': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
621 'sp-flooded-right': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
622 'sp-waterfall': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
623 'sp-boss-defeated': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot, canKillBoss('sp'))),
624 'sw-big-chest': fromBool(and(canEnterSWFront, hasBig('sw'))),
625 'sw-bridge-chest': fromBool(canEnterSWBack),
626 'sw-boss-defeated': fromBool(and(
627 canEnterSWBack, canPassCurtains, hasFireRod, hasSmall('sw', 3), canKillBoss('sw'),
629 'tt-attic': fromBool(and(hasBig('tt'), hasSmall('tt'), canBomb)),
630 'tt-cell': fromBool(hasBig('tt')),
631 'tt-big-chest': fromBool(and(hasBig('tt'), hasSmall('tt'), hasHammer)),
632 'tt-boss-defeated': fromBool(and(hasBig('tt'), hasSmall('tt'), canKillBoss('tt'))),
633 'ip-big-key-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
634 'ip-map-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
635 'ip-spike-chest': fromBool(rightSideIP),
636 'ip-freezor-chest': fromBool(canMeltThings),
637 'ip-big-chest': fromBool(hasBig('ip')),
638 'ip-boss-defeated': fromBool(and(
642 or(hasSmall('ip', 2), and(hasSomaria, hasSmall('ip'))),
645 'mm-lobby-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
646 'mm-compass-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
647 'mm-big-key-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
648 'mm-big-chest': fromBool(hasBig('mm')),
649 'mm-map-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
650 'mm-boss-defeated': fromBool(and(hasBig('mm'), canDarkRoom, hasSomaria, canKillBoss('mm'))),
651 'tr-roller-left': fromBool(and(hasFireRod, hasSomaria, or(
653 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
654 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
656 'tr-roller-right': fromBool(and(hasFireRod, hasSomaria, or(
658 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
659 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
661 'tr-compass-chest': fromBool(and(hasSomaria, or(
663 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
664 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
666 'tr-chomps': fromBool(or(
667 and(canEnterTRFront, hasSmall('tr')),
670 and(canEnterTRBack, canDarkRoom, hasSomaria),
672 'tr-big-key-chest': fromBool(and(hasSmall('tr', 4), or(
673 and(canEnterTRFront, hasSomaria),
676 and(canEnterTRBack, canDarkRoom, hasSomaria),
678 'tr-big-chest': fromBool(canEnterTREast),
679 'tr-crysta-roller': fromBool(or(
680 and(hasBig('tr'), or(
681 and(canEnterTRFront, hasSomaria, hasSmall('tr', 2)),
685 and(canEnterTRBack, canDarkRoom, hasSomaria),
687 'tr-laser-bridge-top': fromBool(laserBridge),
688 'tr-laser-bridge-left': fromBool(laserBridge),
689 'tr-laser-bridge-right': fromBool(laserBridge),
690 'tr-laser-bridge-bottom': fromBool(laserBridge),
691 'tr-boss-defeated': fromBool(and(
701 fallback: fromBool(alwaysAvailable),
702 aginah: fromBool(canBomb),
703 blacksmith: fromBool(canRescueSmith),
704 'blinds-hut-top': fromBool(canBomb),
705 'bombos-tablet': fromBool(and(southDarkWorld, hasMirror, canTablet)),
706 'bonk-rocks': fromBool(canBonk),
707 brewery: fromBool(and(westDarkWorld, canBomb, hasMoonpearl)),
708 'bumper-cave': fromBool(and(westDarkWorld, hasMoonpearl, canLift, hasCape)),
709 'c-house': fromBool(and(westDarkWorld, hasMoonpearl)),
710 catfish: fromBool(and(eastDarkWorld, hasMoonpearl, canLift)),
711 'cave-45': fromBool(and(southDarkWorld, hasMirror)),
712 checkerboard: fromBool(and(mireArea, hasMirror)),
713 'chest-game': fromBool(and(westDarkWorld, hasMoonpearl)),
714 'chicken-house': fromBool(canBomb),
715 'desert-ledge': fromBool(canEnterDPFront),
716 'digging-game': fromBool(and(southDarkWorld, hasMoonpearl)),
717 'ether-tablet': fromBool(and(northDeathMountain, canTablet)),
718 'floating-island': fromBool(
719 and(eastDarkDeathMountain, hasMoonpearl, canLift, canBomb, hasMirror),
721 'flute-spot': fromBool(hasShovel),
722 'graveyard-ledge': fromBool(and(westDarkWorld, hasMoonpearl, hasMirror)),
723 'hammer-pegs': fromBool(and(westDarkWorld, hasHammer, hasMoonpearl, canHeavyLift)),
724 hobo: fromBool(canSwim),
725 'hookshot-cave-tl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
726 'hookshot-cave-tr': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
727 'hookshot-cave-bl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
728 'hookshot-cave-br': fromBool(
729 and(eastDarkDeathMountain, hasMoonpearl, canLift, or(hasHookshot, canBonk)),
731 'hype-cave-npc': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
732 'hype-cave-top': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
733 'hype-cave-right': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
734 'hype-cave-left': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
735 'hype-cave-bottom': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
736 'ice-rod-cave': fromBool(canBomb),
737 'kak-well-top': fromBool(canBomb),
738 'kings-tomb': fromBool(and(canBonk, or(canHeavyLift, and(westDarkWorld, hasMirror)))),
739 'lake-hylia-island': fromBool(
740 and(canSwim, hasMirror, hasMoonpearl, or(eastDarkWorld, southDarkWorld)),
742 library: fromBool(canBonk),
743 lumberjack: fromBool(and(canBonk, agaDead)),
744 'magic-bat': fromBool(and(hasPowder,
745 or(hasHammer, and(westDarkWorld, hasMoonpearl, canHeavyLift, hasMirror)),
747 'mimic-cave': fromBool(and(canEnterTRFront, canBomb, hasSmall('tr', 2), hasMirror, hasHammer)),
748 'mini-moldorm-left': fromBool(canBomb),
749 'mini-moldorm-right': fromBool(canBomb),
750 'mini-moldorm-far-left': fromBool(canBomb),
751 'mini-moldorm-far-right': fromBool(canBomb),
752 'mini-moldorm-npc': fromBool(canBomb),
753 'mire-shed-left': fromBool(and(mireArea, hasMoonpearl)),
754 'mire-shed-right': fromBool(and(mireArea, hasMoonpearl)),
755 'old-man': fromBool(and(westDeathMountain, canDarkRoom)),
756 'paradox-lower-far-left': fromBool(paradoxLower),
757 'paradox-lower-left': fromBool(paradoxLower),
758 'paradox-lower-right': fromBool(paradoxLower),
759 'paradox-lower-far-right': fromBool(paradoxLower),
760 'paradox-lower-mid': fromBool(paradoxLower),
761 'paradox-upper-left': fromBool(and(eastDeathMountain, canBomb)),
762 'paradox-upper-right': fromBool(and(eastDeathMountain, canBomb)),
763 pedestal: fromBool(hasPendants(3)),
764 'potion-shop': fromBool(hasMushroom),
765 'purple-chest': fromBool(and(canRescueSmith, hasMoonpearl, canHeavyLift)),
766 pyramid: fromBool(eastDarkWorld),
767 'pyramid-fairy-left': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
768 'pyramid-fairy-right': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
769 'race-game': fromBool(or(canBomb, canBonk)),
770 saha: fromBool(hasGreenPendant),
771 'saha-left': fromBool(or(canBomb, canBonk)),
772 'saha-mid': fromBool(or(canBomb, canBonk)),
773 'saha-right': fromBool(or(canBomb, canBonk)),
774 'sick-kid': fromBool(hasBottle(1)),
775 'spec-rock': fromBool(and(westDeathMountain, hasMirror)),
776 'spec-rock-cave': fromBool(westDeathMountain),
777 'spike-cave': fromBool(and(
778 westDarkDeathMountain,
782 or(hasByrna, and(hasCape, hasMagicBars(2))),
784 'spiral-cave': fromBool(eastDeathMountain),
785 stumpy: fromBool(and(southDarkWorld, hasMoonpearl)),
786 'super-bunny-top': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
787 'super-bunny-bottom': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
788 'waterfall-fairy-left': fromBool(canSwim),
789 'waterfall-fairy-right': fromBool(canSwim),
790 zora: fromBool(or(canLift, canSwim)),
791 'zora-ledge': fromBool(canSwim),
792 ct: fromBool(canEnterCT),
793 gt: fromBool(canEnterGT),
794 dp: fromBool(or(canEnterDPFront, canEnterDPBack)),
795 th: fromBool(canEnterTH),
796 pd: fromBool(canEnterPD),
797 sp: fromBool(canEnterSP),
798 sw: fromBool(or(canEnterSWFront, canEnterSWMid, canEnterSWBack)),
799 tt: fromBool(canEnterTT),
800 ip: fromBool(canEnterIP),
801 mm: fromBool(canEnterMM),
802 tr: fromBool(or(canEnterTRFront, canEnterTRWest, canEnterTREast, canEnterTRBack)),
803 ...Logic.dungeonInterior,
807 fallback: fromBool(alwaysAvailable),
808 aginah: fromBool(and(southLightWorld, hasMoonpearl, canBomb)),
809 blacksmith: fromBool(and(or(canHeavyLift, hasMirror), westLightWorld)),
810 'blinds-hut-top': fromBool(and(westLightWorld, hasMoonpearl, canBomb)),
811 'blinds-hut-far-left': fromBool(and(westLightWorld, hasMoonpearl)),
812 'blinds-hut-left': fromBool(and(westLightWorld, hasMoonpearl)),
813 'blinds-hut-right': fromBool(and(westLightWorld, hasMoonpearl)),
814 'blinds-hut-far-right': fromBool(and(westLightWorld, hasMoonpearl)),
815 'bombos-tablet': fromBool(and(southLightWorld, canTablet)),
816 'bonk-rocks': fromBool(and(westLightWorld, hasMoonpearl, canBonk)),
817 'bottle-vendor': fromBool(westLightWorld),
818 brewery: fromBool(canBomb),
819 'bumper-cave': fromBool(and(canLift, hasCape, hasMoonpearl, hasMirror, westLightWorld)),
820 catfish: fromBool(or(
821 and(eastDarkWorld, canLift),
822 and(hasMirror, southLightWorld, hasMoonpearl, canSwim),
824 'cave-45': fromBool(and(southLightWorld, hasMoonpearl)),
825 checkerboard: fromBool(and(southLightWorld, hasMoonpearl, canLift)),
826 'chicken-house': fromBool(and(westLightWorld, hasMoonpearl, canBomb)),
827 'desert-ledge': fromBool(and(hasMoonpearl, canEnterDPFront)),
828 'ether-tablet': fromBool(and(northDeathMountain, canTablet)),
829 'floating-island': fromBool(and(eastDeathMountain)),
830 'flooded-chest': fromBool(and(southLightWorld, hasMoonpearl)),
831 'flute-spot': fromBool(and(southLightWorld, hasMoonpearl, hasShovel)),
832 'graveyard-ledge': fromBool(and(westLightWorld, hasMoonpearl)),
833 'hammer-pegs': fromBool(and(hasHammer, or(canHeavyLift, and(westLightWorld, hasMirror)))),
834 hobo: fromBool(and(southLightWorld, hasMoonpearl, canSwim)),
835 'hookshot-cave-tl': fromBool(and(
836 eastDarkDeathMountain,
838 or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
840 'hookshot-cave-tr': fromBool(and(
841 eastDarkDeathMountain,
843 or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
845 'hookshot-cave-bl': fromBool(and(
846 eastDarkDeathMountain,
848 or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
850 'hookshot-cave-br': fromBool(and(
851 eastDarkDeathMountain,
852 or(canBonk, hasHookshot),
853 or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
855 'hype-cave-npc': fromBool(canBomb),
856 'hype-cave-top': fromBool(canBomb),
857 'hype-cave-right': fromBool(canBomb),
858 'hype-cave-left': fromBool(canBomb),
859 'hype-cave-bottom': fromBool(canBomb),
860 'ice-rod-cave': fromBool(and(southLightWorld, hasMoonpearl, canBomb)),
861 'kak-well-top': fromBool(and(westLightWorld, hasMoonpearl, canBomb)),
862 'kak-well-left': fromBool(and(westLightWorld, hasMoonpearl)),
863 'kak-well-mid': fromBool(and(westLightWorld, hasMoonpearl)),
864 'kak-well-right': fromBool(and(westLightWorld, hasMoonpearl)),
865 'kak-well-bottom': fromBool(and(westLightWorld, hasMoonpearl)),
866 'kings-tomb': fromBool(and(westLightWorld, hasMoonpearl, canBonk, canHeavyLift)),
867 'lake-hylia-island': fromBool(
868 and(southLightWorld, hasMoonpearl, canSwim),
870 library: fromBool(and(southLightWorld, hasMoonpearl, canBonk)),
871 lumberjack: fromBool(and(westLightWorld, hasMoonpearl, canBonk, agaDead)),
872 'lost-woods-hideout': fromBool(and(westLightWorld, hasMoonpearl)),
873 'magic-bat': fromBool(and(westLightWorld, hasMoonpearl, hasPowder, hasHammer)),
874 'maze-race': fromBool(and(southLightWorld, hasMoonpearl, or(canBomb, canBonk))),
875 'mimic-cave': fromBool(and(
880 'mini-moldorm-far-left': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
881 'mini-moldorm-left': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
882 'mini-moldorm-right': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
883 'mini-moldorm-far-right': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
884 'mini-moldorm-npc': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
885 'mire-shed-left': fromBool(mireArea),
886 'mire-shed-right': fromBool(mireArea),
887 'mushroom-spot': fromBool(and(westLightWorld, hasMoonpearl)),
888 'old-man': fromBool(and(westDeathMountain, canDarkRoom)),
889 'paradox-lower-far-left': fromBool(and(hasMoonpearl, paradoxLower)),
890 'paradox-lower-left': fromBool(and(hasMoonpearl, paradoxLower)),
891 'paradox-lower-mid': fromBool(and(hasMoonpearl, paradoxLower)),
892 'paradox-lower-right': fromBool(and(hasMoonpearl, paradoxLower)),
893 'paradox-lower-far-right': fromBool(and(hasMoonpearl, paradoxLower)),
894 'paradox-upper-left': fromBool(and(eastDeathMountain, hasMoonpearl, canBomb)),
895 'paradox-upper-right': fromBool(and(eastDeathMountain, hasMoonpearl, canBomb)),
896 pedestal: fromBool(and(westLightWorld, hasPendants(3))),
897 'potion-shop': fromBool(and(eastLightWorld, hasMushroom, hasMoonpearl)),
898 'purple-chest': fromBool(and(or(canHeavyLift, hasMirror), westLightWorld, southLightWorld)),
899 pyramid: fromBool(eastDarkWorld),
900 'pyramid-fairy-left': fromBool(and(hasRedCrystals(2), hasMirror)),
901 'pyramid-fairy-right': fromBool(and(hasRedCrystals(2), hasMirror)),
902 'race-game': fromBool(and(westLightWorld, hasMoonpearl, or(canBomb, canBonk))),
903 saha: fromBool(and(eastLightWorld, hasGreenPendant)),
904 'saha-left': fromBool(and(eastLightWorld, hasMoonpearl, or(canBomb, canBonk))),
905 'saha-mid': fromBool(and(eastLightWorld, hasMoonpearl, or(canBomb, canBonk))),
906 'saha-right': fromBool(and(eastLightWorld, or(canBomb, canBonk))),
907 'secret-passage': fromBool(and(eastLightWorld, hasMoonpearl)),
908 'sick-kid': fromBool(and(westLightWorld, hasBottle(1))),
909 'spec-rock': fromBool(northDeathMountain),
910 'spec-rock-cave': fromBool(westDeathMountain),
911 'spike-cave': fromBool(and(
912 westDarkDeathMountain,
915 or(hasByrna, and(hasCape, hasMagicBars(2))),
917 'spiral-cave': fromBool(and(
921 'sunken-treasure': fromBool(and(southLightWorld, hasMoonpearl)),
922 'super-bunny-top': fromBool(eastDarkDeathMountain),
923 'super-bunny-bottom': fromBool(eastDarkDeathMountain),
924 tavern: fromBool(and(westLightWorld, hasMoonpearl)),
925 uncle: fromBool(and(eastLightWorld, hasMoonpearl)),
926 'waterfall-fairy-left': fromBool(and(eastLightWorld, hasMoonpearl, canSwim)),
927 'waterfall-fairy-right': fromBool(and(eastLightWorld, hasMoonpearl, canSwim)),
928 zora: fromBool(and(eastLightWorld, hasMoonpearl, or(canLift, canSwim))),
929 'zora-ledge': fromBool(and(eastLightWorld, hasMoonpearl, canSwim)),
930 hc: fromBool(canEnterHC),
931 ct: fromBool(canEnterCT),
932 gt: fromBool(canEnterGT),
933 ep: fromBool(canEnterEP),
934 dp: fromBool(canEnterDPFront),
935 th: fromBool(canEnterTH),
936 pd: fromBool(canEnterPD),
937 sp: fromBool(canEnterSP),
938 sw: fromBool(or(canEnterSWFront, canEnterSWMid, canEnterSWBack)),
939 tt: fromBool(canEnterTT),
940 ip: fromBool(canEnterIP),
941 mm: fromBool(canEnterMM),
942 tr: fromBool(or(canEnterTRFront, canEnterTRWest, canEnterTREast, canEnterTRBack)),
943 ...Logic.dungeonInterior,
946 export default Logic;