/* The Quest for the Deleted Website (quest.html only). The quest survives reloads (and even restoring the website): the save file is questHero + questPronouns (JSON) + questWeapon + questHand + questEncounters (JSON) + questEnc1 (JSON) + questEnc2 + questKid + questEnc3 + questEnc4 + questEnc5 + questPrincess + questWeaponLost + questVillain + questVillainPronouns (JSON) + questAttacked in localStorage. All story text lives in TEXT, written in full with {token} substitutions. Tokens: {name} plus the pronoun forms {subj} {obj} {posd} {refl}. Capitalize the token to capitalize the substitution: {Subj} -> "She" */ (function () { var naming = document.getElementById('naming'); if (!naming) return; var TEXT = { intro: '{name} was but a simple farmer living in the magical kingdom of' + ' Grazaikya, until one day when gade.gg was deleted.', setout: '{name} had wanted to log onto gade.gg, {posd} favorite website, but saw' + ' that it had been deleted, presumably by an evil, heartless monster.' + ' So {subj} picked up {posd} preferred weapon, and embarked on a quest' + ' to find the deleted website.', traverse: 'Clutching {posd} {weapon} in {posd} {hand} hand, {name}' + ' traversed across the lands of Grazaikya, determined to recover the' + ' deleted site.', enc1: '{name} attempted to cross a bridge over a river, but was' + ' accosted by a hideous creature. A bridge troll stopped {obj} and' + ' said "Before you may cross the river, you must first answer my' + ' riddle!".', enc1riddle: '"Very well, then", said {name}, "tell me your riddle,' + ' hideous beast". "Wow, rude" said the troll, aghast. It then stood' + ' for a moment, waiting for an apology that never came, and then' + ' continued: "I run, but never walk; I babble, but never talk. What' + ' am I?".', enc1attack: '{name} {attacked} the troll{withweapon}, but the' + ' troll attacked back, ripping off {posd} leg. {name} {attacked} the' + ' troll one more time, which ended its life. {name} hobbled away.', enc1wrong: '"{answer}?" asked {name}, unsure of {refl}. "Nope", said' + ' the troll, picking up {name} above its head. With a horrible' + " sound, the troll ripped off {name}'s leg, and threw {obj} across" + ' to the other side of the bridge. {name} hobbled away from the' + ' troll, who was laughing triumphantly.', enc1correct: '"A river!" said {name}. "Yeah, that\'s right!", answered' + ' the troll, "you\'re, like, super smart!". "Now let me pass, hideous' + ' beast", demanded {name}. The troll obliged, despite being pretty' + ' hurt by the name-calling. {name} continued onwards on {posd} quest.', enc2: 'While walking on a path through grassy fields, a young boy, no' + ' older than 16, ran up to {name}. "Are you an adventurer? Are you' + ' on a quest? Can I join?", the kid asked excitedly.', enc2yes: '"Why, certainly. The more the merrier!", said {name},' + ' cheerfully. The kid jumped up and twirled around in the air.' + ' "You won\'t regret this!", he said, foreshadowingly, "My name\'s' + ' Breigan!". Breigan and {name} continued on their quest.', enc2no: '"Shouldn\'t you be with your parents, kid?", asked {name}.' + ' The boy lowered his head and looked at the ground.' + ' "I don\'t have parents", he said, "not since the fire". He then' + ' slowly walked away, sulking, leaving {name} to continue {posd}' + ' quest alone.', enc3: 'At nightfall, {name} came across an abandoned cottage. Feeling' + ' tired, {subj} decided to use it for shelter for the night. Inside' + ' the cottage, {name} saw a seemingly untouched chest amongst the' + ' rubble. {Subj} tried to open it, but it was locked.', enc3pryBtn: 'Pry it open with your {weapon}', enc3pry: '{name} attempted to force the chest open with {posd}' + ' {weapon}. After a few tries, the chest broke open, revealing a' + ' horrifying row of teeth inside. The mimic lunged forward towards' + ' {name}, who, in {posd} panic, let go of {posd} {weapon}. {name}' + ' left the cottage, continuing the quest without {posd} {weapon}.', enc3leave: '"Better to leave things like that alone", {name} thought.' + " {Subj} had a good night's rest in the cottage, and continued" + ' onwards on {posd} quest in the morning.', enc4: 'While travelling along a road, {name} met an old man selling' + ' potions. "Potionseller!", {subj} said, "I am going into battle,' + ' and I need your strongest potions". "Well", the old man answered,' + ' "my strongest potions are quite expensive. Do you have the coin?".' + ' {name} did, in fact, not have any money.', enc4steal: '{name} {attacked} the potionseller{withweapon}, and took' + ' one of his potions. Once {subj} was far enough away, {subj} drank' + ' it. Suddenly, {subj} could feel {posd} body changing: {posd} limbs' + ' shrinking and {posd} nose embiggening. Suddenly, {name} found' + ' {refl} in the body of a pig. {Subj} sulked for a bit, and then' + ' continued onwards on {posd} quest, as a pig.', enc4explain: '"I have no money", {name} said, "but if you-", {subj}' + ' continued, but before {subj} could finish, the potionseller spat' + ' in {posd} face and said "piss off, poor-y!". {name} continued' + ' onwards on {posd} quest, potionless.', enc5: '{name} was walking along a road when {subj} passed a tower' + ' standing by the path. A beautiful young woman stuck her head out' + ' of the tallest window and shouted at {name}, "Oi! Are you here to' + ' rescue me?". Flustered, {name} answered "I wasn\'t planning on' + ' it. Are you a princess or something?". "Yeah, probably", said the' + ' likely princess.', enc5decline: '"Actually, I\'m quite busy", said {name}, walking away.' + ' "Aw, come on?", the probable princess asked. "No no, I simply' + ' must go", replied {name}, already too far away to hear whatever' + ' the potential princess said next.', enc5agree: '"All right, then", said {name}, "I\'m sure saving you' + ' won\'t take too much time". {Subj} looked at {posd} options.', enc5vines: '{name} started climbing up the side of the tower,' + ' grabbing on to the vines. The probable princess looked puzzled:' + ' "You know the door is unlocked, right?". {name}, already out of' + ' breath, replied "No, I\'ve committed now!". {Subj} had climbed up' + ' roughly 30 cm and was already straining all of {posd} muscles to' + ' hang on to the vines. "Seriously", said the princess, worried,' + ' "you should really just take the door". {name} lost {posd} grip' + ' on the vines and tumbled to the ground. Embarrassed, {subj}' + ' quickly ran away, continuing {posd} quest.', enc5door: '{name} walked up to the front door, expecting it to be' + ' locked. It was not. {Subj} then walked up the spiral staircase,' + ' expecting to be jumped by a monster or something. {Subj} was not.' + " Finally, {subj} reached the potential princess' door, which was" + ' already open. "I\'m confused", said {name}, "What did you need' + ' saving from?". "Boredom, mainly", replied the' + ' now-not-quite-so-likely princess. "I\'m Anastasia, by the way",' + ' she said, while walking down the stairs. Before {name} could' + ' protest, Anastasia had already joined {posd} quest.', princessrename: "{name} didn't like Anastasia's name, so {subj}" + ' started calling her {princess} instead.', kidrename: "{name} didn't like Breigan's name, so {subj} started" + ' calling him {kid} instead.', arrival: '{name} arrived at the tower of the evil wizard {subj} had' + ' heard was behind the deletion of gade.gg, {posd} favorite website.', confront: '{name} went inside the tower, seeing the massive dark' + ' gothic interior. There, sitting on a throne, was {vname}.' + ' "I suspect you have come to kill me", {vsubj} said, "for deleting' + ' gade.gg, your favorite website."' }; /* The showdown endings, one handwritten text per situation. Key: chosen encounters' 1-based pool positions, a colon, then one S/F letter each, all in pool order — '123:SFS' = troll+kid+mimic with only the kid failed. Success is: troll = riddle solved, Breigan = joined, mimic = chest left alone. The wizard is only beatable with >= 2 S. Villain tokens: {vname} {vsubj} {vobj} {vposd} {vrefl}. Empty entries render nothing */ var ENDINGS = { '123:SSS': '{name} ran towards {vname}, {attacking} {vobj} with {posd}' + ' {weapon}. {kid} came up behind {vname}, pushing {vobj}, and' + ' making {vobj} lose {vposd} balance. {vname} tried to cast a spell' + ' at either of them, but it was too late. {name} and {kid} killed' + ' {vname}, restoring the website for good.', '123:SSF': '{name} and {kid} ran towards {vname}, ready to punch {vobj}.' + ' With a flick of {vposd} wrist, {vname} cast a spell on {kid},' + ' disintegrating him immediately. {name} yelled out towards him, but' + ' there was nothing {subj} could do. Nothing, except avenge him.' + ' {name} ran up to {vname} and delivered a powerful punch. A punch' + ' so powerful that {vposd} head exploded. {vname} was dead, and the' + ' website was restored for good.', '123:SFS': '{name} ran towards {vname}. An epic duel commenced, with {vname}' + ' throwing spells and {name} {attacking} with {posd} {weapon}.' + ' Finally, when the dust settled, {name} stood victorious. {vname}' + ' was dead, and the website was restored for good.', '123:SFF': '{name} ran towards {vname}, ready to punch {vobj}. With a flick' + ' of {vposd} wrist, {vname} cast a spell on {name}, disintegrating' + ' {obj} immediately.', '123:FSS': '{name} hobbled towards {vname}, {attacking} {vobj} with {posd}' + ' {weapon}. {kid} came up behind {vname}, pushing {vobj}, and' + ' making {vobj} lose {vposd} balance. {vname} tried to cast a spell' + ' at either of them, but it was too late. {name} and {kid} killed' + ' {vname}, restoring the website for good.', '123:FSF': '{name} hobbled towards {vname}, ready to punch {vobj}. With a' + ' flick of {vposd} wrist, {vname} cast a spell on {kid},' + ' disintegrating him immediately. {name} yelled out towards him, but' + ' there was nothing {subj} could do. With another flick of {vposd}' + ' wrist, {vname} cast the same spell on {name}, disintegrating {obj}' + ' as well.', '123:FFS': '{name} hobbled towards {vname}, {attacking} {vobj} with {posd}' + ' {weapon}. With a flick of {vposd} wrist, {vname} cast a spell on' + ' {name}, disintegrating {obj} immediately.', '123:FFF': '{name} hobbled towards {vname}, ready to punch {vobj}. With a' + ' flick of {vposd} wrist, {vname} cast a spell on {name},' + ' disintegrating {obj} immediately.', /* Family 124 (troll, Breigan, potion): the one-legged pigs. The other six situations are aliased below */ '124:FSF': '{name} hobbled towards {vname} on {posd} three remaining' + ' trotters, {posd} {weapon} clenched in {posd} pig mouth, with' + ' {kid} running ahead. With a flick of {vposd} wrist, {vname} cast' + ' a spell on {kid}, disintegrating him immediately. {name} let out' + ' a devastated squeal. With another flick of {vposd} wrist, {vname}' + ' cast the same spell on {name}, disintegrating {obj} as well.', '124:FFF': '{name} hobbled towards {vname} on {posd} three remaining' + ' trotters, {attacking} {vobj} with {posd} {weapon}. {vname}' + ' watched the limping pig approach for a while, mildly fascinated.' + ' Then, with a flick of {vposd} wrist, {vsubj} cast a spell on' + ' {name}, disintegrating {obj} immediately.', /* Family 134 (troll, mimic, potion): no Breigan, so the win threshold lands differently — same body, different fate. The three overlapping-outcome situations are aliased below */ '134:SSF': '{name} charged towards {vname}, clutching {posd} {weapon}' + ' in {posd} pig mouth. {vname} laughed at the sight, flicking' + ' {vposd} wrist to cast a spell. But the spell missed: {vname} had' + ' never fought a pig before, and pigs are much lower to the ground' + ' than the heroes {vsubj} was used to. {name} {attacked} {vobj}' + ' before {vsubj} could try again. {vname} was dead, and the website' + ' was restored for good.', '134:SFS': '{name} ran towards {vname}, ready to punch {vobj}.' + ' {vname} flicked {vposd} wrist and cast a spell, but {name} dodged' + ' it and kept running. {Subj} reached the throne and delivered a' + ' powerful punch. A punch so powerful that {vposd} head exploded.' + ' {vname} was dead, and the website was restored for good.', '134:FSS': '{name} hobbled towards {vname}, {attacking} {vobj} with' + ' {posd} {weapon}. An epic duel commenced, with {vname} throwing' + ' spells and {name} deflecting them on one leg. Finally, when the' + ' dust settled, {name} stood victorious. {vname} was dead, and the' + ' website was restored for good.', '134:FFS': '{name} hobbled towards {vname}, ready to punch {vobj}.' + ' {vname} watched {posd} slow approach with something between pity' + ' and boredom. With a flick of {vposd} wrist, {vname} cast a spell' + ' on {name}, disintegrating {obj} immediately.', '134:FFF': '{name} hobbled towards {vname} on {posd} three remaining' + ' trotters, ready to bite {vobj}. {vname} waited politely for the' + ' pig to arrive. Then, with a flick of {vposd} wrist, {vsubj} cast' + ' a spell on {name}, disintegrating {obj} immediately.', /* Family 234 (Breigan, mimic, potion): pig situations. The human ones are aliased from family 123 below */ '234:SSF': '{name} charged towards {vname}, clutching {posd} {weapon}' + ' in {posd} pig mouth. {vname} hesitated. {Vsubj} had prepared for' + ' many things, but not for a pig with {aweapon}. {kid} used the' + ' moment to come up behind {vname}, pushing {vobj} and making {vobj}' + ' lose {vposd} balance. {name} {attacked} {vobj} before {vsubj}' + ' could get back up. {vname} was dead, and the website was restored' + ' for good.', '234:SFF': '{kid} ran towards {vname}, ready to punch {vobj}, with' + ' {name} trotting closely behind. With a flick of {vposd} wrist,' + ' {vname} cast a spell on {kid}, disintegrating him immediately.' + ' {name} let out a devastated squeal. With another flick of {vposd}' + ' wrist, {vname} cast the same spell on {name}, disintegrating {obj}' + ' as well.', '234:FSF': '{name} trotted towards {vname}, {attacking} {vobj} with' + ' {posd} {weapon}. {vname} was briefly impressed by the sight of a' + ' pig wielding {aweapon}, but not enough to be stopped. With a' + ' flick of {vposd} wrist, {vname} cast a spell on {name},' + ' disintegrating {obj} immediately.', '234:FFF': '{name} trotted towards {vname}, ready to bite {vobj}.' + ' {vname} looked at the pig for a long moment, almost feeling sorry' + ' for it. Then, with a flick of {vposd} wrist, {vsubj} cast a spell' + ' on {name}, disintegrating {obj} immediately.', /* Family 345 (mimic, potion, princess): Anastasia situations. The princess-less four are aliased below */ '345:SSS': '{name} ran towards {vname}, {attacking} {vobj} with' + ' {posd} {weapon}. {vname} blocked the attack with a shield spell' + ' and began preparing a counterattack. While the wizard was busy,' + ' {princess} calmly walked up behind {vobj} and kicked {vobj} off' + ' the throne. {name} {attacked} {vobj} one final time before' + ' {vsubj} could get up. {vname} was dead, and the website was' + ' restored for good.', '345:SFS': '{name} charged towards {vname}, clutching {posd} {weapon}' + ' in {posd} pig mouth. "Is that a pig?", asked {vname}, bewildered.' + ' "I\'m honestly as confused as you are", answered {princess},' + ' already walking up behind the throne. Before {vname} could figure' + ' out what was going on, {princess} pushed {vobj} to the ground,' + ' and {name} {attacked} {vobj}. {vname} was dead, and the website' + ' was restored for good.', '345:FSS': '{name} ran towards {vname}, ready to punch {vobj}.' + ' {vname} flicked {vposd} wrist and cast a spell at {name}, but' + ' {princess} pulled {obj} out of the way at the last moment. Before' + ' {vname} could try again, {name} reached the throne and delivered' + ' a powerful punch. A punch so powerful that {vposd} head exploded.' + ' {vname} was dead, and the website was restored for good.', '345:FFS': '{name} trotted towards {vname}, ready to bite {vobj},' + ' with {princess} walking behind. With a flick of {vposd} wrist,' + ' {vname} cast a spell at {princess}, who calmly sidestepped it.' + ' {Vsubj} then cast the same spell at {name}, who did not sidestep' + ' it, and was disintegrated immediately. {princess} shrugged, and' + ' showed herself out.', /* Family 145 (troll, potion, princess): the one-legged Anastasia situations. The other six are aliased below */ '145:FSS': '{name} hobbled towards {vname}, {attacking} {vobj} with' + ' {posd} {weapon}. {vname} aimed a spell at {posd} remaining leg,' + ' but {princess} threw a rock at {vposd} head, ruining {vposd}' + ' concentration. Before {vname} could recover, {name} reached the' + ' throne and {attacked} {vobj} one final time. {vname} was dead,' + ' and the website was restored for good.', '145:FFS': '{name} hobbled towards {vname} on {posd} three remaining' + ' trotters, {posd} {weapon} clenched in {posd} pig mouth, with' + ' {princess} walking behind. With a flick of {vposd} wrist, {vname}' + ' cast a spell at {princess}, who calmly sidestepped it. {Vsubj}' + ' then cast the same spell at {name}, who, being a three-legged' + ' pig, could not. {princess} sighed, muttered something under her' + ' breath, and left the tower.', /* Family 135 (troll, mimic, princess): one new situation — the rest alias below */ '135:FFS': '{name} hobbled towards {vname}, ready to punch {vobj},' + ' leaning on {princess} for support. With a flick of {vposd} wrist,' + ' {vname} cast a spell at {princess}, who calmly sidestepped it.' + ' {Vsubj} then cast the same spell at {name}, who could not' + ' sidestep anything, and was disintegrated immediately. {princess}' + ' stood in silence for a moment, then left the tower without a word.', /* Family 125 (troll, Breigan, princess): armed human throughout, so three losses have no armed-and-able precedent to alias */ '125:SSS': '{name}, {kid} and {princess} charged towards {vname}' + ' together. {vname} began casting a spell, but {princess} reached' + ' the throne first and pushed {vobj} to the floor. What followed' + ' was less of a battle and more of a group activity: the three of' + ' them simply kicked {vname} until {vsubj} stopped moving. {name}' + ' had briefly considered using {posd} {weapon}, but kicking had' + ' felt more appropriate. {vname} was dead, and the website was' + ' restored for good.', '125:FSS': '{name} hobbled towards {vname}, but {kid} and {princess}' + ' had already run ahead. {princess} knocked {vname} to the ground,' + ' and {kid} sat down on {vposd} back to keep {vobj} there. By the' + ' time {name} finally reached the throne, {vname} was already dead.' + ' {Subj} tried not to feel left out. The website was restored for' + ' good.', '125:SFF': '{name} ran towards {vname}, {attacking} {vobj} with' + ' {posd} {weapon}. An epic duel commenced, with {vname} throwing' + ' spells and {name} {attacking} back. Slowly, however, {name} began' + ' to tire. With a flick of {vposd} wrist, {vname} cast a spell on' + ' {name}, disintegrating {obj} immediately.', '125:FSF': '{name} hobbled towards {vname}, {attacking} {vobj} with' + ' {posd} {weapon}, with {kid} running ahead. With a flick of' + ' {vposd} wrist, {vname} cast a spell on {kid}, disintegrating him' + ' immediately. {name} let out a scream and {attacked} {vobj} with' + ' everything {subj} had left. It was not enough. With another flick' + ' of {vposd} wrist, {vname} cast the same spell on {name},' + ' disintegrating {obj} as well.', '125:FFS': '{name} hobbled towards {vname}, {attacking} {vobj} with' + ' {posd} {weapon}, leaning on {princess} for support. With a flick' + ' of {vposd} wrist, {vname} cast a spell at {princess}, who calmly' + ' sidestepped it. {name}, who had been leaning on her, lost {posd}' + ' balance and fell. With another flick of {vposd} wrist, {vname}' + ' cast a spell on {name}, disintegrating {obj} immediately.' + ' {princess} gave {vname} a long, disappointed look, and left the' + ' tower.', /* Family 235 (Breigan, mimic, princess): intact human throughout. The weaponless group kicking needs its own entry (the 125 version mentions the weapon); plus the unarmed one-companion losses */ '235:SFS': '{name}, {kid} and {princess} charged towards {vname}' + ' together. {vname} began casting a spell, but {princess} reached' + ' the throne first and pushed {vobj} to the floor. What followed' + ' was less of a battle and more of a group activity: the three of' + ' them simply kicked {vname} until {vsubj} stopped moving. {vname}' + ' was dead, and the website was restored for good.', '235:SFF': '{name} and {kid} ran towards {vname}, ready to punch' + ' {vobj}. With a flick of {vposd} wrist, {vname} cast a spell on' + ' {kid}, disintegrating him immediately. {name} yelled out towards' + ' him, but there was nothing {subj} could do. With another flick of' + ' {vposd} wrist, {vname} cast the same spell on {name},' + ' disintegrating {obj} as well.', '235:FFS': '{name} ran towards {vname}, ready to punch {vobj}, with' + ' {princess} running beside {obj}. With a flick of {vposd} wrist,' + ' {vname} cast a spell at {princess}, who calmly sidestepped it.' + ' {Vsubj} then cast the same spell at {name}, who tried to sidestep' + ' it the same way {princess} had. {Subj} did not succeed, and was' + ' disintegrated immediately. {princess} pinched the bridge of her' + ' nose, turned around, and left the tower.', /* Family 245 (Breigan, potion, princess): armed and able-bodied throughout — the news are the pig situations */ '245:SFS': '{name}, {kid} and {princess} charged towards {vname}' + ' together. {vname} took a moment too long deciding whether to aim' + ' at the boy, the princess, or the pig with {aweapon} in its mouth.' + ' {princess} used that moment to push {vobj} off the throne, {kid}' + ' pinned {vposd} arms, and {name} {attacked} {vobj}. {vname} was' + ' dead, and the website was restored for good.', '245:SFF': '{kid} ran towards {vname}, with {name} trotting behind,' + ' {posd} {weapon} clenched in {posd} pig mouth. With a flick of' + ' {vposd} wrist, {vname} cast a spell on {kid}, disintegrating him' + ' immediately. {name} let out a devastated squeal and charged. With' + ' another flick of {vposd} wrist, {vname} cast the same spell on' + ' {name}, disintegrating {obj} as well.', '245:FFS': '{name} trotted towards {vname}, {posd} {weapon} clenched' + ' in {posd} pig mouth, with {princess} walking behind. With a flick' + ' of {vposd} wrist, {vname} cast a spell at {princess}, who calmly' + ' sidestepped it. {Vsubj} then cast the same spell at {name}. The' + ' {weapon} clattered to the floor, its owner now a pile of dust.' + ' {princess} picked it up, considered it for a moment, then put it' + ' down again and left the tower.' }; /* Family 234 with a human hero (potion succeeded) is the same fight as the corresponding two-legged 123 ending, reused verbatim */ ENDINGS['234:SSS'] = ENDINGS['123:SSS']; ENDINGS['234:SFS'] = ENDINGS['123:SSF']; ENDINGS['234:FSS'] = ENDINGS['123:SFS']; ENDINGS['234:FFS'] = ENDINGS['123:SFF']; /* Family 124 reuses: humans match 123 (same legs/kid/weapon), pigs with both legs match 234 */ ENDINGS['124:SSS'] = ENDINGS['123:SSS']; ENDINGS['124:SSF'] = ENDINGS['234:SSF']; ENDINGS['124:SFS'] = ENDINGS['123:SFS']; ENDINGS['124:SFF'] = ENDINGS['234:FSF']; ENDINGS['124:FSS'] = ENDINGS['123:FSS']; ENDINGS['124:FFS'] = ENDINGS['123:FFS']; /* Family 134 reuses, matched on state AND outcome */ ENDINGS['134:SSS'] = ENDINGS['123:SFS']; ENDINGS['134:SFF'] = ENDINGS['234:FFF']; ENDINGS['134:FSF'] = ENDINGS['124:FFF']; /* Family 345 reuses: no princess collapses to lone-hero situations */ ENDINGS['345:SSF'] = ENDINGS['123:SFS']; ENDINGS['345:SFF'] = ENDINGS['234:FSF']; ENDINGS['345:FSF'] = ENDINGS['123:SFF']; ENDINGS['345:FFF'] = ENDINGS['234:FFF']; /* Family 125 reuses (letters: troll, Breigan, princess) */ ENDINGS['125:SSF'] = ENDINGS['123:SSS']; ENDINGS['125:SFS'] = ENDINGS['345:SSS']; ENDINGS['125:FFF'] = ENDINGS['123:FFS']; /* Family 245 reuses (letters: Breigan, potion, princess) */ ENDINGS['245:SSS'] = ENDINGS['125:SSS']; ENDINGS['245:SSF'] = ENDINGS['123:SSS']; ENDINGS['245:FSS'] = ENDINGS['345:SSS']; ENDINGS['245:FSF'] = ENDINGS['125:SFF']; ENDINGS['245:FFF'] = ENDINGS['234:FSF']; /* Family 235 reuses (letters: Breigan, mimic, princess) */ ENDINGS['235:SSS'] = ENDINGS['125:SSS']; ENDINGS['235:SSF'] = ENDINGS['123:SSS']; ENDINGS['235:FSS'] = ENDINGS['345:SSS']; ENDINGS['235:FSF'] = ENDINGS['125:SFF']; ENDINGS['235:FFF'] = ENDINGS['123:SFF']; /* Family 135 reuses (letters: troll, mimic, princess) */ ENDINGS['135:SSS'] = ENDINGS['345:SSS']; ENDINGS['135:SSF'] = ENDINGS['123:SFS']; ENDINGS['135:SFS'] = ENDINGS['345:FSS']; ENDINGS['135:SFF'] = ENDINGS['123:SFF']; ENDINGS['135:FSS'] = ENDINGS['145:FSS']; ENDINGS['135:FSF'] = ENDINGS['123:FFS']; ENDINGS['135:FFF'] = ENDINGS['134:FFS']; /* Family 145 reuses (letters: troll, potion, princess) */ ENDINGS['145:SSS'] = ENDINGS['345:SSS']; ENDINGS['145:SSF'] = ENDINGS['123:SFS']; ENDINGS['145:SFS'] = ENDINGS['345:SFS']; ENDINGS['145:SFF'] = ENDINGS['234:FSF']; ENDINGS['145:FSF'] = ENDINGS['123:FFS']; ENDINGS['145:FFF'] = ENDINGS['124:FFF']; /* The encounter pool. ROLLED of these are drawn per hero when the hand is chosen, stored in order in questEncounters; the ENDINGS set signature uses 1-based pool positions. Each entry knows how its save key resolves and what counts as success */ var POOL = ['troll', 'kid', 'mimic', 'potion', 'princess']; var ROLLED = 3; function rollEncounters() { var pool = POOL.slice(); var picked = []; while (picked.length < ROLLED && pool.length) { picked.push(pool.splice(Math.floor(Math.random() * pool.length), 1)[0]); } return picked; } /* The hero. The weapon is an icon glyph dropped into the {w} cell of the art (a fixed 2ch box, so the monospace grid survives). Keys are viewer sides, not hands: the hero faces the viewer */ var ART = { base: ' o\n/|\\\n/ \\', right: ' o\n/|\\_{w}\n/ \\', left: ' o\n{w}_/|\\\n / \\', /* Breigan, age 16, shorter than the hero */ kid: ' o\n/|\\', /* Anastasia. The circumflex is a crown */ princess: ' \u00f4\n/|\\\n/ \\', /* The hero as a pig (potion theft). Still clutches the weapon */ pig: { base: '^..^\n(oo)\n /\\', right: '^..^\n(oo)_{w}\n /\\', left: ' ^..^\n{w}_(oo)\n /\\' } }; /* fa: Font Awesome class; em: Noto Emoji glyph (subsetted into fonts/noto-emoji.woff2 — resubset if the roster changes); attacked/attacking: the combat verbs */ var WEAPONS = { sword: { em: '\uD83D\uDDE1', rot: true, attacked: 'slashed', attacking: 'slashing' }, axe: { em: '\uD83E\uDE93', reversed: true, attacked: 'chopped', attacking: 'chopping' }, wand: { fa: 'fa-wand-sparkles', attacked: 'zapped', attacking: 'zapping' }, gun: { fa: 'fa-gun', attacked: 'shot', attacking: 'shooting' } }; var PRESETS = { she: { subj: 'she', obj: 'her', posd: 'her', refl: 'herself' }, he: { subj: 'he', obj: 'him', posd: 'his', refl: 'himself' }, they: { subj: 'they', obj: 'them', posd: 'their', refl: 'themself' } }; var story = document.getElementById('story'); var pronouns = document.getElementById('pronouns'); var custom = document.getElementById('custom'); var weapon = document.getElementById('weapon'); var hand = document.getElementById('hand'); var vnaming = document.getElementById('vnaming'); var vpronouns = document.getElementById('vpronouns'); function loadKey(key) { try { return localStorage.getItem(key); } catch (e) { return null; } } function saveKey(key, value) { try { localStorage.setItem(key, value); } catch (e) {} } function state() { var pron = null, enc1 = null, vpron = null, order = null; try { pron = JSON.parse(loadKey('questPronouns')); } catch (e) {} try { enc1 = JSON.parse(loadKey('questEnc1')); } catch (e) {} try { vpron = JSON.parse(loadKey('questVillainPronouns')); } catch (e) {} try { order = JSON.parse(loadKey('questEncounters')); } catch (e) {} var weaponKey = loadKey('questWeapon'); return { name: loadKey('questHero'), pron: pron, weapon: WEAPONS[weaponKey] ? weaponKey : null, hand: loadKey('questHand'), /* The rolled encounter ids, in play order */ order: order && order.length ? order : null, /* Set by the mimic eating the weapon: bare fists from then on, {attacked} becomes 'punched' */ weaponLost: loadKey('questWeaponLost') === '1', /* { asked: bool, result: 'attack'|'solved'|'wrong'|null, answer: string (wrong only) } */ enc1: enc1, /* 'yes' (Breigan joins) | 'no' | null */ enc2: loadKey('questEnc2'), /* The kid's name once the rename question is answered ('Breigan' if declined); null while unanswered. He/him either way */ kid: loadKey('questKid'), /* 'pry' (mimic eats the weapon) | 'leave' | null */ enc3: loadKey('questEnc3'), /* 'steal' (hero becomes a pig) | 'explain' | null */ enc4: loadKey('questEnc4'), /* 'decline' | 'agree' (mid-choice) | 'vines' | 'door' | null */ enc5: loadKey('questEnc5'), /* The princess's name once the rename question is answered ('Anastasia' if declined); null while unanswered */ princess: loadKey('questPrincess'), vname: loadKey('questVillain'), vpron: vpron, attacked: loadKey('questAttacked') === '1' }; } function fill(text, vars) { return text.replace(/\{([A-Za-z]+)\}/g, function (token, key) { var value = vars[key.toLowerCase()]; if (value === undefined) return token; if (key[0] !== key[0].toLowerCase()) { value = value.charAt(0).toUpperCase() + value.slice(1); } return value; }); } /* Everything on the page is a function of the save file */ function render() { var s = state(); var vars = { name: s.name, kid: s.kid || 'Breigan', princess: s.princess || 'Anastasia' }; if (s.pron) for (var k in s.pron) vars[k] = s.pron[k]; naming.style.display = s.name ? 'none' : ''; story.style.display = s.name ? '' : 'none'; pronouns.style.display = s.name && !s.pron ? '' : 'none'; weapon.style.display = s.pron && !s.weapon ? '' : 'none'; hand.style.display = s.weapon && !s.hand ? '' : 'none'; if (s.name) { document.getElementById('intro').textContent = fill(TEXT.intro, vars); } var setout = document.getElementById('setout'); setout.style.display = s.pron ? '' : 'none'; if (s.pron) setout.textContent = fill(TEXT.setout, vars); var traverse = document.getElementById('traverse'); var armed = s.weapon && s.hand; traverse.style.display = armed ? '' : 'none'; if (armed) { vars.weapon = s.weapon; /* {aweapon}: article included — 'a sword' but 'an axe' */ vars.aweapon = (/^[aeiou]/.test(s.weapon) ? 'an ' : 'a ') + s.weapon; vars.hand = s.hand; traverse.textContent = fill(TEXT.traverse, vars); } /* The roll: which encounters this hero gets, in which order. Rolled lazily so pre-roll saves pick one up on their next render */ var order = s.order; if (armed && !order) { order = rollEncounters(); saveKey('questEncounters', JSON.stringify(order)); } var resolvedEnc = { troll: !!(s.enc1 && s.enc1.result), kid: s.enc2 === 'no' || (s.enc2 === 'yes' && !!s.kid), mimic: !!s.enc3, potion: !!s.enc4, princess: s.enc5 === 'decline' || s.enc5 === 'vines' || (s.enc5 === 'door' && !!s.princess) }; /* Reorder the story's encounter groups to match the roll, and find the single encounter currently awaiting the player */ var active = null; var arrival = document.getElementById('arrival'); if (armed && order) { for (var oi = 0; oi < order.length; oi++) { var g = document.getElementById( 'grp' + order[oi].charAt(0).toUpperCase() + order[oi].slice(1)); if (g) story.insertBefore(g, arrival); if (active === null && !resolvedEnc[order[oi]]) active = order[oi]; } } function appeared(id) { if (!armed || !order || order.indexOf(id) < 0) return false; return resolvedEnc[id] || id === active; } /* Weapon state as of a given encounter: lost only if the mimic ate it earlier in the order (texts must not change retroactively) */ function armedAt(id) { var i = order ? order.indexOf(id) : -1; for (var j = 0; j < i; j++) { if (order[j] === 'mimic' && s.enc3 === 'pry') return false; } return true; } function combatVars(isArmed) { vars.attacked = isArmed ? WEAPONS[s.weapon].attacked : 'punched'; vars.withweapon = isArmed ? ' with ' + vars.posd + ' ' + s.weapon : ''; } /* The bridge troll's riddle */ var showTroll = appeared('troll'); if (showTroll) combatVars(armedAt('troll')); var enc1 = document.getElementById('enc1'); enc1.style.display = showTroll ? '' : 'none'; if (showTroll) enc1.textContent = fill(TEXT.enc1, vars); document.getElementById('enc1choice').style.display = showTroll && !s.enc1 ? '' : 'none'; var asked = showTroll && s.enc1 && s.enc1.asked; var enc1riddle = document.getElementById('enc1riddle'); enc1riddle.style.display = asked ? '' : 'none'; if (asked) enc1riddle.textContent = fill(TEXT.enc1riddle, vars); document.getElementById('riddle').style.display = asked && !s.enc1.result ? '' : 'none'; var attacked = showTroll && s.enc1 && s.enc1.result === 'attack'; var enc1attack = document.getElementById('enc1attack'); enc1attack.style.display = attacked ? '' : 'none'; if (attacked) enc1attack.textContent = fill(TEXT.enc1attack, vars); var wrong = showTroll && s.enc1 && s.enc1.result === 'wrong'; var enc1wrong = document.getElementById('enc1wrong'); enc1wrong.style.display = wrong ? '' : 'none'; if (wrong) { vars.answer = s.enc1.answer; enc1wrong.textContent = fill(TEXT.enc1wrong, vars); } var solved = showTroll && s.enc1 && s.enc1.result === 'solved'; var enc1correct = document.getElementById('enc1correct'); enc1correct.style.display = solved ? '' : 'none'; if (solved) enc1correct.textContent = fill(TEXT.enc1correct, vars); /* Breigan */ var showKid = appeared('kid'); var enc2 = document.getElementById('enc2'); enc2.style.display = showKid ? '' : 'none'; if (showKid) enc2.textContent = fill(TEXT.enc2, vars); document.getElementById('enc2choice').style.display = showKid && !s.enc2 ? '' : 'none'; var enc2yes = document.getElementById('enc2yes'); var joined = showKid && s.enc2 === 'yes'; enc2yes.style.display = joined ? '' : 'none'; if (joined) enc2yes.textContent = fill(TEXT.enc2yes, vars); var enc2no = document.getElementById('enc2no'); var declined = showKid && s.enc2 === 'no'; enc2no.style.display = declined ? '' : 'none'; if (declined) enc2no.textContent = fill(TEXT.enc2no, vars); /* The rename question holds up the journey until answered */ document.getElementById('rename').style.display = joined && !s.kid ? '' : 'none'; /* The mimic chest */ var showMimic = appeared('mimic'); var enc3 = document.getElementById('enc3'); enc3.style.display = showMimic ? '' : 'none'; if (showMimic) enc3.textContent = fill(TEXT.enc3, vars); var choosing3 = showMimic && !s.enc3; document.getElementById('enc3choice').style.display = choosing3 ? '' : 'none'; if (choosing3) { document.getElementById('pryBtn').textContent = fill(TEXT.enc3pryBtn, vars); } var pried = showMimic && s.enc3 === 'pry'; var enc3pry = document.getElementById('enc3pry'); enc3pry.style.display = pried ? '' : 'none'; if (pried) enc3pry.textContent = fill(TEXT.enc3pry, vars); var left = showMimic && s.enc3 === 'leave'; var enc3leave = document.getElementById('enc3leave'); enc3leave.style.display = left ? '' : 'none'; if (left) enc3leave.textContent = fill(TEXT.enc3leave, vars); /* The potion seller */ var showPotion = appeared('potion'); var enc4 = document.getElementById('enc4'); enc4.style.display = showPotion ? '' : 'none'; if (showPotion) enc4.textContent = fill(TEXT.enc4, vars); document.getElementById('enc4choice').style.display = showPotion && !s.enc4 ? '' : 'none'; var stole = showPotion && s.enc4 === 'steal'; var enc4steal = document.getElementById('enc4steal'); enc4steal.style.display = stole ? '' : 'none'; if (stole) { combatVars(armedAt('potion')); enc4steal.textContent = fill(TEXT.enc4steal, vars); } var explained = showPotion && s.enc4 === 'explain'; var enc4explain = document.getElementById('enc4explain'); enc4explain.style.display = explained ? '' : 'none'; if (explained) enc4explain.textContent = fill(TEXT.enc4explain, vars); /* Breigan's rename line (only when he was actually renamed) */ var kidrename = document.getElementById('kidrename'); var kidRenamed = joined && s.kid && s.kid !== 'Breigan'; kidrename.style.display = kidRenamed ? '' : 'none'; if (kidRenamed) kidrename.textContent = fill(TEXT.kidrename, vars); /* The probable princess */ var showPrincess = appeared('princess'); var enc5 = document.getElementById('enc5'); enc5.style.display = showPrincess ? '' : 'none'; if (showPrincess) enc5.textContent = fill(TEXT.enc5, vars); document.getElementById('enc5choice').style.display = showPrincess && !s.enc5 ? '' : 'none'; var declined5 = showPrincess && s.enc5 === 'decline'; var enc5decline = document.getElementById('enc5decline'); enc5decline.style.display = declined5 ? '' : 'none'; if (declined5) enc5decline.textContent = fill(TEXT.enc5decline, vars); var agreed = showPrincess && (s.enc5 === 'agree' || s.enc5 === 'vines' || s.enc5 === 'door'); var enc5agree = document.getElementById('enc5agree'); enc5agree.style.display = agreed ? '' : 'none'; if (agreed) enc5agree.textContent = fill(TEXT.enc5agree, vars); document.getElementById('enc5method').style.display = showPrincess && s.enc5 === 'agree' ? '' : 'none'; var fell = showPrincess && s.enc5 === 'vines'; var enc5vines = document.getElementById('enc5vines'); enc5vines.style.display = fell ? '' : 'none'; if (fell) enc5vines.textContent = fill(TEXT.enc5vines, vars); var rescued = showPrincess && s.enc5 === 'door'; var enc5door = document.getElementById('enc5door'); enc5door.style.display = rescued ? '' : 'none'; if (rescued) enc5door.textContent = fill(TEXT.enc5door, vars); document.getElementById('prename').style.display = rescued && !s.princess ? '' : 'none'; var princessrename = document.getElementById('princessrename'); var pRenamed = rescued && s.princess && s.princess !== 'Anastasia'; princessrename.style.display = pRenamed ? '' : 'none'; if (pRenamed) princessrename.textContent = fill(TEXT.princessrename, vars); /* The wizard's tower: arrival, villain creation, then the ending */ var encountersDone = armed && order && active === null; arrival.style.display = encountersDone ? '' : 'none'; if (encountersDone) arrival.textContent = fill(TEXT.arrival, vars); vnaming.style.display = encountersDone && !s.vname ? '' : 'none'; vpronouns.style.display = encountersDone && s.vname && !s.vpron ? '' : 'none'; var showdown = encountersDone && s.vname && s.vpron; var confront = document.getElementById('confront'); confront.style.display = showdown ? '' : 'none'; if (showdown) { vars.vname = s.vname; for (var vk in s.vpron) vars['v' + vk] = s.vpron[vk]; /* Showdown-time forms: unlike the troll fight, the ending happens after any weapon loss, so here punched/bare-handed applies */ vars.attacked = s.weaponLost ? 'punched' : WEAPONS[s.weapon].attacked; vars.attacking = s.weaponLost ? 'punching' : WEAPONS[s.weapon].attacking; vars.withweapon = s.weaponLost ? '' : ' with ' + vars.posd + ' ' + s.weapon; confront.textContent = fill(TEXT.confront, vars); } document.getElementById('showdownAttack').style.display = showdown && !s.attacked ? '' : 'none'; var ending = document.getElementById('ending'); var endingText = ''; var won = false; if (showdown && s.attacked) { /* The situation key: chosen encounters in pool order (1-based positions), then their outcomes in the same order */ var successOf = { troll: s.enc1 && s.enc1.result === 'solved', kid: s.enc2 === 'yes', mimic: s.enc3 === 'leave', potion: s.enc4 === 'explain', princess: s.enc5 === 'door' }; var chosen = order.slice().sort(function (a, b) { return POOL.indexOf(a) - POOL.indexOf(b); }); var sig = '', letters = '', successes = 0; chosen.forEach(function (id) { sig += POOL.indexOf(id) + 1; letters += successOf[id] ? 'S' : 'F'; successes += successOf[id] ? 1 : 0; }); won = successes >= 2; endingText = ENDINGS[sig + ':' + letters] || ''; } ending.style.display = endingText ? '' : 'none'; if (endingText) ending.textContent = fill(endingText, vars); document.getElementById('endWin').style.display = showdown && s.attacked && won ? '' : 'none'; /* Restart is offered after every ending — losses need it, wins may want another go */ document.getElementById('endRestart').style.display = showdown && s.attacked ? '' : 'none'; var figure = document.getElementById('figure'); /* The hero faces the viewer: their left hand is on the viewer's right, so the art side is the opposite of the handedness */ var side = s.hand === 'left' ? 'right' : 'left'; /* The potion theft turned the hero into a pig (weapon still in trotter) */ var isPig = s.enc4 === 'steal'; var artSet = isPig ? ART.pig : ART; var hero; if (armed && !s.weaponLost) { var w = WEAPONS[s.weapon]; /* Mirror so the weapon faces away from the body; 'reversed' marks glyphs whose natural facing is opposite the FA convention */ var mirrored = side === 'left'; if (w.reversed) mirrored = !mirrored; var flip = mirrored ? ' wpn-flip' : ''; var icon = w.fa ? '' : '' + w.em + ''; icon = '' + icon + ''; hero = artSet[side].replace('{w}', icon); } else { hero = artSet.base; } /* The troll took a leg (in combat or as a quiz penalty) */ if (armed && (attacked || wrong)) { hero = hero.replace(isPig ? '/\\' : '/ \\', '/'); } /* Companions line up on the hero's free side, away from the weapon — and stay there even if the weapon is later lost */ var figs = ['' + hero + '']; function addCompanion(art) { var span = '' + art + ''; if (side === 'right') figs.unshift(span); else figs.push(span); } if (joined) addCompanion(ART.kid); if (rescued) addCompanion(ART.princess); figure.innerHTML = figs.join(''); } naming.addEventListener('submit', function (e) { e.preventDefault(); var name = document.getElementById('heroName').value.trim(); if (!name) return; saveKey('questHero', name); render(); }); /* Hero and villain share the pronoun-picker wiring; ids differ by prefix */ function wirePronouns(form, customTable, customBtn, prefix, storageKey) { form.addEventListener('click', function (e) { var preset = e.target.getAttribute && e.target.getAttribute('data-preset'); if (!preset) return; saveKey(storageKey, JSON.stringify(PRESETS[preset])); render(); }); customBtn.addEventListener('click', function () { customTable.style.display = customTable.style.display ? '' : 'none'; }); form.addEventListener('submit', function (e) { e.preventDefault(); var pron = { subj: document.getElementById(prefix + 'Subj').value.trim(), obj: document.getElementById(prefix + 'Obj').value.trim(), posd: document.getElementById(prefix + 'Posd').value.trim(), refl: document.getElementById(prefix + 'Refl').value.trim() }; for (var k in pron) if (!pron[k]) return; saveKey(storageKey, JSON.stringify(pron)); render(); }); } wirePronouns(pronouns, custom, document.getElementById('customBtn'), 'pn', 'questPronouns'); wirePronouns(vpronouns, document.getElementById('vcustom'), document.getElementById('vcustomBtn'), 'vpn', 'questVillainPronouns'); vnaming.addEventListener('submit', function (e) { e.preventDefault(); var name = document.getElementById('villainName').value.trim(); if (!name) return; saveKey('questVillain', name); render(); }); document.getElementById('showdownAttack').addEventListener('click', function (e) { if (e.target.tagName !== 'BUTTON') return; saveKey('questAttacked', '1'); render(); }); /* A restart or a completed quest wipes the whole save file, hero included — a fresh run starts at "Name your hero" */ function clearRun() { try { ['questHero', 'questPronouns', 'questWeapon', 'questHand', 'questEncounters', 'questEnc1', 'questEnc2', 'questKid', 'questEnc3', 'questEnc4', 'questEnc5', 'questPrincess', 'questWeaponLost', 'questVillain', 'questVillainPronouns', 'questAttacked' ].forEach(function (k) { localStorage.removeItem(k); }); } catch (err) {} } /* Winning genuinely restores gade.gg: same keys the 404's restore hatch clears, then home — where the guard no longer redirects */ document.getElementById('endWin').addEventListener('click', function (e) { if (e.target.tagName !== 'BUTTON') return; /* Permanent — survives the save wipe and the restore. The achievements system on the main page reads it, so the Adventurer toast greets the return home */ saveKey('questWon', '1'); clearRun(); try { localStorage.removeItem('siteDeleted'); localStorage.removeItem('siteDeletedViews'); localStorage.removeItem('questStarted'); } catch (err) {} location.href = '/'; }); document.getElementById('endRestart').addEventListener('click', function (e) { if (e.target.tagName !== 'BUTTON') return; clearRun(); render(); }); weapon.addEventListener('click', function (e) { var chosen = e.target.getAttribute && e.target.getAttribute('data-weapon'); if (!chosen) return; saveKey('questWeapon', chosen); render(); }); hand.addEventListener('click', function (e) { var chosen = e.target.getAttribute && e.target.getAttribute('data-hand'); if (!chosen) return; saveKey('questHand', chosen); render(); }); document.getElementById('enc1choice').addEventListener('click', function (e) { var act = e.target.getAttribute && e.target.getAttribute('data-act'); if (!act) return; saveKey('questEnc1', JSON.stringify(act === 'attack' ? { asked: false, result: 'attack' } : { asked: true, result: null })); render(); }); document.getElementById('riddle').addEventListener('submit', function (e) { e.preventDefault(); var raw = document.getElementById('riddleAnswer').value.trim(); if (!raw) return; var answer = raw.toLowerCase(); var enc1 = answer === 'a river' || answer === 'river' || answer === 'water' ? { asked: true, result: 'solved' } : { asked: true, result: 'wrong', answer: raw }; saveKey('questEnc1', JSON.stringify(enc1)); render(); }); document.getElementById('riddleAttack').addEventListener('click', function () { saveKey('questEnc1', JSON.stringify({ asked: true, result: 'attack' })); render(); }); document.getElementById('enc2choice').addEventListener('click', function (e) { var ans = e.target.getAttribute && e.target.getAttribute('data-ans'); if (!ans) return; saveKey('questEnc2', ans); render(); }); /* Breigan and Anastasia share the rename wiring */ function wireRename(divId, formId, inputId, storageKey, defaultName) { var form = document.getElementById(formId); document.getElementById(divId).addEventListener('click', function (e) { var ans = e.target.getAttribute && e.target.getAttribute('data-rename'); if (!ans) return; if (ans === 'no') { saveKey(storageKey, defaultName); render(); } else { form.style.display = ''; } }); form.addEventListener('submit', function (e) { e.preventDefault(); var name = document.getElementById(inputId).value.trim(); if (!name) return; saveKey(storageKey, name); render(); }); } wireRename('rename', 'renameForm', 'kidName', 'questKid', 'Breigan'); wireRename('prename', 'prenameForm', 'princessName', 'questPrincess', 'Anastasia'); document.getElementById('enc3choice').addEventListener('click', function (e) { var act = e.target.getAttribute && e.target.getAttribute('data-act'); if (!act) return; saveKey('questEnc3', act); if (act === 'pry') saveKey('questWeaponLost', '1'); render(); }); document.getElementById('enc4choice').addEventListener('click', function (e) { var act = e.target.getAttribute && e.target.getAttribute('data-act'); if (!act) return; saveKey('questEnc4', act); render(); }); document.getElementById('enc5choice').addEventListener('click', function (e) { var act = e.target.getAttribute && e.target.getAttribute('data-act'); if (!act) return; saveKey('questEnc5', act); render(); }); document.getElementById('enc5method').addEventListener('click', function (e) { var act = e.target.getAttribute && e.target.getAttribute('data-act'); if (!act) return; saveKey('questEnc5', act); render(); }); render(); })();