summaryrefslogtreecommitdiff
path: root/2026/games/liquidcake1/index.html
diff options
context:
space:
mode:
Diffstat (limited to '2026/games/liquidcake1/index.html')
-rw-r--r--2026/games/liquidcake1/index.html415
1 files changed, 0 insertions, 415 deletions
diff --git a/2026/games/liquidcake1/index.html b/2026/games/liquidcake1/index.html
deleted file mode 100644
index 8bff36c..0000000
--- a/2026/games/liquidcake1/index.html
+++ /dev/null
@@ -1,415 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="UTF-8">
- <script language="javascript" type="module">
- import { Interpreter } from "./interpreter.mjs";
- let interpreter = new Interpreter();
- interpreter.add_handler("char_out", out);
- interpreter.add_handler("error_occurred", oute);
- interpreter.add_handler("cell_changed", handle_set_cell);
- interpreter.add_handler("output_field", console.log);
- interpreter.add_handler("thread_created", setup_thread_gui);
- interpreter.add_handler("thread_paused", handle_thread_paused);
- interpreter.add_handler("thread_state_updated", update_thread_state);
- interpreter.add_handler("thread_state_synced", handle_thread_state_synced);
- interpreter.add_handler("terminate", handle_thread_state_synced);
- interpreter.add_handler("thread_dead", handle_thread_dead);
- interpreter.max_loops = 1000;
- window.befunge_interpreter = interpreter;
- var start_time;
- var end_time;
- var difficulty;
- async function handle_message(ev) {
- console.log("handle_message", ev);
- console.log("handle_message", ev.data);
- console.log("handle_message", ev.data.op);
- if (ev.data.op == "start") {
- winner = loser = false;
- console.log("Picking level");
- await pick_level();
- set_speed();
- console.log("Picked level; explaining started.");
- window.parent.postMessage({op: "started", verb: "catch!"});
- difficulty = ev.data.difficulty;
- let timeout;
- if (difficulty < 10) {
- timeout = 150000 / (10 + difficulty);
- } else {
- timeout = 5000 + 150000 / difficulty;
- }
- console.log("Starting... with difficulty ", difficulty, "which is", timeout);
- start_time = new Date().getTime();
- end_time = start_time + timeout;
- check_time();
- go();
- let code = document.getElementById("code");
- code.style.animation = "none";
- window.setTimeout(function () {
- code.style.animation = "";
- }, 10);
- console.log("Started.");
- }
- }
- function check_time() {
- if (winner) {
- console.log("Check time: winner");
- return;
- }
- let now = new Date().getTime();
- let fraction_done = (now - start_time) / (end_time - start_time);
- let bomb = document.getElementById("bomb");
- if (fraction_done > 1) {
- console.log("Check time: loser");
- loser = true;
- bomb.innerText = "💥";
- interpreter.pause();
- return;
- }
- let ticks = 10 - Math.ceil(fraction_done * 10);
- bomb.innerText = "💣" + ".".repeat(ticks) + "💥";
- window.setTimeout(check_time, 50);
-
- }
- async function load() {
- document.getElementById("speed").addEventListener("input", set_speed);
- document.addEventListener("mousemove", function (e) {
- let follower = document.getElementById("follower");
- follower.style.left = e.pageX + "px";
- follower.style.top = e.pageY + "px";
- });
- set_speed();
- window.addEventListener("message", handle_message);
- window.parent.postMessage({op: "ready"});
- }
- let levels = [
- '"!dlrow ,olleH",,,,,,,,,,,,,@',
- '"H","e","l","l","o",","," "v\n @,"!","d","l","r","o","w",<',
- '0>:2g:,"!"v\n ^_@#\\+1\\-<\nHello, world!',
- ];
- let current_level;
- let removed;
- let placed_row = -1;
- let placed_col = -1;
- function test_level(content) {
- let test_int = new Interpreter();
- let out = "";
- let fulfil;
- let test_stopping = false;
- test_int.add_handler("char_out", function (c) { out += c; });
- test_int.add_handler("thread_paused", function () { if (test_stopping) return; test_stopping = true; test_int.stop(); });
- test_int.add_handler("thread_dead", function (thread) { console.log("dead!"); fulfil([out, thread.tick_count]); });
- test_int.max_loops = 10000;
- test_int.set_speed(100)
- let lines = content.split("\n");
- let width = 0;
- for(let i=0; i<lines.length; i++) {
- if (lines[i].length > width) {
- width = lines[i].length;
- }
- }
- for(let i=0; i<lines.length; i++) {
- test_int.field.push([]);
- for(let j=0; j<width; j++) {
- if (j < lines[i].length) {
- test_int.field[i].push(lines[i].charCodeAt(j))
- } else {
- test_int.field[i].push(32);
- }
- }
- }
- let p = new Promise(function(f) { fulfil = f; test_int.go(); });
- return p;
- }
- function ticks_to_speed(ticks) {
- let speed = Math.log(ticks / 100) / Math.log(1.1);
- if (ticks < 100) {
- speed -= 20;
- }
- return speed;
- }
- async function pick_level() {
- let level_idx = Math.floor(Math.random() * levels.length);
- const base_level = levels[level_idx];
- let base_res = await test_level(base_level);
- if (base_res[0] == "Hello, world!") {
- console.log("Pre-edit validated!");
- } else {
- console.log("Ooops!");
- }
- let tries = 0;
- while(tries < 100) {
- tries += 1;
- let idx = Math.floor(Math.random() * base_level.length);
- removed = base_level[idx];
- if (removed == "\n") {
- continue;
- }
- let replace;
- if (difficulty < 10) {
- replace = " ";
- } else {
- replace = String.fromCharCode(Math.floor(Math.random() * 94) + 33);
- }
- current_level = base_level.slice(0, idx) + replace + base_level.slice(idx + 1);
- console.log(idx);
- let current_res = await test_level(current_level);
- if (current_res[0] == "Hello, world!") {
- console.log("Ooops! Try again!");
- } else {
- console.log("Post-edit validated!");
- document.getElementById("to_place").innerText = removed;
- document.getElementById("follower_cell").innerText = removed;
- let ticks = current_res[1];
- if (ticks > base_res[1] * 2) { ticks = base_res[1] * 2; }
- document.getElementById("speed").value = ticks_to_speed(ticks);
- if (interpreter.instructions_raw.hasOwnProperty(removed)) {
- document.getElementById("place_description").innerText = interpreter.instructions_raw[removed].desc;
- } else {
- document.getElementById("place_description").innerText = "not an instruction";
-
- }
- console.log("level picked!");
- return;
- }
- }
- }
- function set_speed(e) {
- let raw_speed = document.getElementById("speed").value;
- interpreter.set_speed(raw_speed);
- }
- function setup_thread_gui(thread) {
- const this_thread = thread;
- let thb = document.createElement("th");
- let table = document.createElement("table");
- let tr = document.createElement("tr");
- let th = document.createElement("th");
- tr.appendChild(thb);
- tr.appendChild(th);
- table.appendChild(tr);
- let thread_info = document.createElement("p");
- thread_info.appendChild(table);
- document.getElementById("threads").appendChild(thread_info);
- thread.info_elt = thread_info;
- }
- function update_thread_state(thread) {
- let tr = thread.info_elt.children[0].children[0];
- tr.children[1].innerText = `(${("" + thread.col).padStart(3, "\u00a0")},${("" + thread.row).padStart(3, "\u00a0")})`;
- while(tr.children.length > thread.stack.length + 2) {
- tr.removeChild(tr.children[tr.children.length - 1]);
- }
- while(tr.children.length < thread.stack.length + 2) {
- tr.appendChild(document.createElement("td"));
- }
- thread.stack.forEach(function (val, idx) {
- if (val > 32 && val < 127) {
- val = String.fromCharCode(val);
- }
- tr.children[thread.stack.length - idx + 1].innerText = val;
- });
- }
- let winner = false;
- let loser = false;
- let just_placed = false;
- async function go() {
- if (winner || loser) {
- if (winner) {
- console.log("We are winner!");
- } else {
- console.log("We are loser!");
- }
- window.parent.postMessage({op: "done", win: winner});
- document.getElementById("out").classList.remove("right");
- placed_col = placed_row = -1;
- placed_td = undefined;
- let table = document.getElementById("table");
- while(table.children.length > 0) {
- table.removeChild(table.children[table.children.length-1]);
- interpreter.field.pop();
- }
- document.getElementById("out").innerText = "";
- return;
- }
- if (document.getElementById("out").innerText == "Hello, world!") {
- // WIN!
- winner = true;
- document.getElementById("out").classList.add("right");
- placed_td.classList.add("right");
- placed_td.classList.remove("wrong");
- //console.log(dead_thread_ticks, ticks_to_speed(dead_thread_ticks / 10));
- interpreter.set_speed(ticks_to_speed(dead_thread_ticks / 5));
- } else if (just_placed) {
- // Run once, super fast. We'll get back here immediately.
- interpreter.set_speed(100);
- just_placed = false;
- load_level(current_level);
- document.getElementById("out").innerText = "";
- interpreter.go();
- return;
- } else {
- set_speed();
- }
- document.getElementById("outlast").innerHTML = document.getElementById("out").innerHTML;
- document.getElementById("out").innerText = "";
- load_level(current_level);
- interpreter.go();
- }
- function set_cell(col, row, val) {
- interpreter.set_cell(col, row, val);
- }
- function handle_set_cell(col, row, val) {
- let val_str = String.fromCharCode(val);
- document.getElementById("table").children[row].children[col].innerText = val_str == " " ? "\u00a0" : val_str;
- let title = `(${col},${row})=${val} (${val_str})`;
- if (interpreter.instructions_raw[val_str] !== undefined)
- title += ": " + interpreter.instructions_raw[val_str].desc;
- document.getElementById("table").children[row].children[col].title = title;
- }
- function out(s) {
- document.getElementById("out").appendChild(document.createTextNode(s));
- }
- function oute(s) {
- if (s == "ERROR: Normal termination!" || s.startsWith("State was: ")) {
- return;
- }
- let span = document.createElement("p");
- span.className = "error";
- span.innerText = s;
- document.getElementById("out").appendChild(span);
- }
- let highlighted_cells = [];
- function handle_thread_state_synced(threads) {
- threads ||= [];
- let new_highlighted_cells = threads.map(thread => document.getElementById("table").children[thread.row].children[thread.col]);
- highlighted_cells.filter(x => !new_highlighted_cells.includes(x)).forEach(
- cell => cell.classList.remove("active"));
- highlighted_cells = new_highlighted_cells;
- highlighted_cells.forEach(cell => cell.classList.add("active"));
- }
- let stopping;
- function handle_thread_paused(paused_thread) {
- if (stopping) {
- // We'll unpause and then pause again...
- return;
- }
- stopping = true;
- interpreter.stop();
- }
- let dead_thread_ticks;
- function handle_thread_dead(dead_thread) {
- dead_thread_ticks = dead_thread.tick_count;
- stopping = false;
- document.getElementById("threads").removeChild(dead_thread.info_elt);
- go();
- }
- let placed_td;
- function click_cell(col, row, td) {
- if (winner) {
- return;
- }
- placed_col = col;
- placed_row = row;
- if (placed_td) {
- placed_td.classList.remove("wrong");
- }
- placed_td = td;
- td.classList.add("wrong");
- set_cell(placed_col, placed_row, removed.charCodeAt(0));
- just_placed = true;
- interpreter.pause();
- }
- function load_level(content) {
- const lines = content.split("\n");
- const height = lines.length;
- let width = 0;
- for(let i=0; i<height; i++) {
- if (lines[i].length > width) {
- width = lines[i].length;
- }
- }
- let table = document.getElementById("table");
- while(table.children.length > height) {
- table.removeChild(table.children[table.children.length-1]);
- interpreter.field.pop();
- }
- while(table.children.length < height) {
- table.appendChild(document.createElement("tr"));
- interpreter.field.push([]);
- }
- for(let i=0; i<height; i++) {
- let line;
- if (i >= lines.length)
- line = "";
- else
- line = lines[i];
- let row = table.children[i];
- while(row.children.length > width) {
- row.removeChild(row.children[row.children.length-1]);
- interpreter.field[i].pop();
- }
- while(row.children.length < width) {
- const td = document.createElement("td");
- const rown = i;
- const coln = row.children.length;
- td.addEventListener("click", function() { click_cell(coln, rown, td); });
- row.appendChild(td);
- interpreter.field[i].push(32);
- }
- for(let j=0; j<width; j++) {
- let val;
- if (j >= line.length)
- val = " ";
- else
- val = line[j];
- if (j == placed_col && i == placed_row) {
- val = removed;
- }
- set_cell(j, i, val.charCodeAt(0));
- }
- }
- }
- window.addEventListener("load", load);
- </script>
-<style>
-body { font-size: 4vh; }
-table { border: black solid 1px; padding: 0px; }
-th { font-family: monospace; font-weight: normal; }
-td { font-family: monospace; background: lightgrey; width: 1em; padding: 0px; text-align: center; }
-.out1 > p { display: inline-block; margin-top: 0; margin-bottom: 0; min-height: 1em; }
-.out1 > div { font-family: monospace; border: black solid 1px; display: inline-block; white-space-collapse: preserve; }
-.out1 > p:empty::before {
- content: "";
- display: inline-block;
-}
-.error { background-color: red; margin: 0px; }
-.active { background-color: lightpink; }
-.wrong { background-color: orange; }
-.right { background-color: green; }
-.follower { position: absolute; transform: translate(-50%, -50%); pointer-events: none; }
-body { cursor: none; }
-#threads { border: black solid 1px; padding: 0px; min-height: 2em;}
-#threads > p { margin: 0px; }
-@keyframes fadeOut {
- from { opacity: 1; }
- to { opacity: 0; }
-}
-
-#code { position: absolute; font-weight: bold; font-size: 50vh; pointer-events: none; animation: fadeOut 2s ease-out forwards; background: white; pointer-events: none; }
-</style>
- <title>Befunge</title>
- </head>
- <body>
- <div id="code">Code!</div>
- <div style="display: inline-block;"><big>Placing:</big></div><table style="display: inline-block;"><tr><td id="to_place"></td><th>Which does: <div id="place_description" style="display: inline-block;"></div></th></tr></table>
- <div style="display: inline-block;">Speed <input type="range" min="-100" max="150" value="40" id="speed" style="height: 1em;"/></div>
- <br/>
- <div id="threads"></div>
- <table id="table">
- </table>
- <div class="out1"><p>Output:</p><div id="out"></div></div>
- <div class="out1"><p>Previous:</p><div id="outlast"></div></div>
- <div class="out1"><p>Target:</p><div>Hello, world!</div></div>
- <div id="follower" class="follower"><table><tr><td id="follower_cell">x</td></tr></table></div>
- <div>Don't get exploded: <code id="bomb">💣......💥</code></div>
- </body>
-</html>