From 50942522feb7c65265c5e00386ef67364f58a269 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Sat, 24 Aug 2024 06:26:38 -0500 Subject: [PATCH 01/35] snake: add most of snake, needs trim function to be fixed --- index.html | 6 ++ js/snake.js | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 js/snake.js diff --git a/index.html b/index.html index e7b82cb..a72e5af 100644 --- a/index.html +++ b/index.html @@ -26,6 +26,12 @@

Right Paddle Height:

View Code +
+

Snake

+ + + View Code +
diff --git a/js/snake.js b/js/snake.js new file mode 100644 index 0000000..94815e2 --- /dev/null +++ b/js/snake.js @@ -0,0 +1,220 @@ +/* + bits: + 0 = snake + 1 = food + 2 = checked (for searching algorithms) +*/ + +// Bit functions for ease +function isBitSet(num, bit){ + return ((num >> bit) % 2 != 0) +} + +function bitSet(num, bit){ + return num | 1 << bit; +} + +function bitClear(num, bit){ + return num & ~(1 << bit); +} + +class OrderedPair { + constructor(x, y) { + this.x = x; + this.y = y; + } +} + +class SnakeCore { + constructor() { + // TODO: Add CSS stuff for page + this.canvas = document.getElementById('snake'); + this.context = this.canvas.getContext('2d'); + this.grid = 25; // size of grid squares + this.speed = 10; // speed in ms + this.width = 25; + this.height = 15; + this.board = []; + for (let i = 0; i < this.height; i++) { + this.board.push(new Array(this.width)); + for (let j = 0; j < this.width; j++) { + this.board[i][j] = 0; + } + } + this.body = []; + this.gameover = false; + this.foodAte = true; + this.body.push(new OrderedPair(12, 8)); + this.board[8][12] = 1; + } + + reset() { + snake.gameover = false; + snake.foodAte = true; + for (let i = 0; i < this.height; i++) { + for (let j = 0; j < this.width; j++) { + this.board[i][j] = 0; + } + } + } + + foodRegen() { + if (!this.foodAte) + return; + this.foodAte = false; + while (true) { + let tmp = new OrderedPair(Math.floor(Math.random() * this.width), Math.floor(Math.random() * this.height)); + if (isBitSet(this.board[tmp.y][tmp.x], 0)) + continue; + this.board[tmp.y][tmp.x] = bitSet(this.board[tmp.y][tmp.x], 1); + return; + } + } +} + +class Bot { + constructor() { + this.pathUntrimmed = []; + this.path = []; + } + + bfs() { + var search = [snake.body.at(0)]; + while (search.length !== 0) { + let current = search.pop(); + if (isBitSet(snake.board[current.y][current.x], 2)) + continue; + this.pathUntrimmed.push(current); + let locals = []; + for (var i = 0; i < 4; i++) + locals[i] = new OrderedPair(current.x, current.y); + locals[0].y += 1; + locals[1].x += 1; + locals[2].y -= 1; + locals[3].x -= 1; + for (const local of locals) { + if (local.x < 0 || local.x > snake.width - 1 || local.y < 0 || local.y > snake.height - 1) { + continue; + } + let value = snake.board[local.y][local.x]; + if (isBitSet(value, 1)) { + this.pathUntrimmed.push(local); + return; + } + if (isBitSet(value, 2)) + continue; + if (isBitSet(value, 0)) + continue; + search.push(local); + } + snake.board[current.y][current.x] = bitSet(snake.board[current.y][current.x], 2); + } + } + + // TODO: Fix trim function + trim() { + let reachedSnake = false; + this.path.push(this.pathUntrimmed.pop()); // Push food location + while (this.pathUntrimmed.length !== 0) { + if (!reachedSnake) { + let location = this.pathUntrimmed.shift(); + if (isBitSet(snake.board[location.y][location.x], 0)) + reachedSnake = true; + var delta = new OrderedPair; + let connection = this.path.at(0); + delta.x = location.x - connection.x; + delta.y = location.y - connection.y; + if ((Math.abs(delta.x) + Math.abs(delta.y)) === 1) + this.path.push(location); + } else + this.pathUntrimmed.shift(); + } + } + + unvisit() { + for (let i = 0; i < snake.height; i++) { + for (let j = 0; j < snake.width; j++) { + snake.board[i][j] = bitClear(snake.board[i][j], 2); + } + } + } + + /* + values: + 0 = left + 1 = up + 2 = right + 4 = down + */ + autoplay() { + if (this.path.length !== 0) + return; + this.bfs(); + //this.trim(); + this.unvisit(); + /* + let delta = this.headPos - this.path.pop(); + if (delta.x > 0) + return 0; + if (delta.y > 0) + return 1; + if (delta.x < 0) + return 2; + if (delta.y < 0) + return 4; + return 0; // Safety guard if above doesn't return + */ + } +} + +const snake = new SnakeCore(); // Singleton for snake game +const bot = new Bot(); // Singleton for bot playing + +function snakeloop() { + snake.context.clearRect(0, 0, snake.canvas.width, snake.canvas.height); + // Reset of needed + if (snake.gameover) + snake.reset(); + // Input + bot.autoplay(); + + // Move snake + // TODO: Fix teleporting snake + let next = bot.pathUntrimmed.shift(); + + if (next.x < 0 || next.x > snake.width || next.y < 0 || next.y > snake.height) + snake.gameover = true; + if (isBitSet(snake.board[next.y][next.x], 0) && (snake.body.length > 1)) + snake.gameover = true; // Game should end (Snake touching snake) + + snake.board[next.y][next.x] = bitSet(snake.board[next.y][next.x], 0); + snake.body.push(next); + if (!isBitSet(snake.board[next.y][next.x], 1)) { + let old = snake.body.shift(); + snake.board[old.y][old.x] = bitClear(snake.board[old.y][old.x], 0); + } else { + snake.board[next.y][next.x] = bitClear(snake.board[next.y][next.x], 1); + snake.foodAte = true; + while (bot.path.length > 0) + bot.path.pop(); + } + + // Regenerate food if needed + snake.foodRegen(); + + // Draw game + for (let i = 0; i < snake.height; i++) { + for (let j = 0; j < snake.width; j++) { + if (isBitSet(snake.board[i][j], 0)) + snake.context.fillStyle = "green"; + else if (isBitSet(snake.board[i][j], 1)) + snake.context.fillStyle = "red"; + else + snake.context.fillStyle = "black"; + snake.context.fillRect(j * snake.grid, i * snake.grid, snake.grid, snake.grid); + } + } +} + +// start the game +setInterval(snakeloop, snake.speed); From 0cbdb1f7fcb3e3c5acf3bc771c3821a689c1dcc8 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:28:36 -0500 Subject: [PATCH 02/35] core: add typescript and npm --- .gitignore | 11 +++++++++++ package-lock.json | 29 +++++++++++++++++++++++++++++ package.json | 18 ++++++++++++++++++ tsconfig.json | 8 ++++++++ 4 files changed, 66 insertions(+) create mode 100644 .gitignore create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0fb9ddb --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# production +/build + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..255b297 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,29 @@ +{ + "name": "trianta.dev", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "trianta.dev", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "typescript": "^5.5.4" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e8ba880 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "trianta.dev", + "version": "0.1.0", + "description": "My personal website", + "main": "index.html", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://lab.trianta.dev/Trianta/trianta.dev.git" + }, + "author": "trianta", + "license": "MIT", + "dependencies": { + "typescript": "^5.5.4" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..aadd7b2 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "outDir": "./built", + "allowJs": true, + "target": "es5" + }, + "include": ["./src/**/*"] +} From eb6c0235781f6558239c2131e3b2c78c01592745 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:29:51 -0500 Subject: [PATCH 03/35] tsconfig: adjust build dir name --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index aadd7b2..fe73056 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "outDir": "./built", + "outDir": "./build", "allowJs": true, "target": "es5" }, From 53af7849520e78833366795799ac24b392530e42 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:32:54 -0500 Subject: [PATCH 04/35] core: move files to src and convert snake to ts --- {css => src}/home.css | 5 +- {css => src}/pong.css | 0 {js => src}/pong.js | 0 js/snake.js => src/snake.ts | 120 ++++++++++++++++++++++++++---------- 4 files changed, 92 insertions(+), 33 deletions(-) rename {css => src}/home.css (96%) rename {css => src}/pong.css (100%) rename {js => src}/pong.js (100%) rename js/snake.js => src/snake.ts (63%) diff --git a/css/home.css b/src/home.css similarity index 96% rename from css/home.css rename to src/home.css index 751f8bb..90107a7 100644 --- a/css/home.css +++ b/src/home.css @@ -125,8 +125,11 @@ a.button { border-top-left-radius: 18px; border-top-right-radius: 18px; animation: card 3s linear infinite; - max-width: 800px; + width: 800px; + height: 800px; margin: 0px auto; + margin-top: 25px; + margin-bottom: 25px; } .cardTop { diff --git a/css/pong.css b/src/pong.css similarity index 100% rename from css/pong.css rename to src/pong.css diff --git a/js/pong.js b/src/pong.js similarity index 100% rename from js/pong.js rename to src/pong.js diff --git a/js/snake.js b/src/snake.ts similarity index 63% rename from js/snake.js rename to src/snake.ts index 94815e2..ff79f02 100644 --- a/js/snake.js +++ b/src/snake.ts @@ -6,30 +6,58 @@ */ // Bit functions for ease -function isBitSet(num, bit){ - return ((num >> bit) % 2 != 0) +function isBitSet(value: number, bit: number): boolean { + return ((value >> bit) % 2 != 0) } -function bitSet(num, bit){ - return num | 1 << bit; +function bitSet(value: number, bit: number): number { + return value | 1 << bit; } -function bitClear(num, bit){ - return num & ~(1 << bit); +function bitClear(value: number, bit: number): number { + return value & ~(1 << bit); } -class OrderedPair { - constructor(x, y) { +class Point { + x: number; + y: number; + + constructor(x = 0, y = 0) { this.x = x; this.y = y; } + + add(other: Point) { + var result = new Point; + result.x = this.x + other.x; + result.y = this.y + other.y; + return result; + } + + subtract(other: Point) { + var result = new Point; + result.x = this.x - other.x; + result.y = this.y - other.y; + return result; + } } class SnakeCore { + canvas: HTMLCanvasElement; + context: CanvasRenderingContext2D; + grid: number; + speed: number; + width: number; + height: number; + board: number[][]; + body: Point[]; + gameover: boolean; + foodAte: boolean; + constructor() { // TODO: Add CSS stuff for page - this.canvas = document.getElementById('snake'); - this.context = this.canvas.getContext('2d'); + this.canvas = document.getElementById('snake') as HTMLCanvasElement; + this.context = this.canvas.getContext('2d') as CanvasRenderingContext2D; this.grid = 25; // size of grid squares this.speed = 10; // speed in ms this.width = 25; @@ -44,10 +72,14 @@ class SnakeCore { this.body = []; this.gameover = false; this.foodAte = true; - this.body.push(new OrderedPair(12, 8)); + this.body.push(new Point(12, 8)); this.board[8][12] = 1; } + get head(): Point { + return this.body[this.body.length - 1]; + } + reset() { snake.gameover = false; snake.foodAte = true; @@ -63,7 +95,7 @@ class SnakeCore { return; this.foodAte = false; while (true) { - let tmp = new OrderedPair(Math.floor(Math.random() * this.width), Math.floor(Math.random() * this.height)); + let tmp = new Point(Math.floor(Math.random() * this.width), Math.floor(Math.random() * this.height)); if (isBitSet(this.board[tmp.y][tmp.x], 0)) continue; this.board[tmp.y][tmp.x] = bitSet(this.board[tmp.y][tmp.x], 1); @@ -73,21 +105,24 @@ class SnakeCore { } class Bot { + pathUntrimmed: Point[]; + path: Point[]; + constructor() { this.pathUntrimmed = []; this.path = []; } bfs() { - var search = [snake.body.at(0)]; + var search: Point[] = [snake.head]; while (search.length !== 0) { - let current = search.pop(); + let current: Point = search.shift() as Point; if (isBitSet(snake.board[current.y][current.x], 2)) continue; this.pathUntrimmed.push(current); - let locals = []; + let locals: Point[] = new Array[4]; for (var i = 0; i < 4; i++) - locals[i] = new OrderedPair(current.x, current.y); + locals[i] = new Point(current.x, current.y); locals[0].y += 1; locals[1].x += 1; locals[2].y -= 1; @@ -114,20 +149,20 @@ class Bot { // TODO: Fix trim function trim() { let reachedSnake = false; - this.path.push(this.pathUntrimmed.pop()); // Push food location + this.path.push(this.pathUntrimmed.pop() as Point); // Push food location while (this.pathUntrimmed.length !== 0) { if (!reachedSnake) { - let location = this.pathUntrimmed.shift(); + let location = this.pathUntrimmed[this.pathUntrimmed.length - 1]; if (isBitSet(snake.board[location.y][location.x], 0)) reachedSnake = true; - var delta = new OrderedPair; - let connection = this.path.at(0); + var delta = new Point; + let connection = this.path[this.path.length - 1]; delta.x = location.x - connection.x; delta.y = location.y - connection.y; if ((Math.abs(delta.x) + Math.abs(delta.y)) === 1) this.path.push(location); - } else - this.pathUntrimmed.shift(); + } + this.pathUntrimmed.pop(); } } @@ -146,12 +181,34 @@ class Bot { 2 = right 4 = down */ + nextMove() { + var next: Point = this.path.pop() as Point; + var head: Point = snake.head; + var delta = new Point(0, 0); + delta = next.subtract(head); + if (delta.x > 1) { + delta.x = 1; + console.log("[ERR] delta.x > 1, clamping"); + } else if (delta.x < -1) { + delta.x = -1; + console.log("[ERR] delta.x < 1, clamping"); + } + if (delta.y > 1) { + delta.y = 1; + console.log("[ERR] delta.y > 1, clamping"); + } else if (delta.y < -1) { + delta.y = -1; + console.log("[ERR] delta.y < 1, clamping"); + } + return delta; + } + autoplay() { - if (this.path.length !== 0) - return; - this.bfs(); - //this.trim(); - this.unvisit(); + if (this.path.length === 0) + this.bfs(); + this.trim(); + this.unvisit(); + return this.nextMove(); /* let delta = this.headPos - this.path.pop(); if (delta.x > 0) @@ -167,8 +224,8 @@ class Bot { } } -const snake = new SnakeCore(); // Singleton for snake game -const bot = new Bot(); // Singleton for bot playing +const snake: SnakeCore = new SnakeCore(); // Singleton for snake game +const bot: Bot = new Bot(); // Singleton for bot playing function snakeloop() { snake.context.clearRect(0, 0, snake.canvas.width, snake.canvas.height); @@ -180,8 +237,7 @@ function snakeloop() { // Move snake // TODO: Fix teleporting snake - let next = bot.pathUntrimmed.shift(); - + let next = bot.nextMove().add(snake.head); if (next.x < 0 || next.x > snake.width || next.y < 0 || next.y > snake.height) snake.gameover = true; if (isBitSet(snake.board[next.y][next.x], 0) && (snake.body.length > 1)) @@ -190,7 +246,7 @@ function snakeloop() { snake.board[next.y][next.x] = bitSet(snake.board[next.y][next.x], 0); snake.body.push(next); if (!isBitSet(snake.board[next.y][next.x], 1)) { - let old = snake.body.shift(); + let old: Point = snake.body.shift() as Point; snake.board[old.y][old.x] = bitClear(snake.board[old.y][old.x], 0); } else { snake.board[next.y][next.x] = bitClear(snake.board[next.y][next.x], 1); From 06b7aa8c6f29fb36edffeebe679c9679e7d9bdec Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:34:13 -0500 Subject: [PATCH 05/35] index: use new files after move and ts conversion --- index.html | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index a72e5af..93ab29a 100644 --- a/index.html +++ b/index.html @@ -3,10 +3,10 @@ Trianta - + - From f975b0a0453a839f1a2b1d40860b2f5b1e8de563 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Wed, 28 Aug 2024 00:29:51 -0500 Subject: [PATCH 06/35] snake: move core game pieces into separate functions instead of just the main loop --- src/snake.ts | 151 ++++++++++++++++++++++++++++----------------------- 1 file changed, 83 insertions(+), 68 deletions(-) diff --git a/src/snake.ts b/src/snake.ts index ff79f02..d5781a5 100644 --- a/src/snake.ts +++ b/src/snake.ts @@ -27,6 +27,11 @@ class Point { this.y = y; } + copy(other: Point) { + this.x = other.x; + this.y = other.y; + } + add(other: Point) { var result = new Point; result.x = this.x + other.x; @@ -46,7 +51,7 @@ class SnakeCore { canvas: HTMLCanvasElement; context: CanvasRenderingContext2D; grid: number; - speed: number; + timeout: number; width: number; height: number; board: number[][]; @@ -59,7 +64,7 @@ class SnakeCore { this.canvas = document.getElementById('snake') as HTMLCanvasElement; this.context = this.canvas.getContext('2d') as CanvasRenderingContext2D; this.grid = 25; // size of grid squares - this.speed = 10; // speed in ms + this.timeout = 100; // speed in ms this.width = 25; this.height = 15; this.board = []; @@ -88,6 +93,12 @@ class SnakeCore { this.board[i][j] = 0; } } + snake.context.fillStyle = "black"; + for (let i = 0; i < snake.height; i++) { + for (let j = 0; j < snake.width; j++) { + snake.context.fillRect(j * snake.grid, i * snake.grid, snake.grid, snake.grid); + } + } } foodRegen() { @@ -102,6 +113,53 @@ class SnakeCore { return; } } + + // Simulate game logic + simulate() { + // Move snake + // TODO: Fix teleporting snake + let next: Point = new Point; + next.copy(bot.nextMove()); + if (next.x < 0 || next.x > snake.width || next.y < 0 || next.y > snake.height) { + snake.gameover = true; + return; + } + if (isBitSet(snake.board[next.y][next.x], 0) && (snake.body.length > 1)) { + snake.gameover = true; // Game should end (Snake touching snake) + return; + } + + snake.board[next.y][next.x] = bitSet(snake.board[next.y][next.x], 0); + snake.body.push(next); + if (!isBitSet(snake.board[next.y][next.x], 1)) { + let old: Point = snake.body.shift() as Point; + snake.board[old.y][old.x] = bitClear(snake.board[old.y][old.x], 0); + } else { + snake.board[next.y][next.x] = bitClear(snake.board[next.y][next.x], 1); + snake.foodAte = true; + while (bot.path.length > 0) + bot.path.pop(); + } + } + + // Draw game to canvas + draw() { + // Clear the screen + snake.context.clearRect(0, 0, snake.canvas.width, snake.canvas.height); + + // Draw game + for (let i = 0; i < snake.height; i++) { + for (let j = 0; j < snake.width; j++) { + if (isBitSet(snake.board[i][j], 0)) + snake.context.fillStyle = "green"; + else if (isBitSet(snake.board[i][j], 1)) + snake.context.fillStyle = "red"; + else + snake.context.fillStyle = "black"; + snake.context.fillRect(j * snake.grid, i * snake.grid, snake.grid, snake.grid); + } + } + } } class Bot { @@ -120,9 +178,11 @@ class Bot { if (isBitSet(snake.board[current.y][current.x], 2)) continue; this.pathUntrimmed.push(current); - let locals: Point[] = new Array[4]; - for (var i = 0; i < 4; i++) - locals[i] = new Point(current.x, current.y); + let locals: Point[] = new Array(4); + for (var i = 0; i < 4; i++) { + locals[i] = new Point; + locals[i].copy(current); + } locals[0].y += 1; locals[1].x += 1; locals[2].y -= 1; @@ -152,13 +212,12 @@ class Bot { this.path.push(this.pathUntrimmed.pop() as Point); // Push food location while (this.pathUntrimmed.length !== 0) { if (!reachedSnake) { - let location = this.pathUntrimmed[this.pathUntrimmed.length - 1]; + let location: Point = new Point; + location.copy(this.pathUntrimmed[this.pathUntrimmed.length - 1]); if (isBitSet(snake.board[location.y][location.x], 0)) reachedSnake = true; var delta = new Point; - let connection = this.path[this.path.length - 1]; - delta.x = location.x - connection.x; - delta.y = location.y - connection.y; + delta = location.subtract(this.path[this.path.length - 1]); if ((Math.abs(delta.x) + Math.abs(delta.y)) === 1) this.path.push(location); } @@ -182,95 +241,51 @@ class Bot { 4 = down */ nextMove() { - var next: Point = this.path.pop() as Point; - var head: Point = snake.head; - var delta = new Point(0, 0); - delta = next.subtract(head); + var next: Point = new Point; + next.copy(this.path.pop()); + var delta = new Point; + delta = next.subtract(snake.head); if (delta.x > 1) { - delta.x = 1; - console.log("[ERR] delta.x > 1, clamping"); + console.log("[ERR] delta.x > 1"); } else if (delta.x < -1) { - delta.x = -1; - console.log("[ERR] delta.x < 1, clamping"); + console.log("[ERR] delta.x < 1"); } if (delta.y > 1) { - delta.y = 1; - console.log("[ERR] delta.y > 1, clamping"); + console.log("[ERR] delta.y > 1"); } else if (delta.y < -1) { - delta.y = -1; - console.log("[ERR] delta.y < 1, clamping"); + console.log("[ERR] delta.y < 1"); } - return delta; + return next; } autoplay() { - if (this.path.length === 0) + if (this.path.length === 0) { this.bfs(); this.trim(); this.unvisit(); + } return this.nextMove(); - /* - let delta = this.headPos - this.path.pop(); - if (delta.x > 0) - return 0; - if (delta.y > 0) - return 1; - if (delta.x < 0) - return 2; - if (delta.y < 0) - return 4; - return 0; // Safety guard if above doesn't return - */ } } const snake: SnakeCore = new SnakeCore(); // Singleton for snake game const bot: Bot = new Bot(); // Singleton for bot playing +// game loop function snakeloop() { - snake.context.clearRect(0, 0, snake.canvas.width, snake.canvas.height); // Reset of needed if (snake.gameover) snake.reset(); // Input bot.autoplay(); - - // Move snake - // TODO: Fix teleporting snake - let next = bot.nextMove().add(snake.head); - if (next.x < 0 || next.x > snake.width || next.y < 0 || next.y > snake.height) - snake.gameover = true; - if (isBitSet(snake.board[next.y][next.x], 0) && (snake.body.length > 1)) - snake.gameover = true; // Game should end (Snake touching snake) - snake.board[next.y][next.x] = bitSet(snake.board[next.y][next.x], 0); - snake.body.push(next); - if (!isBitSet(snake.board[next.y][next.x], 1)) { - let old: Point = snake.body.shift() as Point; - snake.board[old.y][old.x] = bitClear(snake.board[old.y][old.x], 0); - } else { - snake.board[next.y][next.x] = bitClear(snake.board[next.y][next.x], 1); - snake.foodAte = true; - while (bot.path.length > 0) - bot.path.pop(); - } + snake.simulate(); // Regenerate food if needed snake.foodRegen(); - // Draw game - for (let i = 0; i < snake.height; i++) { - for (let j = 0; j < snake.width; j++) { - if (isBitSet(snake.board[i][j], 0)) - snake.context.fillStyle = "green"; - else if (isBitSet(snake.board[i][j], 1)) - snake.context.fillStyle = "red"; - else - snake.context.fillStyle = "black"; - snake.context.fillRect(j * snake.grid, i * snake.grid, snake.grid, snake.grid); - } - } + snake.draw(); } // start the game -setInterval(snakeloop, snake.speed); +setInterval(snakeloop, snake.timeout); From 8e626448a2079123749298e4c1e1c47ba153bf4e Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Sun, 1 Sep 2024 05:05:49 -0500 Subject: [PATCH 07/35] snake: fix snake body skipping placement half the time --- src/snake.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/snake.ts b/src/snake.ts index d5781a5..794528c 100644 --- a/src/snake.ts +++ b/src/snake.ts @@ -259,12 +259,11 @@ class Bot { } autoplay() { - if (this.path.length === 0) { - this.bfs(); - this.trim(); - this.unvisit(); - } - return this.nextMove(); + if (this.path.length > 0) + return; + this.bfs(); + this.trim(); + this.unvisit(); } } @@ -276,6 +275,7 @@ function snakeloop() { // Reset of needed if (snake.gameover) snake.reset(); + // Input bot.autoplay(); From ceeb1f552b6e46d90aa545e5def94d439636b598 Mon Sep 17 00:00:00 2001 From: Trimutex Date: Tue, 17 Sep 2024 02:30:55 -0500 Subject: [PATCH 08/35] docker: add initial Dockerfile --- Dockerfile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8902d05 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM node:14-alpine + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +RUN npm run build + +EXPOSE 3466 + +CMD ["npm", "start"] From 10db37262c48ee130ba6ffdd5a150e67001ea9f7 Mon Sep 17 00:00:00 2001 From: Trimutex Date: Tue, 17 Sep 2024 02:31:19 -0500 Subject: [PATCH 09/35] jenkins: add initial Jenkinsfile --- Jenkinsfile | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..4059131 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,20 @@ +pipeline { + agent any + stages { + stage('Checkout') { + steps { + checkout scm + } + } + stage('Build') { + steps { + script { + docker.build('test.trianta.dev:latest') + } + } + } + stage('Deploy') { + sh 'docker run -p 3466:3466 test.trianta.dev' + } + } +} From 4f41b247babe8b95f70352e72efb34fecc26e174 Mon Sep 17 00:00:00 2001 From: Trimutex Date: Tue, 17 Sep 2024 02:46:51 -0500 Subject: [PATCH 10/35] jenkins: fix deploy --- Jenkinsfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4059131..08a9b48 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -14,7 +14,9 @@ pipeline { } } stage('Deploy') { - sh 'docker run -p 3466:3466 test.trianta.dev' + steps { + sh 'docker run -p 3466:3466 test.trianta.dev' + } } } } From c317e7ab0880138141a95d0927ed5659e87518bd Mon Sep 17 00:00:00 2001 From: Trimutex Date: Tue, 17 Sep 2024 02:51:23 -0500 Subject: [PATCH 11/35] npm: add build script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index e8ba880..51f85b2 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "My personal website", "main": "index.html", "scripts": { + "build": "tsc", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { From 08645727a854a6ede654054f826ba74e6d5a00a5 Mon Sep 17 00:00:00 2001 From: Trimutex Date: Tue, 17 Sep 2024 02:53:37 -0500 Subject: [PATCH 12/35] docker: remove start script --- Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8902d05..43addd1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,5 +11,3 @@ COPY . . RUN npm run build EXPOSE 3466 - -CMD ["npm", "start"] From b8198afd257e0f1f6cd6f73577ce6e27026e0729 Mon Sep 17 00:00:00 2001 From: Trimutex Date: Tue, 17 Sep 2024 14:51:59 -0500 Subject: [PATCH 13/35] dockerfile: use nginx to host static site --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 43addd1..3b4961f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:14-alpine +FROM nginx:alpine WORKDIR /app @@ -6,7 +6,7 @@ COPY package*.json ./ RUN npm install -COPY . . +COPY . /usr/share/nginx/html RUN npm run build From 4f6fbc41966d23329aed60759427043089efee2c Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:40:58 -0500 Subject: [PATCH 14/35] docker: use npm for Typescript stuff --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3b4961f..bd10721 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,14 @@ FROM nginx:alpine +RUN apt-get update && apt-get install -y nodejs npm + WORKDIR /app COPY package*.json ./ RUN npm install -COPY . /usr/share/nginx/html +COPY . . RUN npm run build From 0e34226b432e3e97e1a1237939c839b86d01bd6b Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:43:39 -0500 Subject: [PATCH 15/35] docker: use base image with apt --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bd10721..5d6cffd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM nginx:alpine +FROM nginx:latest RUN apt-get update && apt-get install -y nodejs npm From e0c09898aee154846ea39beeb56aeff03e15d2f6 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:03:13 -0500 Subject: [PATCH 16/35] jenkins: detach container on deploy --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 08a9b48..88da48f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -15,7 +15,7 @@ pipeline { } stage('Deploy') { steps { - sh 'docker run -p 3466:3466 test.trianta.dev' + sh 'docker run -d -p 3466:3466 test.trianta.dev' } } } From 98149cae073616997f51c1a4e21691fc6b9bb684 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:09:54 -0500 Subject: [PATCH 17/35] docker: use nginx internal port --- Dockerfile | 2 +- Jenkinsfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5d6cffd..685cc12 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,4 +12,4 @@ COPY . . RUN npm run build -EXPOSE 3466 +EXPOSE 80 diff --git a/Jenkinsfile b/Jenkinsfile index 88da48f..237737c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -15,7 +15,7 @@ pipeline { } stage('Deploy') { steps { - sh 'docker run -d -p 3466:3466 test.trianta.dev' + sh 'docker run -d -p 3466:80 test.trianta.dev' } } } From bda79f51a61a5b549f02fa112d9775e26ed39125 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:14:33 -0500 Subject: [PATCH 18/35] jenkins: add name to container on deploy --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 237737c..52c5980 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -15,7 +15,7 @@ pipeline { } stage('Deploy') { steps { - sh 'docker run -d -p 3466:80 test.trianta.dev' + sh 'docker run -d -p 3466:80 --name test test.trianta.dev' } } } From 3641cfd836cde4859f83c9eb16327e2cc7b1ed5e Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:19:15 -0500 Subject: [PATCH 19/35] docker: deploy website to nginx dir --- Dockerfile | 2 +- Jenkinsfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 685cc12..d350201 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ COPY package*.json ./ RUN npm install -COPY . . +COPY . /usr/share/nginx/html RUN npm run build diff --git a/Jenkinsfile b/Jenkinsfile index 52c5980..1a2205a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -15,7 +15,7 @@ pipeline { } stage('Deploy') { steps { - sh 'docker run -d -p 3466:80 --name test test.trianta.dev' + sh 'docker run -d -p 3466:80 --name test test.trianta.dev:latest' } } } From 477ce1461e1ebc107e8d38b3995b58eac8193a3d Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:20:32 -0500 Subject: [PATCH 20/35] docker: build before deploy --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index d350201..55050ab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,8 +8,9 @@ COPY package*.json ./ RUN npm install -COPY . /usr/share/nginx/html - RUN npm run build +COPY . /usr/share/nginx/html + + EXPOSE 80 From 2967663a82ef38195126222e55f0457ee705f7e5 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:49:49 -0500 Subject: [PATCH 21/35] docker: correctly set up image --- Dockerfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 55050ab..c4afa94 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,16 @@ COPY package*.json ./ RUN npm install +COPY . . + RUN npm run build -COPY . /usr/share/nginx/html +WORKDIR /usr/share/nginx/html +COPY index.html . +RUN mkdir -p /usr/share/nginx/html/src +COPY src/*.css ./src + +RUN cp /app/build/* ./src EXPOSE 80 From de5f4c5eaf25132378d0e0e45dc6f58280970393 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:03:26 -0500 Subject: [PATCH 22/35] docker: fix directories when in container --- Dockerfile | 6 +++--- index.html | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index c4afa94..7d7e588 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,9 +15,9 @@ RUN npm run build WORKDIR /usr/share/nginx/html COPY index.html . -RUN mkdir -p /usr/share/nginx/html/src -COPY src/*.css ./src +RUN mkdir -p /usr/share/nginx/html/public +COPY src/*.css ./public -RUN cp /app/build/* ./src +RUN cp /app/build/* ./public EXPOSE 80 diff --git a/index.html b/index.html index 93ab29a..0eb4389 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ Trianta - +