const or = (...predicates) => (...args) =>
predicates.reduce((acc, cur) => acc || cur(...args), false);
+const when = (condition, then, otherwise) => (...args) =>
+ condition(...args) ? then(...args) : otherwise(...args);
+
+const alwaysAvailable = () => true;
+
+const neverAvailable = () => false;
+
const fromBool = b => (...args) => b(...args) ? 'available' : 'unavailable';
+const isInverted = (config) => config.worldState === 'inverted';
+
const agaDead = (config, dungeons, state) =>
hasDungeonBoss(state, dungeons.find(d => d.id === 'ct'));
const hasRedCrystals = n => (...args) => countRedCrystals(...args) >= n;
const hasGTCrystals = (config, dungeons, state) =>
- countCrystals(config, dungeons, state) >= getGTCrystals(state);
+ countCrystals(config, dungeons, state) >= getGTCrystals(config);
const countPendants = (config, dungeons, state) => dungeons
.filter(dungeon =>
// Abilities
-const canActivateFlute = () => true;
-
const canBomb = () => true;
const canBonk = hasBoots;
const canDarkRoom = hasLamp;
+const canShootArrows = hasBow;
+
const canFlipSwitches = or(
canBomb,
hasBoom,
hasIceRod,
);
-const canFly = or(hasBird, and(hasFlute, canActivateFlute));
-
const canGetGoodBee = and(hasBugnet, hasBottle(), or(canBonk, and(hasSword(), hasQuake)));
const canLift = (config, dungeons, state) => state['lift'] >= 1;
const canHeavyLift = (config, dungeons, state) => state['lift'] >= 2;
+const canActivateFlute = when(isInverted,
+ and(
+ hasMoonpearl,
+ or(
+ // partial copy of east light world
+ agaDead,
+ and(hasMoonpearl, or(and(canLift, hasHammer), canHeavyLift)),
+ ),
+ ),
+ alwaysAvailable,
+);
+
+const canFly = or(hasBird, and(hasFlute, canActivateFlute));
+
const canKill = damage => damage && damage < 6
? or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1), canBomb, hasByrna)
: or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1));
const canPassCurtains = hasSword();
-const canShootArrows = hasBow;
-
const canSwim = (config, dungeons, state) => !!state['flippers'];
const canTablet = and(hasBook, hasSword(2));
and(canLift, canDarkRoom),
);
-const eastDeathMountain = and(
+const westDarkDeathMountain = when(isInverted,
+ or(canFly, and(canLift, canDarkRoom)),
westDeathMountain,
- or(
- hasHookshot,
- and(hasHammer, hasMirror),
- ),
);
-const northDeathMountain = and(
- westDeathMountain,
+const eastDeathMountain = when(isInverted,
or(
- hasMirror,
- and(hasHammer, hasHookshot),
+ and(canHeavyLift, or(
+ // copy of eastDarkDeathMountain, to avoid circular reference
+ westDarkDeathMountain,
+ and(westDeathMountain, hasMoonpearl, hasHookshot, hasMirror),
+ )),
+ and(westDeathMountain, hasMoonpearl, hasHookshot),
+ ),
+ and(
+ westDeathMountain,
+ or(
+ hasHookshot,
+ and(hasHammer, hasMirror),
+ ),
),
);
-const eastDarkDeathMountain = and(
- eastDeathMountain,
- canHeavyLift,
+const northDeathMountain = when(isInverted,
+ and(eastDeathMountain, hasMoonpearl, hasHammer),
+ and(
+ westDeathMountain,
+ or(
+ hasMirror,
+ and(hasHammer, hasHookshot),
+ ),
+ ),
);
-const westDarkDeathMountain = westDeathMountain;
-
-const eastDarkWorld = and(
- hasMoonpearl,
+const eastDarkDeathMountain = when(isInverted,
or(
- agaDead,
+ westDarkDeathMountain,
+ and(westDeathMountain, hasMoonpearl, hasHookshot, hasMirror),
+ ),
+ and(
+ eastDeathMountain,
canHeavyLift,
- and(canLift, hasHammer),
),
);
-const westDarkWorld = and(
- hasMoonpearl,
+const eastLightWorld = when(isInverted,
or(
- and(canLift, hasHammer),
- canHeavyLift,
- and(eastDarkWorld, hasHookshot, or(canSwim, canLift, hasHammer)),
+ agaDead,
+ and(hasMoonpearl, or(and(canLift, hasHammer), canHeavyLift)),
+ and(canFly, canHeavyLift),
),
+ alwaysAvailable,
);
-const southDarkWorld = or(
- westDarkWorld,
- and(eastDarkWorld, hasMoonpearl, hasHammer),
+const westLightWorld = eastLightWorld;
+
+const southLightWorld = eastLightWorld;
+
+const eastDarkWorld = when(isInverted,
+ or(canFly, canSwim, hasHammer, and(hasMoonpearl, eastLightWorld)),
+ and(
+ hasMoonpearl,
+ or(
+ agaDead,
+ canHeavyLift,
+ and(canLift, hasHammer),
+ ),
+ ),
);
-const mireArea = and(canFly, canHeavyLift);
+const westDarkWorld = when(isInverted,
+ alwaysAvailable,
+ and(
+ hasMoonpearl,
+ or(
+ and(canLift, hasHammer),
+ canHeavyLift,
+ and(eastDarkWorld, hasHookshot, or(canSwim, canLift, hasHammer)),
+ ),
+ ),
+);
+
+const southDarkWorld = when(isInverted,
+ alwaysAvailable,
+ or(
+ westDarkWorld,
+ and(eastDarkWorld, hasMoonpearl, hasHammer),
+ ),
+);
+
+const mireArea = when(isInverted,
+ or(canFly, and(hasMirror, southLightWorld)),
+ and(canFly, canHeavyLift),
+);
// Bosses
// Dungeons
-const canEnterCT = or(hasCape, hasSword(2));
+const canEnterHC = when(isInverted,
+ and(hasMoonpearl, eastLightWorld),
+ alwaysAvailable,
+);
+
+const canEnterCT = when(isInverted,
+ westDarkDeathMountain,
+ or(hasCape, hasSword(2)),
+);
-const canEnterGT = and(eastDarkDeathMountain, hasGTCrystals, hasMoonpearl);
+const canEnterGT = when(isInverted,
+ and(eastLightWorld, hasGTCrystals, hasMoonpearl),
+ and(eastDarkDeathMountain, hasGTCrystals, hasMoonpearl),
+);
+
+const canEnterEP = when(isInverted,
+ and(hasMoonpearl, eastLightWorld),
+ alwaysAvailable,
+);
-const canEnterDPFront = or(hasBook, and(mireArea, hasMirror));
-const canEnterDPBack = or(and(canEnterDPFront, canLift), and(mireArea, hasMirror));
+const canEnterDPFront = when(isInverted,
+ and(southLightWorld, hasBook),
+ or(hasBook, and(mireArea, hasMirror)),
+);
+const canEnterDPBack = when(isInverted,
+ and(canEnterDPFront, canLift),
+ or(and(canEnterDPFront, canLift), and(mireArea, hasMirror)),
+);
const canEnterTH = northDeathMountain;
-const canEnterPD = and(eastDarkWorld, hasMoonpearl);
+const canEnterPD = when(isInverted,
+ eastDarkWorld,
+ and(eastDarkWorld, hasMoonpearl),
+);
-const canEnterSP = and(southDarkWorld, hasMirror, hasMoonpearl, canSwim);
+const canEnterSP = when(isInverted,
+ and(southLightWorld, hasMirror, hasMoonpearl, canSwim),
+ and(southDarkWorld, hasMirror, hasMoonpearl, canSwim),
+);
-const canEnterSWFront = and(westDarkWorld, hasMoonpearl);
-const canEnterSWMid = and(westDarkWorld, hasMoonpearl);
-const canEnterSWBack = and(westDarkWorld, hasMoonpearl, hasFireRod);
+const canEnterSWFront = when(isInverted,
+ westDarkWorld,
+ and(westDarkWorld, hasMoonpearl),
+);
+const canEnterSWMid = canEnterSWFront;
+const canEnterSWBack = and(canEnterSWMid, hasFireRod);
-const canEnterTT = and(westDarkWorld, hasMoonpearl);
+const canEnterTT = when(isInverted,
+ westDarkWorld,
+ and(westDarkWorld, hasMoonpearl),
+);
-const canEnterIP = and(canSwim, canHeavyLift, hasMoonpearl, canMeltThings);
+const canEnterIP = when(isInverted,
+ and(canSwim, canMeltThings),
+ and(canSwim, canHeavyLift, hasMoonpearl, canMeltThings),
+);
const rightSideIP = or(hasHookshot, hasSmall('ip'));
-const canEnterMM = and(
- mireArea,
- hasMoonpearl,
- hasMMMedallion,
- canMedallion,
- or(canBonk, hasHookshot),
- canKill(8),
+const canEnterMM = when(isInverted,
+ and(
+ mireArea,
+ hasMMMedallion,
+ canMedallion,
+ or(canBonk, hasHookshot),
+ canKill(8),
+ ),
+ and(
+ mireArea,
+ hasMoonpearl,
+ hasMMMedallion,
+ canMedallion,
+ or(canBonk, hasHookshot),
+ canKill(8),
+ ),
);
-const canEnterTRFront = and(
- eastDeathMountain,
- canHeavyLift,
- hasHammer,
- hasMoonpearl,
- canMedallion,
- hasTRMedallion,
+const canEnterTRFront = when(isInverted,
+ and(
+ eastDarkDeathMountain,
+ canMedallion,
+ hasTRMedallion,
+ hasSomaria,
+ ),
+ and(
+ eastDeathMountain,
+ canHeavyLift,
+ hasHammer,
+ hasMoonpearl,
+ canMedallion,
+ hasTRMedallion,
+ hasSomaria,
+ ),
+);
+const canEnterTRWest = when(isInverted,
+ and(eastDeathMountain, hasMirror),
+ neverAvailable,
);
-const canEnterTRWest = and(canEnterTRFront, canBomb, hasSmall('tr', 2));
const canEnterTREast = and(canEnterTRWest, or(hasHookshot, hasSomaria));
-const canEnterTRBack = and(
- or(canEnterTRWest, canEnterTREast),
- or(canBomb, canBonk),
- hasBig('tr'),
- hasSmall('tr', 3),
- hasSomaria,
- canDarkRoom,
+const canEnterTRBack = when(isInverted,
+ and(eastDeathMountain, hasMirror),
+ neverAvailable,
);
const laserBridge = or(
and(
- or(canEnterDPFront, canEnterTRWest, canEnterTREast),
+ or(canEnterTRFront, canEnterTRWest, canEnterTREast),
canDarkRoom,
hasSomaria,
hasBig('tr'),
const Logic = {};
-Logic.open = {
- fallback: () => 'available',
- aginah: fromBool(canBomb),
- blacksmith: fromBool(canRescueSmith),
- 'blinds-hut-top': fromBool(canBomb),
- 'bombos-tablet': fromBool(and(southDarkWorld, hasMirror, canTablet)),
- 'bonk-rocks': fromBool(canBonk),
- brewery: fromBool(and(westDarkWorld, canBomb, hasMoonpearl)),
- 'bumper-cave': fromBool(and(westDarkWorld, hasMoonpearl, canLift, hasCape)),
- 'c-house': fromBool(and(westDarkWorld, hasMoonpearl)),
- catfish: fromBool(and(eastDarkWorld, hasMoonpearl)),
- 'cave-45': fromBool(and(southDarkWorld, hasMirror)),
- checkerboard: fromBool(and(mireArea, hasMirror)),
- 'chest-game': fromBool(and(westDarkWorld, hasMoonpearl)),
- 'chicken-house': fromBool(canBomb),
- 'desert-ledge': fromBool(canEnterDPFront),
- 'digging-game': fromBool(and(southDarkWorld, hasMoonpearl)),
- 'ether-tablet': fromBool(and(northDeathMountain, canTablet)),
- 'floating-island': fromBool(
- and(eastDarkDeathMountain, hasMoonpearl, canLift, canBomb, hasMirror),
- ),
- 'flute-spot': fromBool(hasShovel),
- 'graveyard-ledge': fromBool(and(westDarkWorld, hasMoonpearl, hasMirror)),
- 'hammer-pegs': fromBool(and(westDarkWorld, hasHammer, hasMoonpearl, canHeavyLift)),
- hobo: fromBool(canSwim),
- 'hookshot-cave-tl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
- 'hookshot-cave-tr': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
- 'hookshot-cave-bl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
- 'hookshot-cave-br': fromBool(
- and(eastDarkDeathMountain, hasMoonpearl, canLift, or(hasHookshot, canBonk)),
- ),
- 'hype-cave-npc': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
- 'hype-cave-top': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
- 'hype-cave-right': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
- 'hype-cave-left': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
- 'hype-cave-bottom': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
- 'ice-rod-cave': fromBool(canBomb),
- 'kak-well-top': fromBool(canBomb),
- 'kings-tomb': fromBool(and(canBonk, or(canHeavyLift, and(westDarkWorld, hasMirror)))),
- 'lake-hylia-island': fromBool(
- and(canSwim, hasMirror, hasMoonpearl, or(eastDarkWorld, southDarkWorld)),
- ),
- library: fromBool(canBonk),
- lumberjack: fromBool(and(canBonk, agaDead)),
- 'magic-bat': fromBool(and(hasPowder,
- or(hasHammer, and(westDarkWorld, hasMoonpearl, canHeavyLift, hasMirror)),
- )),
- 'mimic-cave': fromBool(and(canEnterTREast, hasMirror, hasHammer)),
- 'mini-moldorm-left': fromBool(canBomb),
- 'mini-moldorm-right': fromBool(canBomb),
- 'mini-moldorm-far-left': fromBool(canBomb),
- 'mini-moldorm-far-right': fromBool(canBomb),
- 'mini-moldorm-npc': fromBool(canBomb),
- 'mire-shed-left': fromBool(and(mireArea, hasMoonpearl)),
- 'mire-shed-right': fromBool(and(mireArea, hasMoonpearl)),
- 'old-man': fromBool(and(westDeathMountain, canDarkRoom)),
- 'paradox-lower-far-left': fromBool(paradoxLower),
- 'paradox-lower-left': fromBool(paradoxLower),
- 'paradox-lower-right': fromBool(paradoxLower),
- 'paradox-lower-far-right': fromBool(paradoxLower),
- 'paradox-lower-mid': fromBool(paradoxLower),
- 'paradox-upper-left': fromBool(and(eastDeathMountain, canBomb)),
- 'paradox-upper-right': fromBool(and(eastDeathMountain, canBomb)),
- pedestal: fromBool(hasPendants(3)),
- 'potion-shop': fromBool(hasMushroom),
- 'purple-chest': fromBool(and(canRescueSmith, hasMoonpearl, canHeavyLift)),
- pyramid: fromBool(eastDarkWorld),
- 'pyramid-fairy-left': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
- 'pyramid-fairy-right': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
- 'race-game': fromBool(or(canBomb, canBonk)),
- saha: fromBool(hasGreenPendant),
- 'saha-left': fromBool(or(canBomb, canBonk)),
- 'saha-mid': fromBool(or(canBomb, canBonk)),
- 'saha-right': fromBool(or(canBomb, canBonk)),
- 'sick-kid': fromBool(hasBottle(1)),
- 'spec-rock': fromBool(and(westDeathMountain, hasMirror)),
- 'spec-rock-cave': fromBool(westDeathMountain),
- 'spike-cave': fromBool(and(
- westDarkDeathMountain,
- hasMoonpearl,
- hasHammer,
- canLift,
- or(hasByrna, and(hasCape, hasMagicBars(2))),
- )),
- 'spiral-cave': fromBool(eastDeathMountain),
- stumpy: fromBool(and(southDarkWorld, hasMoonpearl)),
- 'super-bunny-top': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
- 'super-bunny-bottom': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
- 'waterfall-fairy-left': fromBool(canSwim),
- 'waterfall-fairy-right': fromBool(canSwim),
- zora: fromBool(or(canLift, canSwim)),
- 'zora-ledge': fromBool(canSwim),
+Logic.dungeonInterior = {
'hc-boom': fromBool(and(hasSmall('hc'), canKill())),
'hc-cell': fromBool(and(hasSmall('hc'), canKill())),
'dark-cross': fromBool(canTorchDarkRoom),
'sewers-left': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
'sewers-mid': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
'sewers-right': fromBool(or(canLift, and(canTorchDarkRoom, hasSmall('hc'), canKill()))),
- ct: fromBool(canEnterCT),
'ct-1': fromBool(canKill()),
'ct-2': fromBool(and(canKill(), hasSmall('ct'), canDarkRoom)),
'ct-boss-killable': fromBool(and(
canKill(), hasSmall('ct', 2), canDarkRoom, canPassCurtains, canKillBoss('ct'),
)),
- gt: fromBool(canEnterGT),
'gt-tile-room': fromBool(hasSomaria),
'gt-compass-tl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
'gt-compass-tr': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))),
'ep-boss-defeated': fromBool(and(
canShootArrows, canTorchDarkRoom, hasBig('ep'), canKillBoss('ep'),
)),
- dp: fromBool(or(canEnterDPFront, canEnterDPBack)),
'dp-big-chest': fromBool(and(canEnterDPFront, hasBig('dp'))),
'dp-big-key-chest': fromBool(and(canEnterDPFront, hasSmall('dp'), canKill())),
'dp-compass-chest': fromBool(and(canEnterDPFront, hasSmall('dp'))),
hasSmall('dp'),
canKillBoss('dp'),
)),
- th: fromBool(canEnterTH),
'th-basement-cage': fromBool(canFlipSwitches),
'th-map-chest': fromBool(canFlipSwitches),
'th-big-key-chest': fromBool(and(canFlipSwitches, hasSmall('th'), canTorch)),
hasBig('th'),
canKillBoss('th'),
)),
- pd: fromBool(canEnterPD),
'pd-stalfos-basement': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
'pd-big-key-chest': fromBool(hasSmall('pd', 6)),
'pd-arena-bridge': fromBool(or(hasSmall('pd', 1), and(canShootArrows, hasHammer))),
'pd-boss-defeated': fromBool(and(
canDarkRoom, hasBig('pd'), hasSmall('pd', 6), canShootArrows, hasHammer, canKillBoss('pd'),
)),
- sp: fromBool(canEnterSP),
'sp-map-chest': fromBool(and(hasSmall('sp'), canBomb)),
'sp-big-chest': fromBool(and(hasSmall('sp'), hasHammer, hasBig('sp'))),
'sp-compass-chest': fromBool(and(hasSmall('sp'), hasHammer)),
'sp-flooded-right': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
'sp-waterfall': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)),
'sp-boss-defeated': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot, canKillBoss('sp'))),
- sw: fromBool(or(canEnterSWFront, canEnterSWMid, canEnterSWBack)),
'sw-big-chest': fromBool(and(canEnterSWFront, hasBig('sw'))),
'sw-bridge-chest': fromBool(canEnterSWBack),
'sw-boss-defeated': fromBool(and(
canEnterSWBack, canPassCurtains, hasFireRod, hasSmall('sw', 3), canKillBoss('sw'),
)),
- tt: fromBool(canEnterTT),
'tt-attic': fromBool(and(hasBig('tt'), hasSmall('tt'), canBomb)),
'tt-cell': fromBool(hasBig('tt')),
'tt-big-chest': fromBool(and(hasBig('tt'), hasSmall('tt'), hasHammer)),
'tt-boss-defeated': fromBool(and(hasBig('tt'), hasSmall('tt'), canKillBoss('tt'))),
- ip: fromBool(canEnterIP),
'ip-big-key-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
'ip-map-chest': fromBool(and(rightSideIP, hasHammer, canLift)),
'ip-spike-chest': fromBool(rightSideIP),
or(hasSmall('ip', 2), and(hasSomaria, hasSmall('ip'))),
canKillBoss('ip'),
)),
- mm: fromBool(canEnterMM),
'mm-lobby-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
'mm-compass-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
'mm-big-key-chest': fromBool(and(canTorch, hasSmall('mm', 3))),
'mm-big-chest': fromBool(hasBig('mm')),
'mm-map-chest': fromBool(or(hasBig('mm'), hasSmall('mm'))),
'mm-boss-defeated': fromBool(and(hasBig('mm'), canDarkRoom, hasSomaria, canKillBoss('mm'))),
- tr: fromBool(or(canEnterTRFront, canEnterTRWest, canEnterTREast, canEnterTRBack)),
'tr-roller-left': fromBool(and(hasFireRod, hasSomaria, or(
canEnterTRFront,
and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)),
)),
};
+Logic.open = {
+ fallback: fromBool(alwaysAvailable),
+ aginah: fromBool(canBomb),
+ blacksmith: fromBool(canRescueSmith),
+ 'blinds-hut-top': fromBool(canBomb),
+ 'bombos-tablet': fromBool(and(southDarkWorld, hasMirror, canTablet)),
+ 'bonk-rocks': fromBool(canBonk),
+ brewery: fromBool(and(westDarkWorld, canBomb, hasMoonpearl)),
+ 'bumper-cave': fromBool(and(westDarkWorld, hasMoonpearl, canLift, hasCape)),
+ 'c-house': fromBool(and(westDarkWorld, hasMoonpearl)),
+ catfish: fromBool(and(eastDarkWorld, hasMoonpearl)),
+ 'cave-45': fromBool(and(southDarkWorld, hasMirror)),
+ checkerboard: fromBool(and(mireArea, hasMirror)),
+ 'chest-game': fromBool(and(westDarkWorld, hasMoonpearl)),
+ 'chicken-house': fromBool(canBomb),
+ 'desert-ledge': fromBool(canEnterDPFront),
+ 'digging-game': fromBool(and(southDarkWorld, hasMoonpearl)),
+ 'ether-tablet': fromBool(and(northDeathMountain, canTablet)),
+ 'floating-island': fromBool(
+ and(eastDarkDeathMountain, hasMoonpearl, canLift, canBomb, hasMirror),
+ ),
+ 'flute-spot': fromBool(hasShovel),
+ 'graveyard-ledge': fromBool(and(westDarkWorld, hasMoonpearl, hasMirror)),
+ 'hammer-pegs': fromBool(and(westDarkWorld, hasHammer, hasMoonpearl, canHeavyLift)),
+ hobo: fromBool(canSwim),
+ 'hookshot-cave-tl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
+ 'hookshot-cave-tr': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
+ 'hookshot-cave-bl': fromBool(and(eastDarkDeathMountain, hasMoonpearl, canLift, hasHookshot)),
+ 'hookshot-cave-br': fromBool(
+ and(eastDarkDeathMountain, hasMoonpearl, canLift, or(hasHookshot, canBonk)),
+ ),
+ 'hype-cave-npc': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
+ 'hype-cave-top': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
+ 'hype-cave-right': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
+ 'hype-cave-left': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
+ 'hype-cave-bottom': fromBool(and(southDarkWorld, hasMoonpearl, canBomb)),
+ 'ice-rod-cave': fromBool(canBomb),
+ 'kak-well-top': fromBool(canBomb),
+ 'kings-tomb': fromBool(and(canBonk, or(canHeavyLift, and(westDarkWorld, hasMirror)))),
+ 'lake-hylia-island': fromBool(
+ and(canSwim, hasMirror, hasMoonpearl, or(eastDarkWorld, southDarkWorld)),
+ ),
+ library: fromBool(canBonk),
+ lumberjack: fromBool(and(canBonk, agaDead)),
+ 'magic-bat': fromBool(and(hasPowder,
+ or(hasHammer, and(westDarkWorld, hasMoonpearl, canHeavyLift, hasMirror)),
+ )),
+ 'mimic-cave': fromBool(and(canEnterTRFront, canBomb, hasSmall('tr', 2), hasMirror, hasHammer)),
+ 'mini-moldorm-left': fromBool(canBomb),
+ 'mini-moldorm-right': fromBool(canBomb),
+ 'mini-moldorm-far-left': fromBool(canBomb),
+ 'mini-moldorm-far-right': fromBool(canBomb),
+ 'mini-moldorm-npc': fromBool(canBomb),
+ 'mire-shed-left': fromBool(and(mireArea, hasMoonpearl)),
+ 'mire-shed-right': fromBool(and(mireArea, hasMoonpearl)),
+ 'old-man': fromBool(and(westDeathMountain, canDarkRoom)),
+ 'paradox-lower-far-left': fromBool(paradoxLower),
+ 'paradox-lower-left': fromBool(paradoxLower),
+ 'paradox-lower-right': fromBool(paradoxLower),
+ 'paradox-lower-far-right': fromBool(paradoxLower),
+ 'paradox-lower-mid': fromBool(paradoxLower),
+ 'paradox-upper-left': fromBool(and(eastDeathMountain, canBomb)),
+ 'paradox-upper-right': fromBool(and(eastDeathMountain, canBomb)),
+ pedestal: fromBool(hasPendants(3)),
+ 'potion-shop': fromBool(hasMushroom),
+ 'purple-chest': fromBool(and(canRescueSmith, hasMoonpearl, canHeavyLift)),
+ pyramid: fromBool(eastDarkWorld),
+ 'pyramid-fairy-left': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
+ 'pyramid-fairy-right': fromBool(and(hasRedCrystals(2), southDarkWorld, canBridgeRedBomb)),
+ 'race-game': fromBool(or(canBomb, canBonk)),
+ saha: fromBool(hasGreenPendant),
+ 'saha-left': fromBool(or(canBomb, canBonk)),
+ 'saha-mid': fromBool(or(canBomb, canBonk)),
+ 'saha-right': fromBool(or(canBomb, canBonk)),
+ 'sick-kid': fromBool(hasBottle(1)),
+ 'spec-rock': fromBool(and(westDeathMountain, hasMirror)),
+ 'spec-rock-cave': fromBool(westDeathMountain),
+ 'spike-cave': fromBool(and(
+ westDarkDeathMountain,
+ hasMoonpearl,
+ hasHammer,
+ canLift,
+ or(hasByrna, and(hasCape, hasMagicBars(2))),
+ )),
+ 'spiral-cave': fromBool(eastDeathMountain),
+ stumpy: fromBool(and(southDarkWorld, hasMoonpearl)),
+ 'super-bunny-top': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
+ 'super-bunny-bottom': fromBool(and(eastDarkDeathMountain, hasMoonpearl)),
+ 'waterfall-fairy-left': fromBool(canSwim),
+ 'waterfall-fairy-right': fromBool(canSwim),
+ zora: fromBool(or(canLift, canSwim)),
+ 'zora-ledge': fromBool(canSwim),
+ ct: fromBool(canEnterCT),
+ gt: fromBool(canEnterGT),
+ dp: fromBool(or(canEnterDPFront, canEnterDPBack)),
+ th: fromBool(canEnterTH),
+ pd: fromBool(canEnterPD),
+ sp: fromBool(canEnterSP),
+ sw: fromBool(or(canEnterSWFront, canEnterSWMid, canEnterSWBack)),
+ tt: fromBool(canEnterTT),
+ ip: fromBool(canEnterIP),
+ mm: fromBool(canEnterMM),
+ tr: fromBool(or(canEnterTRFront, canEnterTRWest, canEnterTREast, canEnterTRBack)),
+ ...Logic.dungeonInterior,
+};
+
+Logic.inverted = {
+ fallback: fromBool(alwaysAvailable),
+ aginah: fromBool(and(southLightWorld, hasMoonpearl, canBomb)),
+ blacksmith: fromBool(and(or(canHeavyLift, hasMirror), westLightWorld)),
+ 'blinds-hut-top': fromBool(and(westLightWorld, hasMoonpearl, canBomb)),
+ 'blinds-hut-far-left': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'blinds-hut-left': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'blinds-hut-right': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'blinds-hut-far-right': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'bombos-tablet': fromBool(and(southLightWorld, canTablet)),
+ 'bonk-rocks': fromBool(and(westLightWorld, hasMoonpearl, canBonk)),
+ 'bottle-vendor': fromBool(westLightWorld),
+ brewery: fromBool(canBomb),
+ 'bumper-cave': fromBool(and(canLift, hasCape, hasMoonpearl, hasMirror, westLightWorld)),
+ catfish: fromBool(or(
+ and(eastDarkWorld, canLift),
+ and(hasMirror, southLightWorld, hasMoonpearl, canSwim),
+ )),
+ 'cave-45': fromBool(and(southLightWorld, hasMoonpearl)),
+ checkerboard: fromBool(and(southLightWorld, hasMoonpearl, canLift)),
+ 'chicken-house': fromBool(and(westLightWorld, hasMoonpearl, canBomb)),
+ 'desert-ledge': fromBool(and(hasMoonpearl, canEnterDPFront)),
+ 'ether-tablet': fromBool(and(northDeathMountain, canTablet)),
+ 'floating-island': fromBool(and(eastDeathMountain)),
+ 'flooded-chest': fromBool(and(southLightWorld, hasMoonpearl)),
+ 'flute-spot': fromBool(and(southLightWorld, hasMoonpearl, hasShovel)),
+ 'graveyard-ledge': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'hammer-pegs': fromBool(and(hasHammer, or(canHeavyLift, and(westLightWorld, hasMirror)))),
+ hobo: fromBool(and(southLightWorld, hasMoonpearl, canSwim)),
+ 'hookshot-cave-tl': fromBool(and(
+ eastDarkDeathMountain,
+ hasHookshot,
+ or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
+ )),
+ 'hookshot-cave-tr': fromBool(and(
+ eastDarkDeathMountain,
+ hasHookshot,
+ or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
+ )),
+ 'hookshot-cave-bl': fromBool(and(
+ eastDarkDeathMountain,
+ hasHookshot,
+ or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
+ )),
+ 'hookshot-cave-br': fromBool(and(
+ eastDarkDeathMountain,
+ or(canBonk, hasHookshot),
+ or(canLift, and(canBomb, hasMirror, eastDeathMountain)),
+ )),
+ 'hype-cave-npc': fromBool(canBomb),
+ 'hype-cave-top': fromBool(canBomb),
+ 'hype-cave-right': fromBool(canBomb),
+ 'hype-cave-left': fromBool(canBomb),
+ 'hype-cave-bottom': fromBool(canBomb),
+ 'ice-rod-cave': fromBool(and(southLightWorld, hasMoonpearl, canBomb)),
+ 'kak-well-top': fromBool(and(westLightWorld, hasMoonpearl, canBomb)),
+ 'kak-well-left': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'kak-well-mid': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'kak-well-right': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'kak-well-bottom': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'kings-tomb': fromBool(and(westLightWorld, hasMoonpearl, canBonk, canHeavyLift)),
+ 'lake-hylia-island': fromBool(
+ and(southLightWorld, hasMoonpearl, canSwim),
+ ),
+ library: fromBool(and(southLightWorld, hasMoonpearl, canBonk)),
+ lumberjack: fromBool(and(westLightWorld, hasMoonpearl, canBonk, agaDead)),
+ 'lost-woods-hideout': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'magic-bat': fromBool(and(westLightWorld, hasMoonpearl, hasPowder, hasHammer)),
+ 'maze-race': fromBool(and(southLightWorld, hasMoonpearl, or(canBomb, canBonk))),
+ 'mimic-cave': fromBool(and(
+ eastDeathMountain,
+ hasMoonpearl,
+ hasHammer,
+ )),
+ 'mini-moldorm-far-left': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
+ 'mini-moldorm-left': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
+ 'mini-moldorm-right': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
+ 'mini-moldorm-far-right': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
+ 'mini-moldorm-npc': fromBool(and(southLightWorld, hasMoonpearl, canBomb, canKill)),
+ 'mire-shed-left': fromBool(mireArea),
+ 'mire-shed-right': fromBool(mireArea),
+ 'mushroom-spot': fromBool(and(westLightWorld, hasMoonpearl)),
+ 'old-man': fromBool(and(westDeathMountain, canDarkRoom)),
+ 'paradox-lower-far-left': fromBool(and(hasMoonpearl, paradoxLower)),
+ 'paradox-lower-left': fromBool(and(hasMoonpearl, paradoxLower)),
+ 'paradox-lower-mid': fromBool(and(hasMoonpearl, paradoxLower)),
+ 'paradox-lower-right': fromBool(and(hasMoonpearl, paradoxLower)),
+ 'paradox-lower-far-right': fromBool(and(hasMoonpearl, paradoxLower)),
+ 'paradox-upper-left': fromBool(and(eastDeathMountain, hasMoonpearl, canBomb)),
+ 'paradox-upper-right': fromBool(and(eastDeathMountain, hasMoonpearl, canBomb)),
+ pedestal: fromBool(and(westLightWorld, hasPendants(3))),
+ 'potion-shop': fromBool(and(eastLightWorld, hasMushroom, hasMoonpearl)),
+ 'purple-chest': fromBool(and(or(canHeavyLift, hasMirror), westLightWorld, southLightWorld)),
+ pyramid: fromBool(eastDarkWorld),
+ 'pyramid-fairy-left': fromBool(and(hasRedCrystals(2), hasMirror)),
+ 'pyramid-fairy-right': fromBool(and(hasRedCrystals(2), hasMirror)),
+ 'race-game': fromBool(and(westLightWorld, hasMoonpearl, or(canBomb, canBonk))),
+ saha: fromBool(and(eastLightWorld, hasGreenPendant)),
+ 'saha-left': fromBool(and(eastLightWorld, hasMoonpearl, or(canBomb, canBonk))),
+ 'saha-mid': fromBool(and(eastLightWorld, hasMoonpearl, or(canBomb, canBonk))),
+ 'saha-right': fromBool(and(eastLightWorld, or(canBomb, canBonk))),
+ 'secret-passage': fromBool(and(eastLightWorld, hasMoonpearl)),
+ 'sick-kid': fromBool(and(westLightWorld, hasBottle(1))),
+ 'spec-rock': fromBool(northDeathMountain),
+ 'spec-rock-cave': fromBool(westDeathMountain),
+ 'spike-cave': fromBool(and(
+ westDarkDeathMountain,
+ hasHammer,
+ canLift,
+ or(hasByrna, and(hasCape, hasMagicBars(2))),
+ )),
+ 'spiral-cave': fromBool(and(
+ eastDeathMountain,
+ hasMoonpearl,
+ )),
+ 'sunken-treasure': fromBool(and(southLightWorld, hasMoonpearl)),
+ 'super-bunny-top': fromBool(eastDarkDeathMountain),
+ 'super-bunny-bottom': fromBool(eastDarkDeathMountain),
+ tavern: fromBool(and(westLightWorld, hasMoonpearl)),
+ uncle: fromBool(and(eastLightWorld, hasMoonpearl)),
+ 'waterfall-fairy-left': fromBool(and(eastLightWorld, hasMoonpearl, canSwim)),
+ 'waterfall-fairy-right': fromBool(and(eastLightWorld, hasMoonpearl, canSwim)),
+ zora: fromBool(and(eastLightWorld, hasMoonpearl, or(canLift, canSwim))),
+ 'zora-ledge': fromBool(and(eastLightWorld, hasMoonpearl, canSwim)),
+ hc: fromBool(canEnterHC),
+ ct: fromBool(canEnterCT),
+ gt: fromBool(canEnterGT),
+ ep: fromBool(canEnterEP),
+ dp: fromBool(canEnterDPFront),
+ th: fromBool(canEnterTH),
+ pd: fromBool(canEnterPD),
+ sp: fromBool(canEnterSP),
+ sw: fromBool(or(canEnterSWFront, canEnterSWMid, canEnterSWBack)),
+ tt: fromBool(canEnterTT),
+ ip: fromBool(canEnterIP),
+ mm: fromBool(canEnterMM),
+ tr: fromBool(or(canEnterTRFront, canEnterTRWest, canEnterTREast, canEnterTRBack)),
+ ...Logic.dungeonInterior,
+};
+
export default Logic;