crunch
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

814 Zeilen
23 KiB

  1. let world = null;
  2. let currentRoom = null;
  3. let currentDialog = null;
  4. let currentFoe = null;
  5. let dirButtons = [];
  6. let actionButtons = [];
  7. let mode = "explore";
  8. let actions = [];
  9. let time = 9*60*60;
  10. let date = 1;
  11. let newline = " ";
  12. let player = new Player();
  13. let playerAttacks = [];
  14. let struggles = [];
  15. let killingBlow = null;
  16. let deaths = [];
  17. let respawnRoom;
  18. let noLog = false;
  19. let MIDNIGHT = 0;
  20. let MORNING = 21600;
  21. let NOON = 43200;
  22. let EVENING = 64800;
  23. function toggleLog() {
  24. noLog = !noLog;
  25. if (noLog) {
  26. document.getElementById("log-button").innerHTML = "Log: Disabled";
  27. } else {
  28. document.getElementById("log-button").innerHTML = "Log: Enabled";
  29. }
  30. }
  31. function join(things) {
  32. if (things.length == 1) {
  33. return things[0].description("a");
  34. } else if (things.length == 2) {
  35. return things[0].description("a") + " and " + things[1].description("a");
  36. } else {
  37. let line = "";
  38. line = things.slice(0,-1).reduce((line, prey) => line + prey.description("a") + ", ", line);
  39. line += " and " + things[things.length-1].description("a");
  40. return line;
  41. }
  42. }
  43. function pickRandom(list) {
  44. return list[Math.floor(Math.random() * list.length)];
  45. }
  46. function pick(list, attacker, defender) {
  47. if (list.length == 0)
  48. return null;
  49. else {
  50. let sum = list.reduce((sum, choice) => choice.weight == undefined ? sum + 1 : sum + choice.weight(attacker, defender), 0);
  51. let target = Math.random() * sum;
  52. for (let i = 0; i < list.length; i++) {
  53. sum -= list[i].weight == undefined ? 1 : list[i].weight(attacker, defender);
  54. if (sum <= target) {
  55. return list[i];
  56. }
  57. }
  58. return list[list.length-1];
  59. }
  60. }
  61. function filterValid(options, attacker, defender) {
  62. let filtered = options.filter(option => option.conditions == undefined || option.conditions.reduce((result, test) => result && test(attacker, defender), true));
  63. return filtered.filter(option => option.requirements == undefined || option.requirements.reduce((result, test) => result && test(attacker, defender), true));
  64. }
  65. function filterPriority(options) {
  66. let max = options.reduce((max, option) => option.priority > max ? option.priority : max, -1000);
  67. return options.filter(option => option.priority == max);
  68. }
  69. function round(number, digits) {
  70. return Math.round(number * Math.pow(10,digits)) / Math.pow(10,digits);
  71. }
  72. function updateExploreCompass() {
  73. for (let i = 0; i < dirButtons.length; i++) {
  74. let button = dirButtons[i];
  75. button.classList.remove("active-button");
  76. button.classList.remove("inactive-button");
  77. button.classList.remove("disabled-button");
  78. if (currentRoom.exits[i] == null) {
  79. button.disabled = true;
  80. button.classList.add("inactive-button");
  81. button.innerHTML = "";
  82. } else {
  83. if (currentRoom.exits[i].conditions.reduce((result, test) => result && test(player.prefs), true)) {
  84. button.disabled = false;
  85. button.classList.add("active-button");
  86. button.innerHTML = currentRoom.exits[i].name;
  87. } else {
  88. button.disabled = true;
  89. button.classList.add("disabled-button");
  90. button.innerHTML = currentRoom.exits[i].name;
  91. }
  92. }
  93. }
  94. }
  95. function updateExploreActions() {
  96. for (let i = 0; i < actionButtons.length; i++) {
  97. if (i < actions.length) {
  98. actionButtons[i].disabled = false;
  99. actionButtons[i].innerHTML = actions[i].name;
  100. actionButtons[i].classList.remove("inactive-button");
  101. actionButtons[i].classList.add("active-button");
  102. }
  103. else {
  104. actionButtons[i].disabled = true;
  105. actionButtons[i].innerHTML = "";
  106. actionButtons[i].classList.remove("active-button");
  107. actionButtons[i].classList.add("inactive-button");
  108. }
  109. }
  110. }
  111. function updateExplore() {
  112. updateExploreCompass();
  113. updateExploreActions();
  114. }
  115. function updateEaten() {
  116. let list = document.getElementById("eaten");
  117. while(list.firstChild) {
  118. list.removeChild(list.firstChild);
  119. }
  120. if (player.health > 0)
  121. struggles = filterValid(currentFoe.struggles, currentFoe, player);
  122. else
  123. struggles = [submit(currentFoe)];
  124. for (let i = 0; i < struggles.length; i++) {
  125. let li = document.createElement("li");
  126. let button = document.createElement("button");
  127. button.classList.add("eaten-button");
  128. button.innerHTML = struggles[i].name;
  129. button.addEventListener("click", function() { struggleClicked(i); } );
  130. button.addEventListener("mouseover", function() { struggleHovered(i); } );
  131. button.addEventListener("mouseout", function() { document.getElementById("eaten-desc").innerHTML = ""; } );
  132. li.appendChild(button);
  133. list.appendChild(li);
  134. }
  135. }
  136. function updateCombat() {
  137. let list = document.getElementById("combat");
  138. while(list.firstChild) {
  139. list.removeChild(list.firstChild);
  140. }
  141. if (player.health > 0)
  142. if (currentFoe.playerAttacks == undefined)
  143. playerAttacks = filterValid(player.attacks, player, currentFoe);
  144. else
  145. playerAttacks = filterValid(currentFoe.playerAttacks.map(attack => attack(player)), player, currentFoe);
  146. else
  147. playerAttacks = [pass(player)];
  148. if (playerAttacks.length == 0)
  149. playerAttacks = [player.backupAttack];
  150. for (let i = 0; i < playerAttacks.length; i++) {
  151. let li = document.createElement("li");
  152. let button = document.createElement("button");
  153. button.classList.add("combat-button");
  154. button.innerHTML = playerAttacks[i].name;
  155. button.addEventListener("click", function() { attackClicked(i); } );
  156. button.addEventListener("mouseover", function() { attackHovered(i); } );
  157. button.addEventListener("mouseout", function() { document.getElementById("combat-desc").innerHTML = ""; } );
  158. li.appendChild(button);
  159. list.appendChild(li);
  160. }
  161. document.getElementById("stat-foe-name").innerHTML = "Name: " + currentFoe.name;
  162. document.getElementById("stat-foe-health").innerHTML = "Health: " + currentFoe.health + "/" + currentFoe.maxHealth;
  163. document.getElementById("stat-foe-stamina").innerHTML = "Stamina: " + currentFoe.stamina + "/" + currentFoe.maxStamina;
  164. document.getElementById("stat-foe-str").innerHTML = "Str: " + currentFoe.str;
  165. document.getElementById("stat-foe-dex").innerHTML = "Dex: " + currentFoe.dex;
  166. document.getElementById("stat-foe-con").innerHTML = "Con: " + currentFoe.con;
  167. }
  168. function updateDialog() {
  169. let list = document.getElementById("dialog");
  170. while(list.firstChild) {
  171. list.removeChild(list.firstChild);
  172. }
  173. for (let i = 0; i < currentDialog.choices.length; i++) {
  174. let activated = currentDialog.choices[i].node.requirements == undefined || currentDialog.choices[i].node.requirements.reduce((result, test) => result && test(player, currentFoe), true);
  175. let li = document.createElement("li");
  176. let button = document.createElement("button");
  177. button.classList.add("dialog-button");
  178. button.innerHTML = currentDialog.choices[i].text;
  179. button.addEventListener("click", function() { dialogClicked(i); });
  180. if (!activated) {
  181. button.classList.add("disabled-button");
  182. button.disabled = true;
  183. }
  184. li.appendChild(button);
  185. list.appendChild(li);
  186. }
  187. }
  188. function updateDisplay() {
  189. document.querySelectorAll(".selector").forEach(function (x) {
  190. x.style.display = "none";
  191. });
  192. switch(mode) {
  193. case "explore":
  194. document.getElementById("selector-explore").style.display = "flex";
  195. updateExplore();
  196. break;
  197. case "combat":
  198. document.getElementById("selector-combat").style.display = "flex";
  199. updateCombat();
  200. break;
  201. case "dialog":
  202. document.getElementById("selector-dialog").style.display = "flex";
  203. updateDialog();
  204. break;
  205. case "eaten":
  206. document.getElementById("selector-eaten").style.display = "flex";
  207. updateEaten();
  208. break;
  209. }
  210. document.getElementById("time").innerHTML = "Time: " + renderTime(time);
  211. document.getElementById("date").innerHTML = "Day " + date;
  212. document.getElementById("stat-name").innerHTML = "Name: " + player.name;
  213. document.getElementById("stat-health").innerHTML = "Health: " + round(player.health,0) + "/" + round(player.maxHealth,0);
  214. document.getElementById("stat-cash").innerHTML = "Cash: $" + round(player.cash,0);
  215. document.getElementById("stat-stamina").innerHTML = "Stamina: " + round(player.stamina,0) + "/" + round(player.maxStamina,0);
  216. document.getElementById("stat-str").innerHTML = "Str: " + player.str;
  217. document.getElementById("stat-dex").innerHTML = "Dex: " + player.dex;
  218. document.getElementById("stat-con").innerHTML = "Con: " + player.con;
  219. document.getElementById("stat-fullness").innerHTML = "Fullness: " + round(player.fullness(),0);
  220. if (player.prefs.scat) {
  221. document.getElementById("stat-bowels").innerHTML = "Bowels: " + round(player.bowels.fullness,0);
  222. } else {
  223. document.getElementById("stat-bowels").innerHTML = "";
  224. }
  225. }
  226. function advanceTimeTo(newTime) {
  227. advanceTime((86400 + newTime - time) % 86400);
  228. }
  229. function advanceTime(amount) {
  230. time = (time + amount);
  231. date += Math.floor(time / 86400);
  232. time = time % 86400;
  233. player.restoreHealth(amount);
  234. player.restoreStamina(amount);
  235. update(player.stomach.digest(amount));
  236. update(player.butt.digest(amount));
  237. update(player.balls.digest(amount));
  238. }
  239. function renderTime(time) {
  240. let suffix = (time < 43200) ? "AM" : "PM";
  241. let hour = Math.floor((time % 43200) / 3600);
  242. if (hour == 0)
  243. hour = 12;
  244. let minute = Math.floor(time / 60) % 60;
  245. if (minute < 9)
  246. minute = "0" + minute;
  247. return hour + ":" + minute + " " + suffix;
  248. }
  249. function move(direction) {
  250. if (noLog)
  251. clearScreen();
  252. let target = currentRoom.exits[direction];
  253. if (target == null) {
  254. alert("Tried to move to an empty room!");
  255. return;
  256. }
  257. moveTo(target,currentRoom.exitDescs[direction]);
  258. }
  259. function moveToByName(roomName, desc="You go places lol", loading=false) {
  260. moveTo(world[roomName], desc, loading);
  261. }
  262. function moveTo(room,desc="You go places lol", loading=false) {
  263. actions = [];
  264. currentRoom = room;
  265. if (!loading)
  266. advanceTime(30);
  267. currentRoom.objects.forEach(function (object) {
  268. object.actions.forEach(function (action) {
  269. if (action.conditions == undefined || action.conditions.reduce((result, cond) => result && cond(player.prefs), true))
  270. actions.push(action);
  271. });
  272. });
  273. update([desc,newline]);
  274. currentRoom.visit();
  275. }
  276. window.addEventListener('load', function(event) {
  277. document.getElementById("start-button").addEventListener("click", start, false);
  278. });
  279. function start() {
  280. applySettings(generateSettings());
  281. transformVorePrefs(player.prefs);
  282. document.getElementById("create").style.display = "none";
  283. document.getElementById("game").style.display = "block";
  284. document.getElementById("stat-button-status").addEventListener("click", status, false);
  285. document.getElementById("log-button").addEventListener("click", toggleLog, false);
  286. loadActions();
  287. loadCompass();
  288. loadDialog();
  289. world = createWorld();
  290. currentRoom = world["Bedroom"];
  291. respawnRoom = currentRoom;
  292. moveTo(currentRoom,"");
  293. updateDisplay();
  294. }
  295. // copied from Stroll LUL
  296. function generateSettings() {
  297. let form = document.forms.namedItem("character-form");
  298. let settings = {};
  299. for (let i=0; i<form.length; i++) {
  300. let value = form[i].value == "" ? form[i].placeholder : form[i].value;
  301. if (form[i].type == "text")
  302. if (form[i].value == "")
  303. settings[form[i].name] = form[i].placeholder;
  304. else
  305. settings[form[i].name] = value;
  306. else if (form[i].type == "number")
  307. settings[form[i].name] = parseFloat(value);
  308. else if (form[i].type == "checkbox") {
  309. settings[form[i].name] = form[i].checked;
  310. } else if (form[i].type == "radio") {
  311. let name = form[i].name;
  312. if (form[i].checked)
  313. settings[name] = form[i].value;
  314. } else if (form[i].type == "select-one") {
  315. settings[form[i].name] = form[i][form[i].selectedIndex].value;
  316. }
  317. }
  318. return settings;
  319. }
  320. function applySettings(settings) {
  321. player.name = settings.name;
  322. player.species = settings.species;
  323. for (let key in settings) {
  324. if (settings.hasOwnProperty(key)) {
  325. if (key.match(/prefs/)) {
  326. let tokens = key.split("-");
  327. let pref = player.prefs;
  328. pref = tokens.slice(1,-1).reduce(function(pref, key) {
  329. if (pref[key] == undefined)
  330. pref[key] = {};
  331. return pref[key];
  332. }, pref);
  333. pref[tokens.slice(-1)[0]] = settings[key];
  334. }
  335. }
  336. }
  337. }
  338. // turn things like "1" into a number
  339. function transformVorePrefs(prefs) {
  340. for (let key in prefs.vore) {
  341. if (prefs.vore.hasOwnProperty(key)) {
  342. switch(prefs.vore[key]) {
  343. case "0": prefs.vore[key] = 0; break;
  344. case "1": prefs.vore[key] = 0.5; break;
  345. case "2": prefs.vore[key] = 1; break;
  346. case "3": prefs.vore[key] = 2; break;
  347. }
  348. }
  349. }
  350. return prefs;
  351. }
  352. function saveSettings() {
  353. window.localStorage.setItem("settings", JSON.stringify(generateSettings()));
  354. }
  355. function retrieveSettings() {
  356. return JSON.parse(window.localStorage.getItem("settings"));
  357. }
  358. function clearScreen() {
  359. let log = document.getElementById("log");
  360. let child = log.firstChild;
  361. while (child != null) {
  362. log.removeChild(child);
  363. child = log.firstChild;
  364. }
  365. }
  366. function update(lines=[]) {
  367. let log = document.getElementById("log");
  368. for (let i=0; i<lines.length; i++) {
  369. let div = document.createElement("div");
  370. div.innerHTML = lines[i];
  371. log.appendChild(div);
  372. }
  373. log.scrollTop = log.scrollHeight;
  374. updateDisplay();
  375. }
  376. function changeMode(newMode) {
  377. mode = newMode;
  378. let body = document.querySelector("body");
  379. document.getElementById("foe-stats").style.display = "none";
  380. body.className = "";
  381. switch(mode) {
  382. case "explore":
  383. case "dialog":
  384. body.classList.add("explore");
  385. break;
  386. case "combat":
  387. body.classList.add("combat");
  388. document.getElementById("foe-stats").style.display = "block";
  389. break;
  390. case "eaten":
  391. body.classList.add("eaten");
  392. document.getElementById("foe-stats").style.display = "block";
  393. break;
  394. }
  395. updateDisplay();
  396. }
  397. // make it look like eaten mode, even when in combat
  398. function changeBackground(newMode) {
  399. let body = document.querySelector("body");
  400. document.getElementById("foe-stats").style.display = "none";
  401. body.className = "";
  402. switch(newMode) {
  403. case "explore":
  404. case "dialog":
  405. body.classList.add("explore");
  406. break;
  407. case "combat":
  408. body.classList.add("combat");
  409. document.getElementById("foe-stats").style.display = "block";
  410. break;
  411. case "eaten":
  412. body.classList.add("eaten");
  413. document.getElementById("foe-stats").style.display = "block";
  414. break;
  415. }
  416. }
  417. function respawn(respawnRoom) {
  418. if (killingBlow.gameover == undefined) {
  419. if (player.prefs.prey) {
  420. deaths.push("Digested by " + currentFoe.description("a") + " at " + renderTime(time) + " on day " + date);
  421. } else {
  422. deaths.push("Defeated by " + currentFoe.description("a") + " at " + renderTime(time) + " on day " + date);
  423. }
  424. } else {
  425. deaths.push(killingBlow.gameover() + " at " + renderTime(time) + " on day " + date);
  426. }
  427. moveTo(respawnRoom,"You drift through space and time...");
  428. player.clear();
  429. player.stomach.contents = [];
  430. player.butt.contents = [];
  431. player.bowels.contents = [];
  432. player.bowels.fullness = 0;
  433. advanceTime(Math.floor(86400 / 2 * (Math.random() * 0.5 - 0.25 + 1)));
  434. changeMode("explore");
  435. player.health = 100;
  436. update(["You wake back up in your bed."]);
  437. }
  438. function startCombat(opponent) {
  439. currentFoe = opponent;
  440. changeMode("combat");
  441. update(opponent.startCombat(player).concat([newline]));
  442. }
  443. function attackClicked(index) {
  444. if (noLog)
  445. clearScreen();
  446. update(playerAttacks[index].attack(currentFoe).concat([newline]));
  447. if (currentFoe.health <= 0) {
  448. currentFoe.defeated();
  449. } else if (mode == "combat") {
  450. let attack = pick(filterPriority(filterValid(currentFoe.attacks, currentFoe, player)), currentFoe, player);
  451. if (attack == null) {
  452. attack = currentFoe.backupAttack;
  453. }
  454. update(attack.attackPlayer(player).concat([newline]));
  455. if (player.health <= -100) {
  456. killingBlow = attack;
  457. if (currentFoe.finishCombat != undefined)
  458. update(currentFoe.finishCombat().concat([newline]));
  459. update(["You die..."]);
  460. respawn(respawnRoom);
  461. } else if (player.health <= 0) {
  462. update(["You're too weak to do anything..."]);
  463. if (player.prefs.prey) {
  464. // nada
  465. } else {
  466. killingBlow = attack;
  467. update(["You die..."]);
  468. respawn(respawnRoom);
  469. }
  470. }
  471. if (currentFoe.status != undefined) {
  472. let status = currentFoe.status();
  473. if (status.length > 0)
  474. update(status.concat([newline]));
  475. }
  476. }
  477. }
  478. function attackHovered(index) {
  479. document.getElementById("combat-desc").innerHTML = playerAttacks[index].desc;
  480. }
  481. function struggleClicked(index) {
  482. if (noLog)
  483. clearScreen();
  484. let struggle = struggles[index];
  485. let result = struggle.struggle(player);
  486. update(result.lines.concat([newline]));
  487. if (result.escape == "stay") {
  488. changeMode("combat");
  489. } else if (result.escape == "escape") {
  490. changeMode("explore");
  491. } else {
  492. let digest = pick(filterValid(currentFoe.digests, currentFoe, player), currentFoe, player);
  493. if (digest == null) {
  494. digest = currentFoe.backupDigest;
  495. }
  496. update(digest.digest(player).concat([newline]));
  497. if (player.health <= -100) {
  498. killingBlow = digest;
  499. update(currentFoe.finishDigest().concat([newline]));
  500. respawn(respawnRoom);
  501. }
  502. }
  503. }
  504. function struggleHovered(index) {
  505. document.getElementById("eaten-desc").innerHTML = currentFoe.struggles[index].desc;
  506. }
  507. function startDialog(dialog) {
  508. if (noLog)
  509. clearScreen();
  510. currentDialog = dialog;
  511. changeMode("dialog");
  512. update(currentDialog.text.concat([newline]));
  513. currentDialog.visit();
  514. updateDisplay();
  515. }
  516. function dialogClicked(index) {
  517. currentDialog = currentDialog.choices[index].node;
  518. update(currentDialog.text.concat([newline]));
  519. currentDialog.visit();
  520. if (currentDialog.choices.length == 0 && mode == "dialog") {
  521. changeMode("explore");
  522. updateDisplay();
  523. }
  524. }
  525. function loadDialog() {
  526. dialogButtons = Array.from( document.querySelectorAll(".dialog-button"));
  527. for (let i = 0; i < dialogButtons.length; i++) {
  528. dialogButtons[i].addEventListener("click", function() { dialogClicked(i); });
  529. }
  530. }
  531. function actionClicked(index) {
  532. actions[index].action();
  533. }
  534. function loadActions() {
  535. actionButtons = Array.from( document.querySelectorAll(".action-button"));
  536. for (let i = 0; i < actionButtons.length; i++) {
  537. actionButtons[i].addEventListener("click", function() { actionClicked(i); });
  538. }
  539. }
  540. function loadCompass() {
  541. dirButtons[NORTH_WEST] = document.getElementById("compass-north-west");
  542. dirButtons[NORTH_WEST].addEventListener("click", function() {
  543. move(NORTH_WEST);
  544. });
  545. dirButtons[NORTH] = document.getElementById("compass-north");
  546. dirButtons[NORTH].addEventListener("click", function() {
  547. move(NORTH);
  548. });
  549. dirButtons[NORTH_EAST] = document.getElementById("compass-north-east");
  550. dirButtons[NORTH_EAST].addEventListener("click", function() {
  551. move(NORTH_EAST);
  552. });
  553. dirButtons[WEST] = document.getElementById("compass-west");
  554. dirButtons[WEST].addEventListener("click", function() {
  555. move(WEST);
  556. });
  557. dirButtons[EAST] = document.getElementById("compass-east");
  558. dirButtons[EAST].addEventListener("click", function() {
  559. move(EAST);
  560. });
  561. dirButtons[SOUTH_WEST] = document.getElementById("compass-south-west");
  562. dirButtons[SOUTH_WEST].addEventListener("click", function() {
  563. move(SOUTH_WEST);
  564. });
  565. dirButtons[SOUTH] = document.getElementById("compass-south");
  566. dirButtons[SOUTH].addEventListener("click", function() {
  567. move(SOUTH);
  568. });
  569. dirButtons[SOUTH_EAST] = document.getElementById("compass-south-east");
  570. dirButtons[SOUTH_EAST].addEventListener("click", function() {
  571. move(SOUTH_EAST);
  572. });
  573. document.getElementById("compass-look").addEventListener("click", look, false);
  574. }
  575. function look() {
  576. update([currentRoom.description]);
  577. }
  578. function status() {
  579. let lines = [];
  580. lines.push("You are a " + player.species);
  581. lines.push(newline);
  582. if (player.stomach.contents.length > 0) {
  583. lines.push("Your stomach bulges with prey.");
  584. player.stomach.contents.map(function(prey) {
  585. let state = "";
  586. let healthRatio = prey.health / prey.maxHealth;
  587. if (healthRatio > 0.75) {
  588. state = "is thrashing in your gut";
  589. } else if (healthRatio > 0.5) {
  590. state = "is squirming in your belly";
  591. } else if (healthRatio > 0.25) {
  592. state = "is pressing out at your stomach walls";
  593. } else if (healthRatio > 0) {
  594. state = "is weakly squirming";
  595. } else {
  596. state = "has stopped moving";
  597. }
  598. lines.push(prey.description("A") + " " + state);
  599. });
  600. lines.push(newline);
  601. }
  602. if (player.butt.contents.length > 0) {
  603. lines.push("Your bowels churn with prey.");
  604. player.butt.contents.map(function(prey) {
  605. let state = "";
  606. let healthRatio = prey.health / prey.maxHealth;
  607. if (healthRatio > 0.75) {
  608. state = "is writhing in your bowels";
  609. } else if (healthRatio > 0.5) {
  610. state = "is struggling against your intestines";
  611. } else if (healthRatio > 0.25) {
  612. state = "is bulging out of your lower belly";
  613. } else if (healthRatio > 0) {
  614. state = "is squirming weakly, slipping deeper and deeper";
  615. } else {
  616. state = "has succumbed to your bowels";
  617. }
  618. lines.push(prey.description("A") + " " + state);
  619. });
  620. lines.push(newline);
  621. }
  622. update(lines);
  623. }
  624. let toSave = ["str","dex","con","name","species","health","stamina"];
  625. function saveGame() {
  626. let save = {};
  627. save.player = JSON.stringify(player, function(key, value) {
  628. if (toSave.includes(key) || key == "") {
  629. return value;
  630. } else {
  631. return undefined;
  632. }
  633. });
  634. save.prefs = JSON.stringify(player.prefs);
  635. save.position = currentRoom.name;
  636. save.date = date;
  637. save.time = time;
  638. save.deaths = deaths;
  639. let stringified = JSON.stringify(save);
  640. window.localStorage.setItem("save", stringified);
  641. }
  642. function loadGame() {
  643. changeMode("explore");
  644. let save = JSON.parse(window.localStorage.getItem("save"));
  645. let playerSave = JSON.parse(save.player);
  646. for (let key in playerSave) {
  647. if (playerSave.hasOwnProperty(key)) {
  648. player[key] = playerSave[key];
  649. }
  650. }
  651. player.prefs = JSON.parse(save.prefs);
  652. deaths = save.deaths;
  653. date = save.date;
  654. time = save.time;
  655. clearScreen();
  656. moveToByName(save.position, "");
  657. }
  658. // wow polyfills
  659. if (![].includes) {
  660. Array.prototype.includes = function(searchElement /*, fromIndex*/ ) {
  661. 'use strict';
  662. var O = Object(this);
  663. var len = parseInt(O.length) || 0;
  664. if (len === 0) {
  665. return false;
  666. }
  667. var n = parseInt(arguments[1]) || 0;
  668. var k;
  669. if (n >= 0) {
  670. k = n;
  671. } else {
  672. k = len + n;
  673. if (k < 0) {k = 0;}
  674. }
  675. var currentElement;
  676. while (k < len) {
  677. currentElement = O[k];
  678. if (searchElement === currentElement ||
  679. (searchElement !== searchElement && currentElement !== currentElement)) {
  680. return true;
  681. }
  682. k++;
  683. }
  684. return false;
  685. };
  686. }