summaryrefslogtreecommitdiff
path: root/2026/games_submissions/gbjk
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2026-08-18 00:08:28 -0400
committerLLLL Colonq <llll@colonq>2026-08-18 00:08:28 -0400
commit32a62cfcb925225359a5c90761b795f2f737ebd2 (patch)
tree95c2261964803b19f2d39cb35d8d514ed6e5a6f4 /2026/games_submissions/gbjk
parentde99c5f7636a952025ea13de02bafd25bcb6bdec (diff)
Re-populate games
Diffstat (limited to '2026/games_submissions/gbjk')
-rw-r--r--2026/games_submissions/gbjk/LICENSE21
-rw-r--r--2026/games_submissions/gbjk/index.html456
-rw-r--r--2026/games_submissions/gbjk/src/.gitignore24
-rw-r--r--2026/games_submissions/gbjk/src/index.html12
-rw-r--r--2026/games_submissions/gbjk/src/package.json16
-rw-r--r--2026/games_submissions/gbjk/src/pnpm-lock.yaml568
-rw-r--r--2026/games_submissions/gbjk/src/src/main.ts33
-rw-r--r--2026/games_submissions/gbjk/src/src/setup.ts389
-rw-r--r--2026/games_submissions/gbjk/src/src/style.css103
-rw-r--r--2026/games_submissions/gbjk/src/tsconfig.json23
-rw-r--r--2026/games_submissions/gbjk/src/vite.config.ts9
11 files changed, 0 insertions, 1654 deletions
diff --git a/2026/games_submissions/gbjk/LICENSE b/2026/games_submissions/gbjk/LICENSE
deleted file mode 100644
index 14fac91..0000000
--- a/2026/games_submissions/gbjk/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2026
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/2026/games_submissions/gbjk/index.html b/2026/games_submissions/gbjk/index.html
deleted file mode 100644
index 0e43bab..0000000
--- a/2026/games_submissions/gbjk/index.html
+++ /dev/null
@@ -1,456 +0,0 @@
-<!doctype html>
-<html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>tortis</title>
- <script type="module" crossorigin>//#region \0vite/modulepreload-polyfill.js
-(function polyfill() {
- const relList = document.createElement("link").relList;
- if (relList && relList.supports && relList.supports("modulepreload")) return;
- for (const link of document.querySelectorAll("link[rel=\"modulepreload\"]")) processPreload(link);
- new MutationObserver((mutations) => {
- for (const mutation of mutations) {
- if (mutation.type !== "childList") continue;
- for (const node of mutation.addedNodes) if (node.tagName === "LINK" && node.rel === "modulepreload") processPreload(node);
- }
- }).observe(document, {
- childList: true,
- subtree: true
- });
- function getFetchOpts(link) {
- const fetchOpts = {};
- if (link.integrity) fetchOpts.integrity = link.integrity;
- if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy;
- if (link.crossOrigin === "use-credentials") fetchOpts.credentials = "include";
- else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit";
- else fetchOpts.credentials = "same-origin";
- return fetchOpts;
- }
- function processPreload(link) {
- if (link.ep) return;
- link.ep = true;
- const fetchOpts = getFetchOpts(link);
- fetch(link.href, fetchOpts);
- }
-})();
-//#endregion
-//#region src/setup.ts
-var WIDTH = 160;
-var HEIGHT = 240;
-var GRID_HEIGHT = HEIGHT - 10;
-var ROWS = 15;
-var COLS = 10;
-var GRID_WIDTH = GRID_HEIGHT / ROWS * 10;
-var GRID_X = 5;
-var GRID_Y = 5;
-var MARGIN = 2;
-var CELL_WIDTH = GRID_HEIGHT / ROWS - MARGIN;
-var FALLTIME = 600;
-var MIN_FALLTIME = 300;
-var rotation = 0;
-var board = [];
-function resetBoard() {
- board.length = 0;
- for (let height = 0; height < ROWS; height++) {
- const row = [];
- for (let width = 0; width < COLS; width++) row.push("void");
- board.push(row);
- }
-}
-resetBoard();
-function random(elements) {
- return elements[Math.floor(Math.random() * elements.length)];
-}
-var addedShapeNumber = 1;
-function addSquares() {
- const color = random([
- "fallingRed",
- "fallingGreen",
- "fallingBlue"
- ]);
- let w = COLS / 2;
- let h = 1;
- for (let i = 0; i < 4; i++) {
- board[h][w] = color;
- if (i === 3) break;
- let move = null;
- let j = 0;
- for (; j < 20; j++) {
- move = addedShapeNumber % 6 === 0 ? "down" : random([
- "up",
- "down",
- "left",
- "right"
- ]);
- if (move === "up" && (h === 0 || board[h - 1][w] !== "void")) continue;
- if (move === "down" && (h === ROWS - 1 || board[h + 1][w] !== "void")) continue;
- if (move === "left" && (w === 0 || board[h][w - 1] !== "void")) continue;
- if (move === "right" && (w === COLS - 1 || board[h][w + 1] !== "void")) continue;
- break;
- }
- if (j === 20) return false;
- switch (move) {
- case "up":
- h--;
- break;
- case "down":
- h++;
- break;
- case "left":
- w--;
- break;
- case "right":
- w++;
- break;
- }
- }
- addedShapeNumber++;
- return true;
-}
-function clearFilledRows() {
- let lastClearedRow = ROWS;
- let clearedRows = 0;
- for (let row = ROWS - 1; row >= 0; row--) if (!board[row].some((cell) => cell === "void" || cell === "fallingBlue" || cell === "fallingGreen" || cell === "fallingRed")) {
- for (let col = 0; col < COLS; col++) board[row][col] = "void";
- lastClearedRow = row;
- clearedRows++;
- } else if (lastClearedRow !== ROWS) for (let col = 0; col < COLS; col++) switch (board[row][col]) {
- case "red":
- board[row][col] = "fallingRed";
- break;
- case "green":
- board[row][col] = "fallingGreen";
- break;
- case "blue":
- board[row][col] = "fallingBlue";
- break;
- }
- return clearedRows;
-}
-function setup(elements) {
- const ctx = elements.main.getContext("2d");
- let gameRunning = false;
- let animationFrameId = null;
- let lastFrame = 0;
- let fallTime = FALLTIME;
- let speedUpPressed = false;
- elements.left.addEventListener("click", () => moveFalling("left"));
- elements.right.addEventListener("click", () => moveFalling("right"));
- elements.rotateLeft.addEventListener("click", () => {
- if (!gameRunning) return;
- rotation -= 30 * Math.random();
- elements.main.style.transform = `rotate(${rotation}deg)`;
- });
- elements.rotateRight.addEventListener("click", () => {
- if (!gameRunning) return;
- rotation += 30 * Math.random();
- elements.main.style.transform = `rotate(${rotation}deg)`;
- });
- elements.speedUp.addEventListener("mousedown", () => speedUpPressed = gameRunning);
- elements.speedUp.addEventListener("mouseup", () => speedUpPressed = false);
- window.addEventListener("message", (ev) => {
- const message = ev.data;
- if (!isStartMessage(message)) return;
- startGame(message.difficulty);
- });
- window.parent.postMessage({ op: "ready" }, "*");
- draw();
- function isStartMessage(message) {
- if (typeof message !== "object" || message === null) return false;
- const candidate = message;
- return candidate.op === "start" && typeof candidate.difficulty === "number" && Number.isFinite(candidate.difficulty);
- }
- function resetGame(difficulty) {
- resetBoard();
- addedShapeNumber = 1;
- fallTime = Math.max(MIN_FALLTIME, FALLTIME - Math.max(0, difficulty) * 5);
- rotation = 0;
- elements.main.style.transform = "";
- speedUpPressed = false;
- lastFrame = 0;
- }
- function startGame(difficulty) {
- if (animationFrameId !== null) {
- cancelAnimationFrame(animationFrameId);
- animationFrameId = null;
- }
- resetGame(difficulty);
- gameRunning = true;
- window.parent.postMessage({
- op: "started",
- verb: "catch!"
- }, "*");
- animationFrameId = requestAnimationFrame(gameLoop);
- }
- function finishGame(win) {
- if (!gameRunning) return;
- gameRunning = false;
- if (animationFrameId !== null) {
- cancelAnimationFrame(animationFrameId);
- animationFrameId = null;
- }
- window.parent.postMessage({
- op: "done",
- win
- }, "*");
- resetGame(0);
- draw();
- }
- function moveFalling(move) {
- if (!gameRunning) return;
- switch (move) {
- case "left":
- for (let row = 0; row < ROWS; row++) for (let col = 0; col < COLS - 1; col++) if (board[row][col] === "void") switch (board[row][col + 1]) {
- case "fallingRed":
- case "fallingGreen":
- case "fallingBlue":
- board[row][col] = board[row][col + 1];
- board[row][col + 1] = "void";
- }
- break;
- case "right":
- for (let row = 0; row < ROWS; row++) for (let col = COLS - 1; col > 0; col--) if (board[row][col] === "void") switch (board[row][col - 1]) {
- case "fallingRed":
- case "fallingGreen":
- case "fallingBlue":
- board[row][col] = board[row][col - 1];
- board[row][col - 1] = "void";
- }
- break;
- }
- }
- function physics() {
- let somethingFell = false;
- for (let row = ROWS - 1; row >= 1; row--) for (let col = 0; col < COLS; col++) {
- let space = board[row][col];
- let above = board[row - 1][col];
- switch (above) {
- case "fallingRed":
- case "fallingGreen":
- case "fallingBlue": if (space === "void") {
- somethingFell = true;
- board[row][col] = board[row - 1][col];
- board[row - 1][col] = "void";
- } else switch (above) {
- case "fallingRed":
- board[row - 1][col] = "red";
- break;
- case "fallingGreen":
- board[row - 1][col] = "green";
- break;
- case "fallingBlue":
- board[row - 1][col] = "blue";
- break;
- }
- }
- }
- for (let col = 0; col < COLS; col++) switch (board[ROWS - 1][col]) {
- case "fallingRed":
- board[ROWS - 1][col] = "red";
- break;
- case "fallingGreen":
- board[ROWS - 1][col] = "green";
- break;
- case "fallingBlue":
- board[ROWS - 1][col] = "blue";
- break;
- }
- return somethingFell;
- }
- function draw() {
- ctx.clearRect(0, 0, WIDTH, HEIGHT);
- ctx.fillStyle = "black";
- ctx.fillRect(GRID_X, GRID_Y, GRID_WIDTH, GRID_HEIGHT);
- for (let h = 0; h < ROWS; h++) for (let w = 0; w < COLS; w++) {
- switch (board[h][w]) {
- case "void":
- ctx.fillStyle = "#2e2e2e";
- break;
- case "red":
- ctx.fillStyle = "#994444";
- break;
- case "green":
- ctx.fillStyle = "#449944";
- break;
- case "blue":
- ctx.fillStyle = "#444499";
- break;
- case "fallingRed":
- ctx.fillStyle = "#bb3333";
- break;
- case "fallingGreen":
- ctx.fillStyle = "#33bb33";
- break;
- case "fallingBlue":
- ctx.fillStyle = "#3333bb";
- break;
- }
- const x = 8 + w * CELL_WIDTH + (w - 1) * MARGIN;
- const y = 8 + h * CELL_WIDTH + (h - 1) * MARGIN;
- ctx.fillRect(x, y, CELL_WIDTH, CELL_WIDTH);
- }
- }
- function gameLoop(time) {
- animationFrameId = null;
- if (!gameRunning) return;
- if (time - lastFrame > (speedUpPressed ? fallTime / 10 : fallTime)) {
- lastFrame = time;
- if (!physics()) {
- const clearedRows = clearFilledRows();
- if (clearedRows >= 4) {
- finishGame(true);
- return;
- } else if (clearedRows === 0) {
- if (!addSquares()) {
- finishGame(false);
- return;
- }
- }
- }
- }
- draw();
- animationFrameId = requestAnimationFrame(gameLoop);
- }
-}
-//#endregion
-//#region src/main.ts
-document.querySelector("#app").innerHTML = `
- <div class="layout">
-
- <div class="game">
- <div class="title-bar">
- <h1>Tortis</h1>
- <p>(4row clear to win)</p>
- </div>
-
- <canvas height="240" width="160" id="main"></canvas>
- </div>
-
- <ul>
- <button id="move-left">move left</button>
- <button id="rotate-left">rotate left</button>
- <button id="move-right">move right</button>
- <button id="rotate-right">rotate right</button>
- <button id="speed-up">speed up</button>
- </ul>
- </div>
-`;
-setup({
- main: document.querySelector("#main"),
- left: document.querySelector("#move-left"),
- right: document.querySelector("#move-right"),
- rotateLeft: document.querySelector("#rotate-left"),
- rotateRight: document.querySelector("#rotate-right"),
- speedUp: document.querySelector("#speed-up")
-});
-//#endregion</script>
- <style rel="stylesheet" crossorigin>* {
- box-sizing: border-box;
-}
-
-html,
-body,
-#app {
- min-height: 100%;
-}
-
-body {
- margin: 0;
- color: darksalmon;
- background-color: #2e2e2e;
- font-family: monospace;
- overflow-x: hidden;
-}
-
-button {
- min-width: 0;
- font: inherit;
- font-size: .4rem;
- line-height: 1.1;
- padding: .15rem;
- color: darksalmon;
- background-color: #2e2e2e;
- border-color: salmon;
- cursor: pointer;
- white-space: normal;
- overflow-wrap: anywhere;
-
- z-index: 9999;
-}
-
-button:hover {
- background-color: darkslategray;
-}
-
-button:active {
- background-color: slategray;
-}
-
-.layout {
- margin: auto;
- display: flex;
- min-height: 100dvh;
- width: 100%;
- padding: .15rem;
- gap: .2rem;
- align-items: center;
- justify-content: center;
- overflow: hidden;
-}
-
-.game {
- min-width: 0;
-}
-
-.title-bar {
- display: flex;
- align-items: baseline;
- gap: .25rem;
- margin-bottom: .2rem;
-}
-
-h1,
-p {
- margin: 0;
-}
-
-h1 {
- font-size: .6rem;
- line-height: 1;
-}
-
-p {
- font-size: .4rem;
- line-height: 1.1;
-}
-
-canvas {
- display: block;
- aspect-ratio: 2 / 3;
- border-radius: 6px;
- border: 1px solid darksalmon;
- box-shadow: 0px 0px 4px darksalmon;
- height: 80vmin;
- width: auto;
-
- transition: transform 100ms;
- margin: auto;
-}
-
-ul {
- display: flex;
- justify-content: center;
- flex-direction: column;
- gap: .15rem;
- width: min(6rem, 42vw);
- margin: 0;
- padding: 0;
- list-style: none;
-}
-/*$vite$:1*/</style>
- </head>
- <body>
- <div id="app"></div>
- </body>
-</html>
diff --git a/2026/games_submissions/gbjk/src/.gitignore b/2026/games_submissions/gbjk/src/.gitignore
deleted file mode 100644
index a547bf3..0000000
--- a/2026/games_submissions/gbjk/src/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
diff --git a/2026/games_submissions/gbjk/src/index.html b/2026/games_submissions/gbjk/src/index.html
deleted file mode 100644
index c68a552..0000000
--- a/2026/games_submissions/gbjk/src/index.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!doctype html>
-<html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>tortis</title>
- </head>
- <body>
- <div id="app"></div>
- <script type="module" src="/src/main.ts"></script>
- </body>
-</html>
diff --git a/2026/games_submissions/gbjk/src/package.json b/2026/games_submissions/gbjk/src/package.json
deleted file mode 100644
index a5e9656..0000000
--- a/2026/games_submissions/gbjk/src/package.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "name": "tortis",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "tsc && vite build",
- "preview": "vite preview"
- },
- "devDependencies": {
- "typescript": "6.0.2",
- "vite": "8.0.12",
- "vite-plugin-singlefile": "2.3.3"
- }
-}
diff --git a/2026/games_submissions/gbjk/src/pnpm-lock.yaml b/2026/games_submissions/gbjk/src/pnpm-lock.yaml
deleted file mode 100644
index 1087420..0000000
--- a/2026/games_submissions/gbjk/src/pnpm-lock.yaml
+++ /dev/null
@@ -1,568 +0,0 @@
-lockfileVersion: '9.0'
-
-settings:
- autoInstallPeers: true
- excludeLinksFromLockfile: false
-
-importers:
-
- .:
- devDependencies:
- typescript:
- specifier: ~6.0.2
- version: 6.0.3
- vite:
- specifier: ^8.0.12
- version: 8.0.16
- vite-plugin-singlefile:
- specifier: ^2.3.3
- version: 2.3.3(vite@8.0.16)
-
-packages:
-
- '@emnapi/core@1.10.0':
- resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
-
- '@emnapi/runtime@1.10.0':
- resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
-
- '@emnapi/wasi-threads@1.2.1':
- resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
-
- '@napi-rs/wasm-runtime@1.1.5':
- resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==}
- peerDependencies:
- '@emnapi/core': ^1.7.1
- '@emnapi/runtime': ^1.7.1
-
- '@oxc-project/types@0.133.0':
- resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==}
-
- '@rolldown/binding-android-arm64@1.0.3':
- resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm64]
- os: [android]
-
- '@rolldown/binding-darwin-arm64@1.0.3':
- resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm64]
- os: [darwin]
-
- '@rolldown/binding-darwin-x64@1.0.3':
- resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [x64]
- os: [darwin]
-
- '@rolldown/binding-freebsd-x64@1.0.3':
- resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [x64]
- os: [freebsd]
-
- '@rolldown/binding-linux-arm-gnueabihf@1.0.3':
- resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm]
- os: [linux]
-
- '@rolldown/binding-linux-arm64-gnu@1.0.3':
- resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm64]
- os: [linux]
- libc: [glibc]
-
- '@rolldown/binding-linux-arm64-musl@1.0.3':
- resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm64]
- os: [linux]
- libc: [musl]
-
- '@rolldown/binding-linux-ppc64-gnu@1.0.3':
- resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [ppc64]
- os: [linux]
- libc: [glibc]
-
- '@rolldown/binding-linux-s390x-gnu@1.0.3':
- resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [s390x]
- os: [linux]
- libc: [glibc]
-
- '@rolldown/binding-linux-x64-gnu@1.0.3':
- resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [x64]
- os: [linux]
- libc: [glibc]
-
- '@rolldown/binding-linux-x64-musl@1.0.3':
- resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [x64]
- os: [linux]
- libc: [musl]
-
- '@rolldown/binding-openharmony-arm64@1.0.3':
- resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm64]
- os: [openharmony]
-
- '@rolldown/binding-wasm32-wasi@1.0.3':
- resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [wasm32]
-
- '@rolldown/binding-win32-arm64-msvc@1.0.3':
- resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [arm64]
- os: [win32]
-
- '@rolldown/binding-win32-x64-msvc@1.0.3':
- resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==}
- engines: {node: ^20.19.0 || >=22.12.0}
- cpu: [x64]
- os: [win32]
-
- '@rolldown/pluginutils@1.0.1':
- resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
-
- '@tybys/wasm-util@0.10.2':
- resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==}
-
- braces@3.0.3:
- resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
- engines: {node: '>=8'}
-
- detect-libc@2.1.2:
- resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
- engines: {node: '>=8'}
-
- fdir@6.5.0:
- resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
- engines: {node: '>=12.0.0'}
- peerDependencies:
- picomatch: ^3 || ^4
- peerDependenciesMeta:
- picomatch:
- optional: true
-
- fill-range@7.1.1:
- resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
- engines: {node: '>=8'}
-
- fsevents@2.3.3:
- resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
- engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
- os: [darwin]
-
- is-number@7.0.0:
- resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
- engines: {node: '>=0.12.0'}
-
- lightningcss-android-arm64@1.32.0:
- resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [android]
-
- lightningcss-darwin-arm64@1.32.0:
- resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [darwin]
-
- lightningcss-darwin-x64@1.32.0:
- resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [darwin]
-
- lightningcss-freebsd-x64@1.32.0:
- resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [freebsd]
-
- lightningcss-linux-arm-gnueabihf@1.32.0:
- resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm]
- os: [linux]
-
- lightningcss-linux-arm64-gnu@1.32.0:
- resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [linux]
- libc: [glibc]
-
- lightningcss-linux-arm64-musl@1.32.0:
- resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [linux]
- libc: [musl]
-
- lightningcss-linux-x64-gnu@1.32.0:
- resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [linux]
- libc: [glibc]
-
- lightningcss-linux-x64-musl@1.32.0:
- resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [linux]
- libc: [musl]
-
- lightningcss-win32-arm64-msvc@1.32.0:
- resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [win32]
-
- lightningcss-win32-x64-msvc@1.32.0:
- resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [win32]
-
- lightningcss@1.32.0:
- resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
- engines: {node: '>= 12.0.0'}
-
- micromatch@4.0.8:
- resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
- engines: {node: '>=8.6'}
-
- nanoid@3.3.13:
- resolution: {integrity: sha512-sPdqC6ByMVVGvF1ynvvMo0/o+oD1VX7DaHhijt1bFgjvBkHBib4t49GoNDhf2NDta4oeUNlaGbSt5K7qjZ955Q==}
- engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
- hasBin: true
-
- picocolors@1.1.1:
- resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
-
- picomatch@2.3.2:
- resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==}
- engines: {node: '>=8.6'}
-
- picomatch@4.0.4:
- resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
- engines: {node: '>=12'}
-
- postcss@8.5.15:
- resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
- engines: {node: ^10 || ^12 || >=14}
-
- rolldown@1.0.3:
- resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==}
- engines: {node: ^20.19.0 || >=22.12.0}
- hasBin: true
-
- source-map-js@1.2.1:
- resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
- engines: {node: '>=0.10.0'}
-
- tinyglobby@0.2.17:
- resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
- engines: {node: '>=12.0.0'}
-
- to-regex-range@5.0.1:
- resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
- engines: {node: '>=8.0'}
-
- tslib@2.8.1:
- resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
-
- typescript@6.0.3:
- resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==}
- engines: {node: '>=14.17'}
- hasBin: true
-
- vite-plugin-singlefile@2.3.3:
- resolution: {integrity: sha512-XVnGH0QzbOa8fxRSsHdCarVN1BSBXNi7uLMQYlrGRN5apdHkk62XQWRJhVever0lnfuyBkwn+kvVChdm/OoOUg==}
- engines: {node: '>18.0.0'}
- peerDependencies:
- rollup: ^4.59.0
- vite: ^5.4.21 || ^6.0.0 || ^7.0.0 || ^8.0.0
- peerDependenciesMeta:
- rollup:
- optional: true
-
- vite@8.0.16:
- resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==}
- engines: {node: ^20.19.0 || >=22.12.0}
- hasBin: true
- peerDependencies:
- '@types/node': ^20.19.0 || >=22.12.0
- '@vitejs/devtools': ^0.1.18
- esbuild: ^0.27.0 || ^0.28.0
- jiti: '>=1.21.0'
- less: ^4.0.0
- sass: ^1.70.0
- sass-embedded: ^1.70.0
- stylus: '>=0.54.8'
- sugarss: ^5.0.0
- terser: ^5.16.0
- tsx: ^4.8.1
- yaml: ^2.4.2
- peerDependenciesMeta:
- '@types/node':
- optional: true
- '@vitejs/devtools':
- optional: true
- esbuild:
- optional: true
- jiti:
- optional: true
- less:
- optional: true
- sass:
- optional: true
- sass-embedded:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
- tsx:
- optional: true
- yaml:
- optional: true
-
-snapshots:
-
- '@emnapi/core@1.10.0':
- dependencies:
- '@emnapi/wasi-threads': 1.2.1
- tslib: 2.8.1
- optional: true
-
- '@emnapi/runtime@1.10.0':
- dependencies:
- tslib: 2.8.1
- optional: true
-
- '@emnapi/wasi-threads@1.2.1':
- dependencies:
- tslib: 2.8.1
- optional: true
-
- '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
- dependencies:
- '@emnapi/core': 1.10.0
- '@emnapi/runtime': 1.10.0
- '@tybys/wasm-util': 0.10.2
- optional: true
-
- '@oxc-project/types@0.133.0': {}
-
- '@rolldown/binding-android-arm64@1.0.3':
- optional: true
-
- '@rolldown/binding-darwin-arm64@1.0.3':
- optional: true
-
- '@rolldown/binding-darwin-x64@1.0.3':
- optional: true
-
- '@rolldown/binding-freebsd-x64@1.0.3':
- optional: true
-
- '@rolldown/binding-linux-arm-gnueabihf@1.0.3':
- optional: true
-
- '@rolldown/binding-linux-arm64-gnu@1.0.3':
- optional: true
-
- '@rolldown/binding-linux-arm64-musl@1.0.3':
- optional: true
-
- '@rolldown/binding-linux-ppc64-gnu@1.0.3':
- optional: true
-
- '@rolldown/binding-linux-s390x-gnu@1.0.3':
- optional: true
-
- '@rolldown/binding-linux-x64-gnu@1.0.3':
- optional: true
-
- '@rolldown/binding-linux-x64-musl@1.0.3':
- optional: true
-
- '@rolldown/binding-openharmony-arm64@1.0.3':
- optional: true
-
- '@rolldown/binding-wasm32-wasi@1.0.3':
- dependencies:
- '@emnapi/core': 1.10.0
- '@emnapi/runtime': 1.10.0
- '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
- optional: true
-
- '@rolldown/binding-win32-arm64-msvc@1.0.3':
- optional: true
-
- '@rolldown/binding-win32-x64-msvc@1.0.3':
- optional: true
-
- '@rolldown/pluginutils@1.0.1': {}
-
- '@tybys/wasm-util@0.10.2':
- dependencies:
- tslib: 2.8.1
- optional: true
-
- braces@3.0.3:
- dependencies:
- fill-range: 7.1.1
-
- detect-libc@2.1.2: {}
-
- fdir@6.5.0(picomatch@4.0.4):
- optionalDependencies:
- picomatch: 4.0.4
-
- fill-range@7.1.1:
- dependencies:
- to-regex-range: 5.0.1
-
- fsevents@2.3.3:
- optional: true
-
- is-number@7.0.0: {}
-
- lightningcss-android-arm64@1.32.0:
- optional: true
-
- lightningcss-darwin-arm64@1.32.0:
- optional: true
-
- lightningcss-darwin-x64@1.32.0:
- optional: true
-
- lightningcss-freebsd-x64@1.32.0:
- optional: true
-
- lightningcss-linux-arm-gnueabihf@1.32.0:
- optional: true
-
- lightningcss-linux-arm64-gnu@1.32.0:
- optional: true
-
- lightningcss-linux-arm64-musl@1.32.0:
- optional: true
-
- lightningcss-linux-x64-gnu@1.32.0:
- optional: true
-
- lightningcss-linux-x64-musl@1.32.0:
- optional: true
-
- lightningcss-win32-arm64-msvc@1.32.0:
- optional: true
-
- lightningcss-win32-x64-msvc@1.32.0:
- optional: true
-
- lightningcss@1.32.0:
- dependencies:
- detect-libc: 2.1.2
- optionalDependencies:
- lightningcss-android-arm64: 1.32.0
- lightningcss-darwin-arm64: 1.32.0
- lightningcss-darwin-x64: 1.32.0
- lightningcss-freebsd-x64: 1.32.0
- lightningcss-linux-arm-gnueabihf: 1.32.0
- lightningcss-linux-arm64-gnu: 1.32.0
- lightningcss-linux-arm64-musl: 1.32.0
- lightningcss-linux-x64-gnu: 1.32.0
- lightningcss-linux-x64-musl: 1.32.0
- lightningcss-win32-arm64-msvc: 1.32.0
- lightningcss-win32-x64-msvc: 1.32.0
-
- micromatch@4.0.8:
- dependencies:
- braces: 3.0.3
- picomatch: 2.3.2
-
- nanoid@3.3.13: {}
-
- picocolors@1.1.1: {}
-
- picomatch@2.3.2: {}
-
- picomatch@4.0.4: {}
-
- postcss@8.5.15:
- dependencies:
- nanoid: 3.3.13
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
- rolldown@1.0.3:
- dependencies:
- '@oxc-project/types': 0.133.0
- '@rolldown/pluginutils': 1.0.1
- optionalDependencies:
- '@rolldown/binding-android-arm64': 1.0.3
- '@rolldown/binding-darwin-arm64': 1.0.3
- '@rolldown/binding-darwin-x64': 1.0.3
- '@rolldown/binding-freebsd-x64': 1.0.3
- '@rolldown/binding-linux-arm-gnueabihf': 1.0.3
- '@rolldown/binding-linux-arm64-gnu': 1.0.3
- '@rolldown/binding-linux-arm64-musl': 1.0.3
- '@rolldown/binding-linux-ppc64-gnu': 1.0.3
- '@rolldown/binding-linux-s390x-gnu': 1.0.3
- '@rolldown/binding-linux-x64-gnu': 1.0.3
- '@rolldown/binding-linux-x64-musl': 1.0.3
- '@rolldown/binding-openharmony-arm64': 1.0.3
- '@rolldown/binding-wasm32-wasi': 1.0.3
- '@rolldown/binding-win32-arm64-msvc': 1.0.3
- '@rolldown/binding-win32-x64-msvc': 1.0.3
-
- source-map-js@1.2.1: {}
-
- tinyglobby@0.2.17:
- dependencies:
- fdir: 6.5.0(picomatch@4.0.4)
- picomatch: 4.0.4
-
- to-regex-range@5.0.1:
- dependencies:
- is-number: 7.0.0
-
- tslib@2.8.1:
- optional: true
-
- typescript@6.0.3: {}
-
- vite-plugin-singlefile@2.3.3(vite@8.0.16):
- dependencies:
- micromatch: 4.0.8
- vite: 8.0.16
-
- vite@8.0.16:
- dependencies:
- lightningcss: 1.32.0
- picomatch: 4.0.4
- postcss: 8.5.15
- rolldown: 1.0.3
- tinyglobby: 0.2.17
- optionalDependencies:
- fsevents: 2.3.3
diff --git a/2026/games_submissions/gbjk/src/src/main.ts b/2026/games_submissions/gbjk/src/src/main.ts
deleted file mode 100644
index 8752b31..0000000
--- a/2026/games_submissions/gbjk/src/src/main.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { setup } from "./setup";
-import "./style.css";
-
-document.querySelector<HTMLDivElement>("#app")!.innerHTML = `
- <div class="layout">
-
- <div class="game">
- <div class="title-bar">
- <h1>Tortis</h1>
- <p>(4row clear to win)</p>
- </div>
-
- <canvas height="240" width="160" id="main"></canvas>
- </div>
-
- <ul>
- <button id="move-left">move left</button>
- <button id="rotate-left">rotate left</button>
- <button id="move-right">move right</button>
- <button id="rotate-right">rotate right</button>
- <button id="speed-up">speed up</button>
- </ul>
- </div>
-`;
-
-setup({
- main: document.querySelector<HTMLCanvasElement>("#main")!,
- left: document.querySelector<HTMLButtonElement>("#move-left")!,
- right: document.querySelector<HTMLButtonElement>("#move-right")!,
- rotateLeft: document.querySelector<HTMLButtonElement>("#rotate-left")!,
- rotateRight: document.querySelector<HTMLButtonElement>("#rotate-right")!,
- speedUp: document.querySelector<HTMLButtonElement>("#speed-up")!,
-});
diff --git a/2026/games_submissions/gbjk/src/src/setup.ts b/2026/games_submissions/gbjk/src/src/setup.ts
deleted file mode 100644
index 9d0614b..0000000
--- a/2026/games_submissions/gbjk/src/src/setup.ts
+++ /dev/null
@@ -1,389 +0,0 @@
-export type Elements = {
- main: HTMLCanvasElement;
- right: HTMLButtonElement;
- left: HTMLButtonElement;
- rotateRight: HTMLButtonElement;
- rotateLeft: HTMLButtonElement;
- speedUp: HTMLButtonElement;
-};
-
-const WIDTH = 160;
-const HEIGHT = 240;
-
-const GRID_HEIGHT = HEIGHT - 10;
-const ROWS = 15;
-const COLS = 10;
-const GRID_WIDTH = (GRID_HEIGHT / ROWS) * 10;
-const GRID_X = 5;
-const GRID_Y = 5;
-const MARGIN = 2;
-const CELL_WIDTH = GRID_HEIGHT / ROWS - MARGIN;
-const FALLTIME = 600;
-const MIN_FALLTIME = 300;
-
-let rotation = 0;
-
-type Block =
- | "void"
- | "red"
- | "green"
- | "blue"
- | "fallingRed"
- | "fallingGreen"
- | "fallingBlue";
-
-const board: Block[][] = [];
-
-function resetBoard() {
- board.length = 0;
-
- for (let height = 0; height < ROWS; height++) {
- const row: Block[] = [];
- for (let width = 0; width < COLS; width++) {
- row.push("void");
- }
- board.push(row);
- }
-}
-
-resetBoard();
-
-function random<T>(elements: T[]): T {
- return elements[Math.floor(Math.random() * elements.length)];
-}
-
-let addedShapeNumber = 1;
-function addSquares(): boolean {
- const color = random(["fallingRed", "fallingGreen", "fallingBlue"] as const);
- let w = COLS / 2;
- let h = 1;
- for (let i = 0; i < 4; i++) {
- board[h][w] = color;
-
- if (i === 3) break;
-
- let move: "up" | "down" | "left" | "right" | null = null;
- let j = 0;
- for (; j < 20; j++) {
- move =
- addedShapeNumber % 6 === 0
- ? "down"
- : random(["up", "down", "left", "right"] as const);
-
- if (move === "up" && (h === 0 || board[h - 1][w] !== "void")) continue;
- if (move === "down" && (h === ROWS - 1 || board[h + 1][w] !== "void"))
- continue;
-
- if (move === "left" && (w === 0 || board[h][w - 1] !== "void")) continue;
- if (move === "right" && (w === COLS - 1 || board[h][w + 1] !== "void"))
- continue;
-
- break;
- }
- if (j === 20) {
- return false;
- }
-
- switch (move) {
- case "up":
- h--;
- break;
- case "down":
- h++;
- break;
- case "left":
- w--;
- break;
- case "right":
- w++;
- break;
- }
- }
-
- addedShapeNumber++;
- return true;
-}
-
-function clearFilledRows(): number {
- let lastClearedRow = ROWS;
- let clearedRows = 0;
-
- for (let row = ROWS - 1; row >= 0; row--) {
- if (
- !board[row].some(
- (cell) =>
- cell === "void" ||
- cell === "fallingBlue" ||
- cell === "fallingGreen" ||
- cell === "fallingRed",
- )
- ) {
- for (let col = 0; col < COLS; col++) {
- board[row][col] = "void";
- }
- lastClearedRow = row;
- clearedRows++;
- } else if (lastClearedRow !== ROWS) {
- for (let col = 0; col < COLS; col++) {
- switch (board[row][col]) {
- case "red":
- board[row][col] = "fallingRed";
- break;
- case "green":
- board[row][col] = "fallingGreen";
- break;
- case "blue":
- board[row][col] = "fallingBlue";
- break;
- }
- }
- }
- }
-
- return clearedRows;
-}
-
-export function setup(elements: Elements) {
- const ctx = elements.main.getContext("2d")!;
-
- let gameRunning = false;
- let animationFrameId: number | null = null;
- let lastFrame = 0;
- let fallTime = FALLTIME;
-
- let speedUpPressed = false;
-
- elements.left.addEventListener("click", () => moveFalling("left"));
- elements.right.addEventListener("click", () => moveFalling("right"));
-
- elements.rotateLeft.addEventListener("click", () => {
- if (!gameRunning) return;
-
- rotation -= 30 * Math.random();
- elements.main.style.transform = `rotate(${rotation}deg)`;
- });
- elements.rotateRight.addEventListener("click", () => {
- if (!gameRunning) return;
-
- rotation += 30 * Math.random();
- elements.main.style.transform = `rotate(${rotation}deg)`;
- });
-
- elements.speedUp.addEventListener(
- "mousedown",
- () => (speedUpPressed = gameRunning),
- );
- elements.speedUp.addEventListener("mouseup", () => (speedUpPressed = false));
-
- window.addEventListener("message", (ev: MessageEvent<unknown>) => {
- const message = ev.data;
- if (!isStartMessage(message)) return;
-
- startGame(message.difficulty);
- });
-
- window.parent.postMessage({ op: "ready" }, "*");
-
- draw();
-
- function isStartMessage(
- message: unknown,
- ): message is { op: "start"; difficulty: number } {
- if (typeof message !== "object" || message === null) return false;
-
- const candidate = message as { op?: unknown; difficulty?: unknown };
- return (
- candidate.op === "start" &&
- typeof candidate.difficulty === "number" &&
- Number.isFinite(candidate.difficulty)
- );
- }
-
- function resetGame(difficulty: number) {
- resetBoard();
- addedShapeNumber = 1;
- fallTime = Math.max(MIN_FALLTIME, FALLTIME - Math.max(0, difficulty) * 5);
- rotation = 0;
- elements.main.style.transform = "";
- speedUpPressed = false;
- lastFrame = 0;
- }
-
- function startGame(difficulty: number) {
- if (animationFrameId !== null) {
- cancelAnimationFrame(animationFrameId);
- animationFrameId = null;
- }
-
- resetGame(difficulty);
- gameRunning = true;
- window.parent.postMessage({ op: "started", verb: "catch!" }, "*");
- animationFrameId = requestAnimationFrame(gameLoop);
- }
-
- function finishGame(win: boolean) {
- if (!gameRunning) return;
-
- gameRunning = false;
- if (animationFrameId !== null) {
- cancelAnimationFrame(animationFrameId);
- animationFrameId = null;
- }
-
- window.parent.postMessage({ op: "done", win }, "*");
- resetGame(0);
- draw();
- }
-
- function moveFalling(move: "left" | "right") {
- if (!gameRunning) return;
-
- switch (move) {
- case "left":
- for (let row = 0; row < ROWS; row++) {
- for (let col = 0; col < COLS - 1; col++) {
- if (board[row][col] === "void") {
- switch (board[row][col + 1]) {
- case "fallingRed":
- case "fallingGreen":
- case "fallingBlue":
- board[row][col] = board[row][col + 1];
- board[row][col + 1] = "void";
- }
- }
- }
- }
- break;
- case "right":
- for (let row = 0; row < ROWS; row++) {
- for (let col = COLS - 1; col > 0; col--) {
- if (board[row][col] === "void") {
- switch (board[row][col - 1]) {
- case "fallingRed":
- case "fallingGreen":
- case "fallingBlue":
- board[row][col] = board[row][col - 1];
- board[row][col - 1] = "void";
- }
- }
- }
- }
- break;
- }
- }
-
- function physics(): boolean {
- let somethingFell = false;
-
- for (let row = ROWS - 1; row >= 1; row--) {
- for (let col = 0; col < COLS; col++) {
- let space = board[row][col];
- let above = board[row - 1][col];
- switch (above) {
- case "fallingRed":
- case "fallingGreen":
- case "fallingBlue":
- if (space === "void") {
- somethingFell = true;
- board[row][col] = board[row - 1][col];
- board[row - 1][col] = "void";
- } else {
- switch (above) {
- case "fallingRed":
- board[row - 1][col] = "red";
- break;
- case "fallingGreen":
- board[row - 1][col] = "green";
- break;
- case "fallingBlue":
- board[row - 1][col] = "blue";
- break;
- }
- }
- }
- }
- }
-
- for (let col = 0; col < COLS; col++) {
- switch (board[ROWS - 1][col]) {
- case "fallingRed":
- board[ROWS - 1][col] = "red";
- break;
- case "fallingGreen":
- board[ROWS - 1][col] = "green";
- break;
- case "fallingBlue":
- board[ROWS - 1][col] = "blue";
- break;
- }
- }
-
- return somethingFell;
- }
-
- function draw() {
- ctx.clearRect(0, 0, WIDTH, HEIGHT);
-
- ctx.fillStyle = "black";
- ctx.fillRect(GRID_X, GRID_Y, GRID_WIDTH, GRID_HEIGHT);
-
- for (let h = 0; h < ROWS; h++) {
- for (let w = 0; w < COLS; w++) {
- switch (board[h][w]) {
- case "void":
- ctx.fillStyle = "#2e2e2e";
- break;
- case "red":
- ctx.fillStyle = "#994444";
- break;
- case "green":
- ctx.fillStyle = "#449944";
- break;
- case "blue":
- ctx.fillStyle = "#444499";
- break;
- case "fallingRed":
- ctx.fillStyle = "#bb3333";
- break;
- case "fallingGreen":
- ctx.fillStyle = "#33bb33";
- break;
- case "fallingBlue":
- ctx.fillStyle = "#3333bb";
- break;
- }
-
- const x = GRID_X + MARGIN * 1.5 + w * CELL_WIDTH + (w - 1) * MARGIN;
- const y = GRID_Y + MARGIN * 1.5 + h * CELL_WIDTH + (h - 1) * MARGIN;
-
- ctx.fillRect(x, y, CELL_WIDTH, CELL_WIDTH);
- }
- }
- }
-
- function gameLoop(time: number) {
- animationFrameId = null;
-
- if (!gameRunning) return;
-
- if (time - lastFrame > (speedUpPressed ? fallTime / 10 : fallTime)) {
- lastFrame = time;
- const somethingFell = physics();
- if (!somethingFell) {
- const clearedRows = clearFilledRows();
- if (clearedRows >= 4) {
- finishGame(true);
- return;
- } else if (clearedRows === 0) {
- if (!addSquares()) {
- finishGame(false);
- return;
- }
- }
- }
- }
-
- draw();
- animationFrameId = requestAnimationFrame(gameLoop);
- }
-}
diff --git a/2026/games_submissions/gbjk/src/src/style.css b/2026/games_submissions/gbjk/src/src/style.css
deleted file mode 100644
index 56e07d1..0000000
--- a/2026/games_submissions/gbjk/src/src/style.css
+++ /dev/null
@@ -1,103 +0,0 @@
-* {
- box-sizing: border-box;
-}
-
-html,
-body,
-#app {
- min-height: 100%;
-}
-
-body {
- margin: 0;
- color: darksalmon;
- background-color: #2e2e2e;
- font-family: monospace;
- overflow-x: hidden;
-}
-
-button {
- min-width: 0;
- font: inherit;
- font-size: .4rem;
- line-height: 1.1;
- padding: .15rem;
- color: darksalmon;
- background-color: #2e2e2e;
- border-color: salmon;
- cursor: pointer;
- white-space: normal;
- overflow-wrap: anywhere;
-
- z-index: 9999;
-}
-
-button:hover {
- background-color: darkslategray;
-}
-
-button:active {
- background-color: slategray;
-}
-
-.layout {
- margin: auto;
- display: flex;
- min-height: 100dvh;
- width: 100%;
- padding: .15rem;
- gap: .2rem;
- align-items: center;
- justify-content: center;
- overflow: hidden;
-}
-
-.game {
- min-width: 0;
-}
-
-.title-bar {
- display: flex;
- align-items: baseline;
- gap: .25rem;
- margin-bottom: .2rem;
-}
-
-h1,
-p {
- margin: 0;
-}
-
-h1 {
- font-size: .6rem;
- line-height: 1;
-}
-
-p {
- font-size: .4rem;
- line-height: 1.1;
-}
-
-canvas {
- display: block;
- aspect-ratio: 2 / 3;
- border-radius: 6px;
- border: 1px solid darksalmon;
- box-shadow: 0px 0px 4px darksalmon;
- height: 80vmin;
- width: auto;
-
- transition: transform 100ms;
- margin: auto;
-}
-
-ul {
- display: flex;
- justify-content: center;
- flex-direction: column;
- gap: .15rem;
- width: min(6rem, 42vw);
- margin: 0;
- padding: 0;
- list-style: none;
-}
diff --git a/2026/games_submissions/gbjk/src/tsconfig.json b/2026/games_submissions/gbjk/src/tsconfig.json
deleted file mode 100644
index 1ab38c8..0000000
--- a/2026/games_submissions/gbjk/src/tsconfig.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "compilerOptions": {
- "target": "es2023",
- "module": "esnext",
- "lib": ["ES2023", "DOM"],
- "types": ["vite/client"],
- "skipLibCheck": true,
-
- /* Bundler mode */
- "moduleResolution": "bundler",
- "allowImportingTsExtensions": true,
- "verbatimModuleSyntax": true,
- "moduleDetection": "force",
- "noEmit": true,
-
- /* Linting */
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "erasableSyntaxOnly": true,
- "noFallthroughCasesInSwitch": true
- },
- "include": ["src"]
-}
diff --git a/2026/games_submissions/gbjk/src/vite.config.ts b/2026/games_submissions/gbjk/src/vite.config.ts
deleted file mode 100644
index c9036bd..0000000
--- a/2026/games_submissions/gbjk/src/vite.config.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { defineConfig } from "vite";
-import { viteSingleFile } from "vite-plugin-singlefile";
-
-export default defineConfig({
- plugins: [viteSingleFile()],
- build: {
- minify: false,
- },
-});