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 fromBool = b => (...args) => b(...args) ? 'available' : 'unavailable';
18 const agaDead = (config, dungeons, state) =>
19 hasDungeonBoss(state, dungeons.find(d => d.id === 'ct'));
21 const countCrystals = (config, dungeons, state) => dungeons
23 (getDungeonPrize(state, dungeon) || 'crystal').endsWith('crystal') &&
25 hasDungeonPrize(state, dungeon)
28 const countRedCrystals = (config, dungeons, state) => dungeons
30 getDungeonPrize(state, dungeon) === 'red-crystal' &&
31 hasDungeonPrize(state, dungeon)
34 const hasRedCrystals = n => (...args) => countRedCrystals(...args) >= n;
36 const hasGTCrystals = (config, dungeons, state) =>
37 countCrystals(config, dungeons, state) >= getGTCrystals(state);
39 const countPendants = (config, dungeons, state) => dungeons
41 (getDungeonPrize(state, dungeon) || '').endsWith('pendant') &&
42 hasDungeonPrize(state, dungeon)
45 const hasGreenPendant = (config, dungeons, state) => dungeons
47 getDungeonPrize(state, dungeon) === 'green-pendant' &&
48 hasDungeonPrize(state, dungeon)
51 const hasPendants = n => (...args) => countPendants(...args) >= n;
55 const hasBig = dungeon => (config, dungeons, state) =>
56 !config.wildBig || !!state[`${dungeon}-big-key`];
58 const hasBird = (config, dungeons, state) => !!state['bird'];
60 const hasBombos = (config, dungeons, state) => !!state['bombos'];
62 const hasBook = (config, dungeons, state) => !!state['book'];
64 const hasBoom = (config, dungeons, state) => !!(state['blue-boomerang'] || state['red-boomerang']);
66 const hasBoots = (config, dungeons, state) => !!state['boots'];
68 const hasBottle = n => (config, dungeons, state) => state['bottle'] >= (n || 1);
70 const hasBow = (config, dungeons, state) => !!state['bow'];
72 const hasBugnet = (config, dungeons, state) => !!state['bugnet'];
74 const hasByrna = (config, dungeons, state) => !!state['byrna'];
76 const hasCape = (config, dungeons, state) => !!state['cape'];
78 const hasFireRod = (config, dungeons, state) => !!state['fire-rod'];
80 const hasFlute = (config, dungeons, state) => !!state['flute'];
82 const hasHammer = (config, dungeons, state) => !!state['hammer'];
84 const hasHookshot = (config, dungeons, state) => !!state['hookshot'];
86 const hasIceRod = (config, dungeons, state) => !!state['ice-rod'];
88 const hasLamp = (config, dungeons, state) => !!state['lamp'];
90 const hasMagicBars = n => (config, dungeons, state) => {
91 let bars = 1 + (state['bottle'] || 0);
92 if (state['half-magic']) {
95 if (state['quarter-magic']) {
98 return bars >= (n || 1);
101 const hasMirror = (config, dungeons, state) => !!state['mirror'];
103 const hasMMMedallion = (config, dungeons, state) =>
104 !!state['mm-medallion'] && !!state[state['mm-medallion']];
106 const hasMoonpearl = (config, dungeons, state) => !!state['moonpearl'];
108 const hasMushroom = (config, dungeons, state) => !!state['mushroom'];
110 const hasPowder = (config, dungeons, state) => !!state['powder'];
112 const hasQuake = (config, dungeons, state) => !!state['quake'];
114 const hasShovel = (config, dungeons, state) => !!state['shovel'];
116 const hasSmall = (dungeon, amount) => (config, dungeons, state) =>
117 !config.wildSmall || state[`${dungeon}-small-key`] >= (amount || 1);
119 const hasSomaria = (config, dungeons, state) => !!state['somaria'];
121 const hasSword = n => (config, dungeons, state) => state['sword'] >= (n || 1);
123 const hasTRMedallion = (config, dungeons, state) =>
124 !!state['tr-medallion'] && !!state[state['tr-medallion']];
128 const canActivateFlute = () => true;
130 const canBomb = () => true;
132 const canBonk = hasBoots;
134 const canDarkRoom = hasLamp;
136 const canFlipSwitches = or(
149 const canFly = or(hasBird, and(hasFlute, canActivateFlute));
151 const canGetGoodBee = and(hasBugnet, hasBottle(), or(canBonk, and(hasSword(), hasQuake)));
153 const canLift = (config, dungeons, state) => state['lift'] >= 1;
155 const canHeavyLift = (config, dungeons, state) => state['lift'] >= 2;
157 const canKill = damage => damage && damage < 6
158 ? or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1), canBomb, hasByrna)
159 : or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1));
161 const canMedallion = hasSword();
163 const canMeltThings = or(hasFireRod, and(hasBombos, canMedallion));
165 const canPassCurtains = hasSword();
167 const canShootArrows = hasBow;
169 const canSwim = (config, dungeons, state) => !!state['flippers'];
171 const canTablet = and(hasBook, hasSword(2));
173 const canTorch = or(hasFireRod, hasLamp);
175 const canTorchDarkRoom = or(canDarkRoom, canTorch);
179 const westDeathMountain = or(
181 and(canLift, canDarkRoom),
184 const eastDeathMountain = and(
188 and(hasHammer, hasMirror),
192 const northDeathMountain = and(
196 and(hasHammer, hasHookshot),
200 const eastDarkDeathMountain = and(
205 const westDarkDeathMountain = westDeathMountain;
207 const eastDarkWorld = and(
212 and(canLift, hasHammer),
216 const westDarkWorld = and(
219 and(canLift, hasHammer),
221 and(eastDarkWorld, hasHookshot, or(canSwim, canLift, hasHammer)),
225 const southDarkWorld = or(
227 and(eastDarkWorld, hasMoonpearl, hasHammer),
230 const mireArea = and(canFly, canHeavyLift);
235 aga: or(hasBugnet, hasHammer, hasSword()),
237 hasSword(), hasHammer, canShootArrows, hasBoom,
238 and(hasMagicBars(4), or(hasFireRod, hasIceRod)),
239 and(hasMagicBars(2), or(hasByrna, hasSomaria)),
241 arrghus: and(hasHookshot, or(
244 and(or(hasMagicBars(2), canShootArrows), or(hasFireRod, hasIceRod)),
246 blind: or(hasSword(), hasHammer, hasSomaria, hasByrna),
247 helma: and(or(canBomb, hasHammer), or(hasSword(), canShootArrows)),
248 kholdstare: and(canMeltThings, or(
251 and(hasFireRod, hasMagicBars(3)),
252 and(hasFireRod, hasBombos, hasMagicBars(2), canMedallion),
255 hasSword(), hasHammer, canShootArrows, hasFireRod, hasIceRod, hasByrna, hasSomaria,
257 moldorm: or(hasSword(), hasHammer),
261 and(hasMagicBars(2), or(hasFireRod, hasSomaria, hasByrna)),
264 trinexx: and(hasFireRod, hasIceRod, or(
267 and(hasMagicBars(2), hasSword(2)),
268 and(hasMagicBars(4), hasSword(1)),
270 vitreous: or(hasSword(), hasHammer, canShootArrows),
273 const canKillBoss = dungeon => (config, dungeons, state) => {
274 const boss = getDungeonBoss(state, dungeons.find(d => d.id === dungeon));
275 return BOSS_RULES[boss](config, dungeons, state);
278 const canKillGTBoss = which => (config, dungeons, state) => {
279 const boss = getGTBoss(state, which);
280 return BOSS_RULES[boss](config, dungeons, state);
285 const canEnterCT = or(hasCape, hasSword(2));
287 const canEnterGT = and(eastDarkDeathMountain, hasGTCrystals, hasMoonpearl);
289 const canEnterDPFront = or(hasBook, and(mireArea, hasMirror));
290 const canEnterDPBack = or(and(canEnterDPFront, canLift), and(mireArea, hasMirror));
292 const canEnterTH = northDeathMountain;
294 const canEnterPD = and(eastDarkWorld, hasMoonpearl);
296 const canEnterSP = and(southDarkWorld, hasMirror, hasMoonpearl, canSwim);
298 const canEnterSWFront = and(westDarkWorld, hasMoonpearl);
299 const canEnterSWMid = and(westDarkWorld, hasMoonpearl);
300 const canEnterSWBack = and(westDarkWorld, hasMoonpearl, hasFireRod);
302 const canEnterTT = and(westDarkWorld, hasMoonpearl);
304 const canEnterIP = and(canSwim, canHeavyLift, hasMoonpearl, canMeltThings);
305 const rightSideIP = or(hasHookshot, hasSmall('ip'));
307 const canEnterMM = and(
312 or(canBonk, hasHookshot),
316 const canEnterTRFront = and(
324 const canEnterTRWest = and(canEnterTRFront, canBomb, hasSmall('tr', 2));
325 const canEnterTREast = and(canEnterTRWest, or(hasHookshot, hasSomaria));
326 const canEnterTRBack = and(
327 or(canEnterTRWest, canEnterTREast),
328 or(canBomb, canBonk),
334 const laserBridge = or(
336 or(canEnterDPFront, canEnterTRWest, canEnterTREast),
347 const paradoxLower = and(eastDeathMountain, or(canBomb, hasBoom, canShootArrows, hasSomaria));
349 const canBridgeRedBomb = or(
350 and(hasMoonpearl, hasHammer),
351 and(agaDead, hasMirror),
354 const canRescueSmith = and(westDarkWorld, hasMoonpearl, canHeavyLift);
359 fallback: () => 'available',
360 aginah: fromBool(canBomb),
361 blacksmith: fromBool(canRescueSmith),
362 'blinds-hut-top': fromBool(canBomb),
363 'bombos-tablet': fromBool(and(southDarkWorld, hasMirror, canTablet)),
364 'bonk-rocks': fromBool(canBonk),
365 brewery: fromBool(and(westDarkWorld, canBomb, hasMoonpearl)),
366 'bumper-cave': fromBool(and(westDarkWorld, hasMoonpearl, canLift, hasCape)),
367 'c-house': fromBool(and(westDarkWorld, hasMoonpearl)),
368 catfish: fromBool(and(eastDarkWorld, hasMoonpearl)),
369 'cave-45': fromBool(and(southDarkWorld, hasMirror)),
370 checkerboard: fromBool(and(mireArea, hasMirror)),
371 'chest-game': fromBool(and(westDarkWorld, hasMoonpearl)),
372 'chicken-house': fromBool(canBomb),
373 'desert-ledge': fromBool(canEnterDPFront),
374 'digging-game': fromBool(and(southDarkWorld, hasMoonpearl)),
375 'ether-tablet': fromBool(and(northDeathMountain, canTablet)),
376 'floating-island': fromBool(
377 and(eastDarkDeathMountain, hasMoonpearl, canLift, canBomb, hasMirror),
379 'flute-spot': fromBool(hasShovel),
380 'graveyard-ledge': fromBool(and(westDarkWorld, hasMoonpearl, hasMirror)),
381 'hammer-pegs': fromBool(and(westDarkWorld, hasHammer, hasMoonpearl, canHeavyLift)),
382 hobo: fromBool(canSwim),
383 'hookshot-cave-tl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
384 'hookshot-cave-tr': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
385 'hookshot-cave-bl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
386 'hookshot-cave-br': fromBool(
387 and(eastDarkDeathMountain, hasMoonpearl, canLift, or(hasHookshot, canBonk)),
389 'hype-cave-npc': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
390 'hype-cave-top': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
391 'hype-cave-right': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
392 'hype-cave-left': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
393 'hype-cave-bottom': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
394 'ice-rod-cave': fromBool(canBomb),
395 'kak-well-top': fromBool(canBomb),
396 'kings-tomb': fromBool(and(canBonk, or(canHeavyLift, and(westDarkWorld, hasMirror)))),
397 'lake-hylia-island': fromBool(
398 and(canSwim, hasMirror, hasMoonpearl, or(eastDarkWorld, southDarkWorld)),
400 library: fromBool(canBonk),
401 lumberjack: fromBool(and(canBonk, agaDead)),
402 'magic-bat': fromBool(and(hasPowder,
403 or(hasHammer, and(westDarkWorld, hasMoonpearl, canHeavyLift, hasMirror)),
405 'mimic-cave': fromBool(and(canEnterTREast, hasMirror, hasHammer)),
406 'mini-moldorm-left': fromBool(canBomb),
407 'mini-moldorm-right': fromBool(canBomb),
408 'mini-moldorm-far-left': fromBool(canBomb),
409 'mini-moldorm-far-right': fromBool(canBomb),
410 'mini-moldorm-npc': fromBool(canBomb),
411 'mire-shed-left': fromBool(and(mireArea, hasMoonpearl)),
412 'mire-shed-right': fromBool(and(mireArea, hasMoonpearl)),
413 'old-man': fromBool(and(westDeathMountain, canDarkRoom)),
414 'paradox-lower-far-left': fromBool(paradoxLower),
415 'paradox-lower-left': fromBool(paradoxLower),
416 'paradox-lower-right': fromBool(paradoxLower),
417 'paradox-lower-far-right': fromBool(paradoxLower),
418 'paradox-lower-mid': fromBool(paradoxLower),
419 'paradox-upper-left': fromBool(and(eastDeathMountain, canBomb)),
420 'paradox-upper-right': fromBool(and(eastDeathMountain, canBomb)),
421 pedestal: fromBool(hasPendants(3)),
422 'potion-shop': fromBool(hasMushroom),
423 'purple-chest': fromBool(and(canRescueSmith, hasMoonpearl, canHeavyLift)),
424 pyramid: fromBool(eastDarkWorld),
425 'pyramid-fairy-left': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
426 'pyramid-fairy-right': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
427 'race-game': fromBool(or(canBomb, canBonk)),
428 saha: fromBool(hasGreenPendant),
429 'saha-left': fromBool(or(canBomb, canBonk)),
430 'saha-mid': fromBool(or(canBomb, canBonk)),
431 'saha-right': fromBool(or(canBomb, canBonk)),
432 'sick-kid': fromBool(hasBottle(1)),
433 'spec-rock': fromBool(and(westDeathMountain, hasMirror)),
434 'spec-rock-cave': fromBool(westDeathMountain),
435 'spike-cave': fromBool(and(
436 westDarkDeathMountain,
440 or(hasByrna, and(hasCape, hasMagicBars(2))),
442 'spiral-cave': fromBool(eastDeathMountain),
443 stumpy: fromBool(and(southDarkWorld, hasMoonpearl)),
444 'super-bunny-top': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
445 'super-bunny-bottom': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
446 'waterfall-fairy-left': fromBool(canSwim),
447 'waterfall-fairy-right': fromBool(canSwim),
448 zora: fromBool(or(canLift, canSwim)),
449 'zora-ledge': fromBool(canSwim),
450 'hc-boom': fromBool(and(hasSmall('hc'), canKill())),
451 'hc-cell': fromBool(and(hasSmall('hc'), canKill())),
452 'dark-cross': fromBool(canTorchDarkRoom),
453 'sewers-left': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
454 'sewers-mid': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
455 'sewers-right': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
456 ct: fromBool(canEnterCT),
457 'ct-1': fromBool(canKill()),
458 'ct-2': fromBool(and(canKill(), hasSmall('ct'), canDarkRoom)),
459 'ct-boss-killable': fromBool(and(
460 canKill(), hasSmall('ct', 2), canDarkRoom, canPassCurtains, canKillBoss('ct'),
462 gt: fromBool(canEnterGT),
463 'gt-tile-room': fromBool(hasSomaria),
464 'gt-compass-tl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
465 'gt-compass-tr': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
466 'gt-compass-bl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
467 'gt-compass-br': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
468 'gt-torch': fromBool(canBonk),
469 'gt-dm-tl': fromBool(and(hasHammer, hasHookshot)),
470 'gt-dm-tr': fromBool(and(hasHammer, hasHookshot)),
471 'gt-dm-bl': fromBool(and(hasHammer, hasHookshot)),
472 'gt-dm-br': fromBool(and(hasHammer, hasHookshot)),
473 'gt-map-chest': fromBool(and(hasHammer, or(hasHookshot, canBonk), hasSmall('gt', 4))),
474 'gt-firesnake': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 3))),
475 'gt-rando-tl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
476 'gt-rando-tr': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
477 'gt-rando-bl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
478 'gt-rando-br': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
479 'gt-bobs-chest': fromBool(and(
480 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
483 'gt-ice-left': fromBool(and(
484 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
486 canKillGTBoss('bot'),
488 'gt-ice-mid': fromBool(and(
489 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
491 canKillGTBoss('bot'),
493 'gt-ice-right': fromBool(and(
494 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
496 canKillGTBoss('bot'),
498 'gt-big-chest': fromBool(and(
499 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
503 'gt-helma-left': fromBool(and(
508 canKillGTBoss('mid'),
510 'gt-helma-right': fromBool(and(
515 canKillGTBoss('mid'),
517 'gt-pre-moldorm': fromBool(and(
522 canKillGTBoss('mid'),
524 'gt-post-moldorm': fromBool(and(
529 canKillGTBoss('mid'),
530 canKillGTBoss('top'),
533 'gt-boss-killable': fromBool(and(
538 canKillGTBoss('mid'),
539 canKillGTBoss('top'),
543 'ep-big-chest': fromBool(hasBig('ep')),
544 'ep-big-key-chest': fromBool(canDarkRoom),
545 'ep-boss-defeated': fromBool(and(
546 canShootArrows, canTorchDarkRoom, hasBig('ep'), canKillBoss('ep'),
548 dp: fromBool(or(canEnterDPFront, canEnterDPBack)),
549 'dp-big-chest': fromBool(and(canEnterDPFront, hasBig('dp'))),
550 'dp-big-key-chest': fromBool(and(canEnterDPFront, hasSmall('dp'), canKill())),
551 'dp-compass-chest': fromBool(and(canEnterDPFront, hasSmall('dp'))),
552 'dp-map-chest': fromBool(canEnterDPFront),
553 'dp-torch': fromBool(and(canEnterDPFront, canBonk)),
554 'dp-boss-defeated': fromBool(and(
561 th: fromBool(canEnterTH),
562 'th-basement-cage': fromBool(canFlipSwitches),
563 'th-map-chest': fromBool(canFlipSwitches),
564 'th-big-key-chest': fromBool(and(canFlipSwitches, hasSmall('th'), canTorch)),
565 'th-compass-chest': fromBool(and(canFlipSwitches, hasBig('th'))),
566 'th-big-chest': fromBool(and(canFlipSwitches, hasBig('th'))),
567 'th-boss-defeated': fromBool(and(
572 pd: fromBool(canEnterPD),
573 'pd-stalfos-basement': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
574 'pd-big-key-chest': fromBool(hasSmall('pd', 6)),
575 'pd-arena-bridge': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
576 'pd-arena-ledge': fromBool(canShootArrows),
577 'pd-map-chest': fromBool(canShootArrows),
578 'pd-compass-chest': fromBool(hasSmall('pd', 4)),
579 'pd-basement-left': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))),
580 'pd-basement-right': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))),
581 'pd-harmless-hellway': fromBool(hasSmall('pd', 6)),
582 'pd-maze-top': fromBool(and(canDarkRoom, hasSmall('pd', 6))),
583 'pd-maze-bottom': fromBool(and(canDarkRoom, hasSmall('pd', 6))),
584 'pd-big-chest': fromBool(and(canDarkRoom, hasBig('pd'), hasSmall('pd', 6))),
585 'pd-boss-defeated': fromBool(and(
586 canDarkRoom, hasBig('pd'), hasSmall('pd', 6), canShootArrows, hasHammer, canKillBoss('pd'),
588 sp: fromBool(canEnterSP),
589 'sp-map-chest': fromBool(and(hasSmall('sp'), canBomb)),
590 'sp-big-chest': fromBool(and(hasSmall('sp'), hasHammer, hasBig('sp'))),
591 'sp-compass-chest': fromBool(and(hasSmall('sp'), hasHammer)),
592 'sp-west-chest': fromBool(and(hasSmall('sp'), hasHammer)),
593 'sp-big-key-chest': fromBool(and(hasSmall('sp'), hasHammer)),
594 'sp-flooded-left': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
595 'sp-flooded-right': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
596 'sp-waterfall': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
597 'sp-boss-defeated': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot, canKillBoss('sp'))),
598 sw: fromBool(or(canEnterSWFront, canEnterSWMid, canEnterSWBack)),
599 'sw-big-chest': fromBool(and(canEnterSWFront, hasBig('sw'))),
600 'sw-bridge-chest': fromBool(canEnterSWBack),
601 'sw-boss-defeated': fromBool(and(
602 canEnterSWBack, canPassCurtains, hasFireRod, hasSmall('sw', 3), canKillBoss('sw'),
604 tt: fromBool(canEnterTT),
605 'tt-attic': fromBool(and(hasBig('tt'), hasSmall('tt'), canBomb)),
606 'tt-cell': fromBool(hasBig('tt')),
607 'tt-big-chest': fromBool(and(hasBig('tt'), hasSmall('tt'), hasHammer)),
608 'tt-boss-defeated': fromBool(and(hasBig('tt'), hasSmall('tt'), canKillBoss('tt'))),
609 ip: fromBool(canEnterIP),
610 'ip-big-key-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
611 'ip-map-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
612 'ip-spike-chest': fromBool(rightSideIP),
613 'ip-freezor-chest': fromBool(canMeltThings),
614 'ip-big-chest': fromBool(hasBig('ip')),
615 'ip-boss-defeated': fromBool(and(
619 or(hasSmall('ip', 2), and(hasSomaria, hasSmall('ip'))),
622 mm: fromBool(canEnterMM),
623 'mm-lobby-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
624 'mm-compass-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
625 'mm-big-key-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
626 'mm-big-chest': fromBool(hasBig('mm')),
627 'mm-map-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
628 'mm-boss-defeated': fromBool(and(hasBig('mm'), canDarkRoom, hasSomaria, canKillBoss('mm'))),
629 tr: fromBool(or(canEnterTRFront, canEnterTRWest, canEnterTREast, canEnterTRBack)),
630 'tr-roller-left': fromBool(and(hasFireRod, hasSomaria, or(
632 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
633 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
635 'tr-roller-right': fromBool(and(hasFireRod, hasSomaria, or(
637 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
638 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
640 'tr-compass-chest': fromBool(and(hasSomaria, or(
642 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
643 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
645 'tr-chomps': fromBool(or(
646 and(canEnterTRFront, hasSmall('tr')),
649 and(canEnterTRBack, canDarkRoom, hasSomaria),
651 'tr-big-key-chest': fromBool(and(hasSmall('tr', 4), or(
652 and(canEnterTRFront, hasSomaria),
655 and(canEnterTRBack, canDarkRoom, hasSomaria),
657 'tr-big-chest': fromBool(canEnterTREast),
658 'tr-crysta-roller': fromBool(or(
659 and(hasBig('tr'), or(
660 and(canEnterTRFront, hasSomaria, hasSmall('tr', 2)),
664 and(canEnterTRBack, canDarkRoom, hasSomaria),
666 'tr-laser-bridge-top': fromBool(laserBridge),
667 'tr-laser-bridge-left': fromBool(laserBridge),
668 'tr-laser-bridge-right': fromBool(laserBridge),
669 'tr-laser-bridge-bottom': fromBool(laserBridge),
670 'tr-boss-defeated': fromBool(and(
679 export default Logic;