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 countBottles = (config, dungeons, state) =>
56 ['bottle-1', 'bottle-2', 'bottle-3', 'bottle-4'].filter(b => !!state[b]).length;
58 const hasBig = dungeon => (config, dungeons, state) =>
59 !config.wildBig || !!state[`${dungeon}-big-key`];
61 const hasBird = (config, dungeons, state) => !!state['bird'];
63 const hasBombos = (config, dungeons, state) => !!state['bombos'];
65 const hasBook = (config, dungeons, state) => !!state['book'];
67 const hasBoom = (config, dungeons, state) => !!(state['blue-boomerang'] || state['red-boomerang']);
69 const hasBoots = (config, dungeons, state) => !!state['boots'];
71 const hasBottle = n => (...args) => countBottles(...args) >= (n || 1);
73 const hasBow = (config, dungeons, state) => !!state['bow'];
75 const hasBugnet = (config, dungeons, state) => !!state['bugnet'];
77 const hasByrna = (config, dungeons, state) => !!state['byrna'];
79 const hasCape = (config, dungeons, state) => !!state['cape'];
81 const hasFireRod = (config, dungeons, state) => !!state['fire-rod'];
83 const hasFlute = (config, dungeons, state) => !!state['flute'];
85 const hasHammer = (config, dungeons, state) => !!state['hammer'];
87 const hasHookshot = (config, dungeons, state) => !!state['hookshot'];
89 const hasIceRod = (config, dungeons, state) => !!state['ice-rod'];
91 const hasLamp = (config, dungeons, state) => !!state['lamp'];
93 const hasMagicBars = n => (config, dungeons, state) => {
94 let bars = 1 + (state['bottle'] || 0);
95 if (state['half-magic']) {
98 if (state['quarter-magic']) {
101 return bars >= (n || 1);
104 const hasMirror = (config, dungeons, state) => !!state['mirror'];
106 const hasMMMedallion = (config, dungeons, state) =>
107 !!state['mm-medallion'] && !!state[state['mm-medallion']];
109 const hasMoonpearl = (config, dungeons, state) => !!state['moonpearl'];
111 const hasMushroom = (config, dungeons, state) => !!state['mushroom'];
113 const hasPowder = (config, dungeons, state) => !!state['powder'];
115 const hasQuake = (config, dungeons, state) => !!state['quake'];
117 const hasShovel = (config, dungeons, state) => !!state['shovel'];
119 const hasSmall = (dungeon, amount) => (config, dungeons, state) =>
120 !config.wildSmall || state[`${dungeon}-small-key`] >= (amount || 1);
122 const hasSomaria = (config, dungeons, state) => !!state['somaria'];
124 const hasSword = n => (config, dungeons, state) => state['sword'] >= (n || 1);
126 const hasTRMedallion = (config, dungeons, state) =>
127 !!state['tr-medallion'] && !!state[state['tr-medallion']];
131 const canActivateFlute = () => true;
133 const canBomb = () => true;
135 const canBonk = hasBoots;
137 const canDarkRoom = hasLamp;
139 const canFlipSwitches = or(
152 const canFly = or(hasBird, and(hasFlute, canActivateFlute));
154 const canGetGoodBee = and(hasBugnet, hasBottle(), or(canBonk, and(hasSword(), hasQuake)));
156 const canLift = (config, dungeons, state) => state['lift'] >= 1;
158 const canHeavyLift = (config, dungeons, state) => state['lift'] >= 2;
160 const canKill = damage => damage && damage < 6
161 ? or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1), canBomb, hasByrna)
162 : or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1));
164 const canMedallion = hasSword();
166 const canMeltThings = or(hasFireRod, and(hasBombos, canMedallion));
168 const canPassCurtains = hasSword();
170 const canShootArrows = hasBow;
172 const canSwim = (config, dungeons, state) => !!state['flippers'];
174 const canTablet = and(hasBook, hasSword(2));
176 const canTorch = or(hasFireRod, hasLamp);
178 const canTorchDarkRoom = or(canDarkRoom, canTorch);
182 const westDeathMountain = or(
184 and(canLift, canDarkRoom),
187 const eastDeathMountain = and(
191 and(hasHammer, hasMirror),
195 const northDeathMountain = and(
199 and(hasHammer, hasHookshot),
203 const eastDarkDeathMountain = and(
208 const westDarkDeathMountain = westDeathMountain;
210 const eastDarkWorld = and(
215 and(canLift, hasHammer),
219 const westDarkWorld = and(
222 and(canLift, hasHammer),
224 and(eastDarkWorld, hasHookshot, or(canSwim, canLift, hasHammer)),
228 const southDarkWorld = or(
230 and(eastDarkWorld, hasMoonpearl, hasHammer),
233 const mireArea = and(canFly, canHeavyLift);
238 aga: or(hasBugnet, hasHammer, hasSword()),
240 hasSword(), hasHammer, canShootArrows, hasBoom,
241 and(hasMagicBars(4), or(hasFireRod, hasIceRod)),
242 and(hasMagicBars(2), or(hasByrna, hasSomaria)),
244 arrghus: and(hasHookshot, or(
247 and(or(hasMagicBars(2), canShootArrows), or(hasFireRod, hasIceRod)),
249 blind: or(hasSword(), hasHammer, hasSomaria, hasByrna),
250 helma: and(or(canBomb, hasHammer), or(hasSword(), canShootArrows)),
251 kholdstare: and(canMeltThings, or(
254 and(hasFireRod, hasMagicBars(3)),
255 and(hasFireRod, hasBombos, hasMagicBars(2), canMedallion),
258 hasSword(), hasHammer, canShootArrows, hasFireRod, hasIceRod, hasByrna, hasSomaria,
260 moldorm: or(hasSword(), hasHammer),
264 and(hasMagicBars(2), or(hasFireRod, hasSomaria, hasByrna)),
267 trinexx: and(hasFireRod, hasIceRod, or(
270 and(hasMagicBars(2), hasSword(2)),
271 and(hasMagicBars(4), hasSword(1)),
273 vitreous: or(hasSword(), hasHammer, canShootArrows),
276 const canKillBoss = dungeon => (config, dungeons, state) => {
277 const boss = getDungeonBoss(state, dungeons.find(d => d.id === dungeon));
278 return BOSS_RULES[boss](config, dungeons, state);
281 const canKillGTBoss = which => (config, dungeons, state) => {
282 const boss = getGTBoss(state, which);
283 return BOSS_RULES[boss](config, dungeons, state);
288 const canEnterCT = or(hasCape, hasSword(2));
290 const canEnterGT = and(eastDarkDeathMountain, hasGTCrystals, hasMoonpearl);
292 const canEnterDPFront = or(hasBook, and(mireArea, hasMirror));
293 const canEnterDPBack = or(and(canEnterDPFront, canLift), and(mireArea, hasMirror));
295 const canEnterTH = northDeathMountain;
297 const canEnterPD = and(eastDarkWorld, hasMoonpearl);
299 const canEnterSP = and(southDarkWorld, hasMirror, hasMoonpearl, canSwim);
301 const canEnterSWFront = and(westDarkWorld, hasMoonpearl);
302 const canEnterSWMid = and(westDarkWorld, hasMoonpearl);
303 const canEnterSWBack = and(westDarkWorld, hasMoonpearl, hasFireRod);
305 const canEnterTT = and(westDarkWorld, hasMoonpearl);
307 const canEnterIP = and(canSwim, canHeavyLift, hasMoonpearl, canMeltThings);
308 const rightSideIP = or(hasHookshot, hasSmall('ip'));
310 const canEnterMM = and(
315 or(canBonk, hasHookshot),
319 const canEnterTRFront = and(
327 const canEnterTRWest = and(canEnterTRFront, canBomb, hasSmall('tr', 2));
328 const canEnterTREast = and(canEnterTRWest, or(hasHookshot, hasSomaria));
329 const canEnterTRBack = and(
330 or(canEnterTRWest, canEnterTREast),
331 or(canBomb, canBonk),
337 const laserBridge = or(
339 or(canEnterDPFront, canEnterTRWest, canEnterTREast),
350 const paradoxLower = and(eastDeathMountain, or(canBomb, hasBoom, canShootArrows, hasSomaria));
352 const canBridgeRedBomb = or(
353 and(hasMoonpearl, hasHammer),
354 and(agaDead, hasMirror),
357 const canRescueSmith = and(westDarkWorld, hasMoonpearl, canHeavyLift);
362 fallback: () => 'available',
363 aginah: fromBool(canBomb),
364 blacksmith: fromBool(canRescueSmith),
365 'blinds-hut-top': fromBool(canBomb),
366 'bombos-tablet': fromBool(and(southDarkWorld, hasMirror, canTablet)),
367 'bonk-rocks': fromBool(canBonk),
368 brewery: fromBool(and(westDarkWorld, canBomb, hasMoonpearl)),
369 'bumper-cave': fromBool(and(westDarkWorld, hasMoonpearl, canLift, hasCape)),
370 'c-house': fromBool(and(westDarkWorld, hasMoonpearl)),
371 catfish: fromBool(and(eastDarkWorld, hasMoonpearl)),
372 'cave-45': fromBool(and(southDarkWorld, hasMirror)),
373 checkerboard: fromBool(and(mireArea, hasMirror)),
374 'chest-game': fromBool(and(westDarkWorld, hasMoonpearl)),
375 'chicken-house': fromBool(canBomb),
376 'desert-ledge': fromBool(canEnterDPFront),
377 'digging-game': fromBool(and(southDarkWorld, hasMoonpearl)),
378 'ether-tablet': fromBool(and(northDeathMountain, canTablet)),
379 'floating-island': fromBool(
380 and(eastDarkDeathMountain, hasMoonpearl, canLift, canBomb, hasMirror),
382 'flute-spot': fromBool(hasShovel),
383 'graveyard-ledge': fromBool(and(westDarkWorld, hasMoonpearl, hasMirror)),
384 'hammer-pegs': fromBool(and(westDarkWorld, hasHammer, hasMoonpearl, canHeavyLift)),
385 hobo: fromBool(canSwim),
386 'hookshot-cave-tl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
387 'hookshot-cave-tr': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
388 'hookshot-cave-bl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
389 'hookshot-cave-br': fromBool(
390 and(eastDarkDeathMountain, hasMoonpearl, canLift, or(hasHookshot, canBonk)),
392 'hype-cave-npc': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
393 'hype-cave-top': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
394 'hype-cave-right': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
395 'hype-cave-left': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
396 'hype-cave-bottom': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
397 'ice-rod-cave': fromBool(canBomb),
398 'kak-well-top': fromBool(canBomb),
399 'kings-tomb': fromBool(and(canBonk, or(canHeavyLift, and(westDarkWorld, hasMirror)))),
400 'lake-hylia-island': fromBool(
401 and(canSwim, hasMirror, hasMoonpearl, or(eastDarkWorld, southDarkWorld)),
403 library: fromBool(canBonk),
404 lumberjack: fromBool(and(canBonk, agaDead)),
405 'magic-bat': fromBool(and(hasPowder,
406 or(hasHammer, and(westDarkWorld, hasMoonpearl, canHeavyLift, hasMirror)),
408 'mimic-cave': fromBool(and(canEnterTREast, hasMirror, hasHammer)),
409 'mini-moldorm-left': fromBool(canBomb),
410 'mini-moldorm-right': fromBool(canBomb),
411 'mini-moldorm-far-left': fromBool(canBomb),
412 'mini-moldorm-far-right': fromBool(canBomb),
413 'mini-moldorm-npc': fromBool(canBomb),
414 'mire-shed-left': fromBool(and(mireArea, hasMoonpearl)),
415 'mire-shed-right': fromBool(and(mireArea, hasMoonpearl)),
416 'old-man': fromBool(and(westDeathMountain, canDarkRoom)),
417 'paradox-lower-far-left': fromBool(paradoxLower),
418 'paradox-lower-left': fromBool(paradoxLower),
419 'paradox-lower-right': fromBool(paradoxLower),
420 'paradox-lower-far-right': fromBool(paradoxLower),
421 'paradox-lower-mid': fromBool(paradoxLower),
422 'paradox-upper-left': fromBool(and(eastDeathMountain, canBomb)),
423 'paradox-upper-right': fromBool(and(eastDeathMountain, canBomb)),
424 pedestal: fromBool(hasPendants(3)),
425 'potion-shop': fromBool(hasMushroom),
426 'purple-chest': fromBool(and(canRescueSmith, hasMoonpearl, canHeavyLift)),
427 pyramid: fromBool(eastDarkWorld),
428 'pyramid-fairy-left': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
429 'pyramid-fairy-right': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
430 'race-game': fromBool(or(canBomb, canBonk)),
431 saha: fromBool(hasGreenPendant),
432 'saha-left': fromBool(or(canBomb, canBonk)),
433 'saha-mid': fromBool(or(canBomb, canBonk)),
434 'saha-right': fromBool(or(canBomb, canBonk)),
435 'sick-kid': fromBool(hasBottle(1)),
436 'spec-rock': fromBool(and(westDeathMountain, hasMirror)),
437 'spec-rock-cave': fromBool(westDeathMountain),
438 'spike-cave': fromBool(and(
439 westDarkDeathMountain,
443 or(hasByrna, and(hasCape, hasMagicBars(2))),
445 'spiral-cave': fromBool(eastDeathMountain),
446 stumpy: fromBool(and(southDarkWorld, hasMoonpearl)),
447 'super-bunny-top': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
448 'super-bunny-bottom': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
449 'waterfall-fairy-left': fromBool(canSwim),
450 'waterfall-fairy-right': fromBool(canSwim),
451 zora: fromBool(or(canLift, canSwim)),
452 'zora-ledge': fromBool(canSwim),
453 'hc-boom': fromBool(and(hasSmall('hc'), canKill())),
454 'hc-cell': fromBool(and(hasSmall('hc'), canKill())),
455 'dark-cross': fromBool(canTorchDarkRoom),
456 'sewers-left': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
457 'sewers-mid': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
458 'sewers-right': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
459 ct: fromBool(canEnterCT),
460 'ct-1': fromBool(canKill()),
461 'ct-2': fromBool(and(canKill(), hasSmall('ct'), canDarkRoom)),
462 'ct-boss-killable': fromBool(and(
463 canKill(), hasSmall('ct', 2), canDarkRoom, canPassCurtains, canKillBoss('ct'),
465 gt: fromBool(canEnterGT),
466 'gt-tile-room': fromBool(hasSomaria),
467 'gt-compass-tl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
468 'gt-compass-tr': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
469 'gt-compass-bl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
470 'gt-compass-br': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
471 'gt-torch': fromBool(canBonk),
472 'gt-dm-tl': fromBool(and(hasHammer, hasHookshot)),
473 'gt-dm-tr': fromBool(and(hasHammer, hasHookshot)),
474 'gt-dm-bl': fromBool(and(hasHammer, hasHookshot)),
475 'gt-dm-br': fromBool(and(hasHammer, hasHookshot)),
476 'gt-map-chest': fromBool(and(hasHammer, or(hasHookshot, canBonk), hasSmall('gt', 4))),
477 'gt-firesnake': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 3))),
478 'gt-rando-tl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
479 'gt-rando-tr': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
480 'gt-rando-bl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
481 'gt-rando-br': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))),
482 'gt-bobs-chest': fromBool(and(
483 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
486 'gt-ice-left': fromBool(and(
487 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
489 canKillGTBoss('bot'),
491 'gt-ice-mid': fromBool(and(
492 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
494 canKillGTBoss('bot'),
496 'gt-ice-right': fromBool(and(
497 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
499 canKillGTBoss('bot'),
501 'gt-big-chest': fromBool(and(
502 or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)),
506 'gt-helma-left': fromBool(and(
511 canKillGTBoss('mid'),
513 'gt-helma-right': fromBool(and(
518 canKillGTBoss('mid'),
520 'gt-pre-moldorm': fromBool(and(
525 canKillGTBoss('mid'),
527 'gt-post-moldorm': fromBool(and(
532 canKillGTBoss('mid'),
533 canKillGTBoss('top'),
536 'gt-boss-killable': fromBool(and(
541 canKillGTBoss('mid'),
542 canKillGTBoss('top'),
546 'ep-big-chest': fromBool(hasBig('ep')),
547 'ep-big-key-chest': fromBool(canDarkRoom),
548 'ep-boss-defeated': fromBool(and(
549 canShootArrows, canTorchDarkRoom, hasBig('ep'), canKillBoss('ep'),
551 dp: fromBool(or(canEnterDPFront, canEnterDPBack)),
552 'dp-big-chest': fromBool(and(canEnterDPFront, hasBig('dp'))),
553 'dp-big-key-chest': fromBool(and(canEnterDPFront, hasSmall('dp'), canKill())),
554 'dp-compass-chest': fromBool(and(canEnterDPFront, hasSmall('dp'))),
555 'dp-map-chest': fromBool(canEnterDPFront),
556 'dp-torch': fromBool(and(canEnterDPFront, canBonk)),
557 'dp-boss-defeated': fromBool(and(
564 th: fromBool(canEnterTH),
565 'th-basement-cage': fromBool(canFlipSwitches),
566 'th-map-chest': fromBool(canFlipSwitches),
567 'th-big-key-chest': fromBool(and(canFlipSwitches, hasSmall('th'), canTorch)),
568 'th-compass-chest': fromBool(and(canFlipSwitches, hasBig('th'))),
569 'th-big-chest': fromBool(and(canFlipSwitches, hasBig('th'))),
570 'th-boss-defeated': fromBool(and(
575 pd: fromBool(canEnterPD),
576 'pd-stalfos-basement': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
577 'pd-big-key-chest': fromBool(hasSmall('pd', 6)),
578 'pd-arena-bridge': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
579 'pd-arena-ledge': fromBool(canShootArrows),
580 'pd-map-chest': fromBool(canShootArrows),
581 'pd-compass-chest': fromBool(hasSmall('pd', 4)),
582 'pd-basement-left': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))),
583 'pd-basement-right': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))),
584 'pd-harmless-hellway': fromBool(hasSmall('pd', 6)),
585 'pd-maze-top': fromBool(and(canDarkRoom, hasSmall('pd', 6))),
586 'pd-maze-bottom': fromBool(and(canDarkRoom, hasSmall('pd', 6))),
587 'pd-big-chest': fromBool(and(canDarkRoom, hasBig('pd'), hasSmall('pd', 6))),
588 'pd-boss-defeated': fromBool(and(
589 canDarkRoom, hasBig('pd'), hasSmall('pd', 6), canShootArrows, hasHammer, canKillBoss('pd'),
591 sp: fromBool(canEnterSP),
592 'sp-map-chest': fromBool(and(hasSmall('sp'), canBomb)),
593 'sp-big-chest': fromBool(and(hasSmall('sp'), hasHammer, hasBig('sp'))),
594 'sp-compass-chest': fromBool(and(hasSmall('sp'), hasHammer)),
595 'sp-west-chest': fromBool(and(hasSmall('sp'), hasHammer)),
596 'sp-big-key-chest': fromBool(and(hasSmall('sp'), hasHammer)),
597 'sp-flooded-left': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
598 'sp-flooded-right': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
599 'sp-waterfall': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
600 'sp-boss-defeated': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot, canKillBoss('sp'))),
601 sw: fromBool(or(canEnterSWFront, canEnterSWMid, canEnterSWBack)),
602 'sw-big-chest': fromBool(and(canEnterSWFront, hasBig('sw'))),
603 'sw-bridge-chest': fromBool(canEnterSWBack),
604 'sw-boss-defeated': fromBool(and(
605 canEnterSWBack, canPassCurtains, hasFireRod, hasSmall('sw', 3), canKillBoss('sw'),
607 tt: fromBool(canEnterTT),
608 'tt-attic': fromBool(and(hasBig('tt'), hasSmall('tt'), canBomb)),
609 'tt-cell': fromBool(hasBig('tt')),
610 'tt-big-chest': fromBool(and(hasBig('tt'), hasSmall('tt'), hasHammer)),
611 'tt-boss-defeated': fromBool(and(hasBig('tt'), hasSmall('tt'), canKillBoss('tt'))),
612 ip: fromBool(canEnterIP),
613 'ip-big-key-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
614 'ip-map-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
615 'ip-spike-chest': fromBool(rightSideIP),
616 'ip-freezor-chest': fromBool(canMeltThings),
617 'ip-big-chest': fromBool(hasBig('ip')),
618 'ip-boss-defeated': fromBool(and(
622 or(hasSmall('ip', 2), and(hasSomaria, hasSmall('ip'))),
625 mm: fromBool(canEnterMM),
626 'mm-lobby-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
627 'mm-compass-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
628 'mm-big-key-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
629 'mm-big-chest': fromBool(hasBig('mm')),
630 'mm-map-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
631 'mm-boss-defeated': fromBool(and(hasBig('mm'), canDarkRoom, hasSomaria, canKillBoss('mm'))),
632 tr: fromBool(or(canEnterTRFront, canEnterTRWest, canEnterTREast, canEnterTRBack)),
633 'tr-roller-left': fromBool(and(hasFireRod, hasSomaria, or(
635 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
636 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
638 'tr-roller-right': fromBool(and(hasFireRod, hasSomaria, or(
640 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
641 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
643 'tr-compass-chest': fromBool(and(hasSomaria, or(
645 and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
646 and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)),
648 'tr-chomps': fromBool(or(
649 and(canEnterTRFront, hasSmall('tr')),
652 and(canEnterTRBack, canDarkRoom, hasSomaria),
654 'tr-big-key-chest': fromBool(and(hasSmall('tr', 4), or(
655 and(canEnterTRFront, hasSomaria),
658 and(canEnterTRBack, canDarkRoom, hasSomaria),
660 'tr-big-chest': fromBool(canEnterTREast),
661 'tr-crysta-roller': fromBool(or(
662 and(hasBig('tr'), or(
663 and(canEnterTRFront, hasSomaria, hasSmall('tr', 2)),
667 and(canEnterTRBack, canDarkRoom, hasSomaria),
669 'tr-laser-bridge-top': fromBool(laserBridge),
670 'tr-laser-bridge-left': fromBool(laserBridge),
671 'tr-laser-bridge-right': fromBool(laserBridge),
672 'tr-laser-bridge-bottom': fromBool(laserBridge),
673 'tr-boss-defeated': fromBool(and(
682 export default Logic;