X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=resources%2Fjs%2Fhelpers%2Flogic.js;h=de4da81cbb039fa99f3852e9abcf7c32014bd732;hb=816690cc4fadff954f4407999550f7feec2884da;hp=175494178041d689479fcbd43e796d969ab6b407;hpb=6a65eac02f94f00fdd2d56ad8feddf5d9476aa1e;p=alttp.git diff --git a/resources/js/helpers/logic.js b/resources/js/helpers/logic.js index 1754941..de4da81 100644 --- a/resources/js/helpers/logic.js +++ b/resources/js/helpers/logic.js @@ -13,8 +13,17 @@ const and = (...predicates) => (...args) => 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')); @@ -34,7 +43,7 @@ const countRedCrystals = (config, dungeons, state) => dungeons 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 => @@ -128,14 +137,14 @@ const hasTRMedallion = (config, dungeons, state) => // Abilities -const canActivateFlute = () => true; - const canBomb = () => true; const canBonk = hasBoots; const canDarkRoom = hasLamp; +const canShootArrows = hasBow; + const canFlipSwitches = or( canBomb, hasBoom, @@ -149,14 +158,26 @@ const canFlipSwitches = or( 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)); @@ -167,8 +188,6 @@ const canMeltThings = or(hasFireRod, and(hasBombos, canMedallion)); const canPassCurtains = hasSword(); -const canShootArrows = hasBow; - const canSwim = (config, dungeons, state) => !!state['flippers']; const canTablet = and(hasBook, hasSword(2)); @@ -184,53 +203,100 @@ const westDeathMountain = or( 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(hasMirror, 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 @@ -285,58 +351,112 @@ const canKillGTBoss = which => (config, dungeons, state) => { // 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'), @@ -358,111 +478,18 @@ const canRescueSmith = and(westDarkWorld, hasMoonpearl, canHeavyLift); 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))), @@ -548,7 +575,6 @@ Logic.open = { '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'))), @@ -561,7 +587,6 @@ Logic.open = { 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)), @@ -572,7 +597,6 @@ Logic.open = { 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))), @@ -588,7 +612,6 @@ Logic.open = { '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)), @@ -598,18 +621,15 @@ Logic.open = { '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), @@ -622,14 +642,12 @@ Logic.open = { 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)), @@ -679,4 +697,250 @@ Logic.open = { )), }; +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, canLift)), + '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;