X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=resources%2Fjs%2Fhelpers%2Flogic.js;fp=resources%2Fjs%2Fhelpers%2Flogic.js;h=2484dc007a08d3e05636d0c1fb606b1a35869fe4;hb=d2e89b06bd80faa5085c454709c7e48c829cc6f2;hp=0000000000000000000000000000000000000000;hpb=249e06be11d0f7778d99956c87d4f0a8ac7e69f7;p=alttp.git diff --git a/resources/js/helpers/logic.js b/resources/js/helpers/logic.js new file mode 100644 index 0000000..2484dc0 --- /dev/null +++ b/resources/js/helpers/logic.js @@ -0,0 +1,679 @@ +import { + getDungeonBoss, + getDungeonPrize, + getGTBoss, + getGTCrystals, + hasDungeonBoss, + hasDungeonPrize, +} from './tracker'; + +const and = (...predicates) => (...args) => + predicates.reduce((acc, cur) => acc && cur(...args), true); + +const or = (...predicates) => (...args) => + predicates.reduce((acc, cur) => acc || cur(...args), false); + +const fromBool = b => (...args) => b(...args) ? 'available' : 'unavailable'; + +const agaDead = (config, dungeons, state) => + hasDungeonBoss(state, dungeons.find(d => d.id === 'ct')); + +const countCrystals = (config, dungeons, state) => dungeons + .filter(dungeon => + (getDungeonPrize(state, dungeon) || 'crystal').endsWith('crystal') && + dungeon.prize && + hasDungeonPrize(state, dungeon) + ).length; + +const countRedCrystals = (config, dungeons, state) => dungeons + .filter(dungeon => + getDungeonPrize(state, dungeon) === 'red-crystal' && + hasDungeonPrize(state, dungeon) + ).length; + +const hasRedCrystals = n => (...args) => countRedCrystals(...args) >= n; + +const hasGTCrystals = (config, dungeons, state) => + countCrystals(config, dungeons, state) >= getGTCrystals(state); + +const countPendants = (config, dungeons, state) => dungeons + .filter(dungeon => + (getDungeonPrize(state, dungeon) || '').endsWith('pendant') && + hasDungeonPrize(state, dungeon) + ).length; + +const hasGreenPendant = (config, dungeons, state) => dungeons + .filter(dungeon => + getDungeonPrize(state, dungeon) === 'green-pendant' && + hasDungeonPrize(state, dungeon) + ).length >= 1; + +const hasPendants = n => (...args) => countPendants(...args) >= n; + +// Equipment + +const hasBig = dungeon => (config, dungeons, state) => + !config.wildBig || !!state[`${dungeon}-big-key`]; + +const hasBird = (config, dungeons, state) => !!state['bird']; + +const hasBombos = (config, dungeons, state) => !!state['bombos']; + +const hasBook = (config, dungeons, state) => !!state['book']; + +const hasBoom = (config, dungeons, state) => !!(state['blue-boomerang'] || state['red-boomerang']); + +const hasBoots = (config, dungeons, state) => !!state['boots']; + +const hasBottle = n => (config, dungeons, state) => state['bottle'] >= (n || 1); + +const hasBow = (config, dungeons, state) => !!state['bow']; + +const hasBugnet = (config, dungeons, state) => !!state['bugnet']; + +const hasByrna = (config, dungeons, state) => !!state['byrna']; + +const hasCape = (config, dungeons, state) => !!state['cape']; + +const hasFireRod = (config, dungeons, state) => !!state['fire-rod']; + +const hasFlute = (config, dungeons, state) => !!state['flute']; + +const hasHammer = (config, dungeons, state) => !!state['hammer']; + +const hasHookshot = (config, dungeons, state) => !!state['hookshot']; + +const hasIceRod = (config, dungeons, state) => !!state['ice-rod']; + +const hasLamp = (config, dungeons, state) => !!state['lamp']; + +const hasMagicBars = n => (config, dungeons, state) => { + let bars = 1 + (state['bottle'] || 0); + if (state['half-magic']) { + bars *= 2; + } + if (state['quarter-magic']) { + bars *= 2; + } + return bars >= (n || 1); +}; + +const hasMirror = (config, dungeons, state) => !!state['mirror']; + +const hasMMMedallion = (config, dungeons, state) => + !!state['mm-medallion'] && !!state[state['mm-medallion']]; + +const hasMoonpearl = (config, dungeons, state) => !!state['moonpearl']; + +const hasMushroom = (config, dungeons, state) => !!state['mushroom']; + +const hasPowder = (config, dungeons, state) => !!state['powder']; + +const hasQuake = (config, dungeons, state) => !!state['quake']; + +const hasShovel = (config, dungeons, state) => !!state['shovel']; + +const hasSmall = (dungeon, amount) => (config, dungeons, state) => + !config.wildSmall || state[`${dungeon}-small-key`] >= (amount || 1); + +const hasSomaria = (config, dungeons, state) => !!state['somaria']; + +const hasSword = n => (config, dungeons, state) => state['sword'] >= (n || 1); + +const hasTRMedallion = (config, dungeons, state) => + !!state['tr-medallion'] && !!state[state['tr-medallion']]; + +// Abilities + +const canActivateFlute = () => true; + +const canBomb = () => true; + +const canBonk = hasBoots; + +const canDarkRoom = hasLamp; + +const canFlipSwitches = or( + canBomb, + hasBoom, + canShootArrows, + hasSword(), + hasHammer, + hasHookshot, + hasSomaria, + hasByrna, + hasFireRod, + 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 canKill = damage => damage && damage < 6 + ? or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1), canBomb, hasByrna) + : or(hasBow, hasFireRod, hasHammer, hasSomaria, hasSword(1)); + +const canMedallion = hasSword(); + +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)); + +const canTorch = or(hasFireRod, hasLamp); + +const canTorchDarkRoom = or(canDarkRoom, canTorch); + +// Regions + +const westDeathMountain = or( + canFly, + and(canLift, canDarkRoom), +); + +const eastDeathMountain = and( + westDeathMountain, + or( + hasHookshot, + and(hasHammer, hasMirror), + ), +); + +const northDeathMountain = and( + westDeathMountain, + or( + hasMirror, + and(hasHammer, hasHookshot), + ), +); + +const eastDarkDeathMountain = and( + eastDeathMountain, + canHeavyLift, +); + +const westDarkDeathMountain = westDeathMountain; + +const eastDarkWorld = and( + hasMoonpearl, + or( + agaDead, + canHeavyLift, + and(canLift, hasHammer), + ), +); + +const westDarkWorld = and( + hasMoonpearl, + or( + and(canLift, hasHammer), + canHeavyLift, + and(eastDarkWorld, hasHookshot, or(canSwim, canLift, hasHammer)), + ), +); + +const southDarkWorld = or( + westDarkWorld, + and(eastDarkWorld, hasMoonpearl, hasHammer), +); + +const mireArea = and(canFly, canHeavyLift); + +// Bosses + +const BOSS_RULES = { + aga: or(hasBugnet, hasHammer, hasSword()), + armos: or( + hasSword(), hasHammer, canShootArrows, hasBoom, + and(hasMagicBars(4), or(hasFireRod, hasIceRod)), + and(hasMagicBars(2), or(hasByrna, hasSomaria)), + ), + arrghus: and(hasHookshot, or( + hasSword(), + hasHammer, + and(or(hasMagicBars(2), canShootArrows), or(hasFireRod, hasIceRod)), + )), + blind: or(hasSword(), hasHammer, hasSomaria, hasByrna), + helma: and(or(canBomb, hasHammer), or(hasSword(), canShootArrows)), + kholdstare: and(canMeltThings, or( + hasHammer, + hasSword(), + and(hasFireRod, hasMagicBars(3)), + and(hasFireRod, hasBombos, hasMagicBars(2), canMedallion), + )), + lanmolas: or( + hasSword(), hasHammer, canShootArrows, hasFireRod, hasIceRod, hasByrna, hasSomaria, + ), + moldorm: or(hasSword(), hasHammer), + mothula: or( + hasSword(), + hasHammer, + and(hasMagicBars(2), or(hasFireRod, hasSomaria, hasByrna)), + canGetGoodBee, + ), + trinexx: and(hasFireRod, hasIceRod, or( + hasSword(3), + hasHammer, + and(hasMagicBars(2), hasSword(2)), + and(hasMagicBars(4), hasSword(1)), + )), + vitreous: or(hasSword(), hasHammer, canShootArrows), +}; + +const canKillBoss = dungeon => (config, dungeons, state) => { + const boss = getDungeonBoss(state, dungeons.find(d => d.id === dungeon)); + return BOSS_RULES[boss](config, dungeons, state); +}; + +const canKillGTBoss = which => (config, dungeons, state) => { + const boss = getGTBoss(state, which); + return BOSS_RULES[boss](config, dungeons, state); +}; + +// Dungeons + +const canEnterCT = or(hasCape, hasSword(2)); + +const canEnterGT = and(eastDarkDeathMountain, hasGTCrystals, hasMoonpearl); + +const canEnterDPFront = or(hasBook, and(mireArea, hasMirror)); +const canEnterDPBack = or(and(canEnterDPFront, canLift), and(mireArea, hasMirror)); + +const canEnterTH = northDeathMountain; + +const canEnterPD = and(eastDarkWorld, hasMoonpearl); + +const canEnterSP = and(southDarkWorld, hasMirror, hasMoonpearl, canSwim); + +const canEnterSWFront = and(westDarkWorld, hasMoonpearl); +const canEnterSWMid = and(westDarkWorld, hasMoonpearl); +const canEnterSWBack = and(westDarkWorld, hasMoonpearl, hasFireRod); + +const canEnterTT = and(westDarkWorld, hasMoonpearl); + +const canEnterIP = and(canSwim, canHeavyLift, hasMoonpearl, canMeltThings); +const rightSideIP = or(hasHookshot, hasSmall('ip')); + +const canEnterMM = and( + mireArea, + hasMoonpearl, + hasMMMedallion, + canMedallion, + or(canBonk, hasHookshot), + canKill(8), +); + +const canEnterTRFront = and( + eastDeathMountain, + canHeavyLift, + hasHammer, + hasMoonpearl, + canMedallion, + hasTRMedallion, +); +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 laserBridge = or( + and( + or(canEnterDPFront, canEnterTRWest, canEnterTREast), + canDarkRoom, + hasSomaria, + hasBig('tr'), + hasSmall('tr', 3), + ), + canEnterTRBack, +); + +// Misc Macros + +const paradoxLower = and(eastDeathMountain, or(canBomb, hasBoom, canShootArrows, hasSomaria)); + +const canBridgeRedBomb = or( + and(hasMoonpearl, hasHammer), + and(agaDead, hasMirror), +); + +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), + '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))), + 'gt-compass-bl': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))), + 'gt-compass-br': fromBool(and(hasSomaria, hasFireRod, hasSmall('gt', 4))), + 'gt-torch': fromBool(canBonk), + 'gt-dm-tl': fromBool(and(hasHammer, hasHookshot)), + 'gt-dm-tr': fromBool(and(hasHammer, hasHookshot)), + 'gt-dm-bl': fromBool(and(hasHammer, hasHookshot)), + 'gt-dm-br': fromBool(and(hasHammer, hasHookshot)), + 'gt-map-chest': fromBool(and(hasHammer, or(hasHookshot, canBonk), hasSmall('gt', 4))), + 'gt-firesnake': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 3))), + 'gt-rando-tl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))), + 'gt-rando-tr': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))), + 'gt-rando-bl': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))), + 'gt-rando-br': fromBool(and(hasHammer, hasHookshot, hasSmall('gt', 4))), + 'gt-bobs-chest': fromBool(and( + or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)), + hasSmall('gt', 3), + )), + 'gt-ice-left': fromBool(and( + or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)), + hasSmall('gt', 3), + canKillGTBoss('bot'), + )), + 'gt-ice-mid': fromBool(and( + or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)), + hasSmall('gt', 3), + canKillGTBoss('bot'), + )), + 'gt-ice-right': fromBool(and( + or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)), + hasSmall('gt', 3), + canKillGTBoss('bot'), + )), + 'gt-big-chest': fromBool(and( + or(and(hasHammer, hasHookshot), and(hasFireRod, hasSomaria)), + hasSmall('gt', 3), + hasBig('gt'), + )), + 'gt-helma-left': fromBool(and( + hasBig('gt'), + hasSmall('gt', 3), + canShootArrows, + canTorch, + canKillGTBoss('mid'), + )), + 'gt-helma-right': fromBool(and( + hasBig('gt'), + hasSmall('gt', 3), + canShootArrows, + canTorch, + canKillGTBoss('mid'), + )), + 'gt-pre-moldorm': fromBool(and( + hasBig('gt'), + hasSmall('gt', 3), + canShootArrows, + canTorch, + canKillGTBoss('mid'), + )), + 'gt-post-moldorm': fromBool(and( + hasBig('gt'), + hasSmall('gt', 4), + canShootArrows, + canTorch, + canKillGTBoss('mid'), + canKillGTBoss('top'), + hasHookshot, + )), + 'gt-boss-killable': fromBool(and( + hasBig('gt'), + hasSmall('gt', 4), + canShootArrows, + canTorch, + canKillGTBoss('mid'), + canKillGTBoss('top'), + hasHookshot, + canKillBoss('ct'), + )), + 'ep-big-chest': fromBool(hasBig('ep')), + 'ep-big-key-chest': fromBool(canDarkRoom), + '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'))), + 'dp-map-chest': fromBool(canEnterDPFront), + 'dp-torch': fromBool(and(canEnterDPFront, canBonk)), + 'dp-boss-defeated': fromBool(and( + canEnterDPBack, + canTorch, + hasBig('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)), + 'th-compass-chest': fromBool(and(canFlipSwitches, hasBig('th'))), + 'th-big-chest': fromBool(and(canFlipSwitches, hasBig('th'))), + 'th-boss-defeated': fromBool(and( + canFlipSwitches, + 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-arena-ledge': fromBool(canShootArrows), + 'pd-map-chest': fromBool(canShootArrows), + 'pd-compass-chest': fromBool(hasSmall('pd', 4)), + 'pd-basement-left': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))), + 'pd-basement-right': fromBool(and(canTorchDarkRoom, hasSmall('pd', 4))), + 'pd-harmless-hellway': fromBool(hasSmall('pd', 6)), + 'pd-maze-top': fromBool(and(canDarkRoom, hasSmall('pd', 6))), + 'pd-maze-bottom': fromBool(and(canDarkRoom, hasSmall('pd', 6))), + 'pd-big-chest': fromBool(and(canDarkRoom, hasBig('pd'), hasSmall('pd', 6))), + '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-west-chest': fromBool(and(hasSmall('sp'), hasHammer)), + 'sp-big-key-chest': fromBool(and(hasSmall('sp'), hasHammer)), + 'sp-flooded-left': fromBool(and(hasSmall('sp'), hasHammer, hasHookshot)), + '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), + 'ip-freezor-chest': fromBool(canMeltThings), + 'ip-big-chest': fromBool(hasBig('ip')), + 'ip-boss-defeated': fromBool(and( + hasBig('ip'), + hasHammer, + canLift, + 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)), + and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)), + ))), + 'tr-roller-right': fromBool(and(hasFireRod, hasSomaria, or( + canEnterTRFront, + and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)), + and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)), + ))), + 'tr-compass-chest': fromBool(and(hasSomaria, or( + canEnterTRFront, + and(or(canEnterTRWest, canEnterTREast), hasSmall('tr', 4)), + and(canEnterTRBack, canDarkRoom, hasSmall('tr', 4)), + ))), + 'tr-chomps': fromBool(or( + and(canEnterTRFront, hasSmall('tr')), + canEnterTRWest, + canEnterTREast, + and(canEnterTRBack, canDarkRoom, hasSomaria), + )), + 'tr-big-key-chest': fromBool(and(hasSmall('tr', 4), or( + and(canEnterTRFront, hasSomaria), + canEnterTRWest, + canEnterTREast, + and(canEnterTRBack, canDarkRoom, hasSomaria), + ))), + 'tr-big-chest': fromBool(canEnterTREast), + 'tr-crysta-roller': fromBool(or( + and(hasBig('tr'), or( + and(canEnterTRFront, hasSomaria, hasSmall('tr', 2)), + canEnterTRWest, + canEnterTREast, + )), + and(canEnterTRBack, canDarkRoom, hasSomaria), + )), + 'tr-laser-bridge-top': fromBool(laserBridge), + 'tr-laser-bridge-left': fromBool(laserBridge), + 'tr-laser-bridge-right': fromBool(laserBridge), + 'tr-laser-bridge-bottom': fromBool(laserBridge), + 'tr-boss-defeated': fromBool(and( + laserBridge, + hasSmall('tr', 4), + hasBig('tr'), + hasSomaria, + canKillBoss('tr'), + )), +}; + +export default Logic;