From 5fbe9b29ff2451f49a4e34b2daac6dac00b11d15 Mon Sep 17 00:00:00 2001 From: Ben Burlingham Date: Sat, 18 Jul 2020 10:05:38 -0700 Subject: [PATCH] Walls placement algorithm overhaul. --- README.md | 7 ++- server/ricochet.js | 110 ++++++++++++++++++++++++++------------------- 2 files changed, 69 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 97f9d3e..d257a13 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,9 @@ A victory state can be stored by taking a snapshot of the current stack. Icons from [https://game-icons.net](https://game-icons.net) ## TODO -- walls and winstate algorithm - tutorial -- restore name prompt1 +- restore name prompt +- home button + +- reset robots? on server reset...avoid multiple shadows +- Fix 9 things diff --git a/server/ricochet.js b/server/ricochet.js index e70685d..9ad841d 100644 --- a/server/ricochet.js +++ b/server/ricochet.js @@ -134,63 +134,81 @@ Ricochet.prototype.freshRobots = function() { }; Ricochet.prototype.freshWalls = function() { - // Edge IDs are of the form [i1-j1-i2-j2]. Top left is 0, 0. - - // Leave here for testing. - // return [ - // "1-9-1-10", - // "9-1-10-1", - // "9-19-10-19", - // "19-9-19-10" - // ]; - - // console.log("Generating walls."); - - // Squares per side has quadratic relationship with wall/corner requirements. - const numberOfCorners = Math.ceil(Math.pow((this.squaresPerSide / 10), 2)); - const numberOfWalls = Math.ceil(Math.pow((this.squaresPerSide / 5), 2)); - - const edges = []; - - // DO NUMBER OF CORNERS FIRST AFTER TESTING - for (let n = 0; n < numberOfWalls; n++) { - const { i: ri, j: rj } = this.randomSquare(); - - const isHorizontal = Math.random() < 0.5; - const isBackward = Math.random() < 0.5; + // Corner count relates quadratically to squares per side. + const numberOfCorners = Math.ceil(Math.pow((this.squaresPerSide / 4), 2)); + const corners = []; + let shortCircuitCounter = 0; + + while (corners.length < numberOfCorners && shortCircuitCounter < numberOfCorners * 5) { + const { i, j } = this.randomSquare(); + + const isTooClose = corners.reduce((acc, v) => { + const delta = Math.abs(v.i - i) + Math.abs(v.j - j); + + return acc || (delta < 3); + }, false); + + if (isTooClose === false) { + corners.push({ i, j }); + } + } - let i1, j1, i2, j2; + // Edge IDs are of the form [i1-j1-i2-j2]. Top left is 0, 0. + const horizontalEdges = corners.map(({ i, j }) => { + const isLeftward = i > 0 && i < this.squaresPerSide && (Math.random() < 0.5); + const i1 = isLeftward ? i - 1 : i; + const i2 = isLeftward ? i : i + 1; + + return { i1, j1: j, i2, j2: j}; + }); + + const verticalEdges = corners.map(({ i, j }) => { + const isUpward = j > 0 && j < this.squaresPerSide && (Math.random() < 0.5); + const j1 = isUpward ? j - 1 : j; + const j2 = isUpward ? j : j + 1; + + return { i1: i, j1, i2: i, j2 }; + }); + + const edges = horizontalEdges.concat(verticalEdges); + + return edges.reduce((acc, { i1, j1, i2, j2 }) => { + // Remove walls along all edges + const onLeft = (i1 === 0 && i2 === 0); + const onRight = (i1 === this.squaresPerSide && i2 === this.squaresPerSide); + const onTop = (j1 === 0 && j2 === 0); + const onBottom = (j1 === this.squaresPerSide && j2 === this.squaresPerSide); + + if (onLeft || onRight || onTop || onBottom) { + return acc; + } - if (isHorizontal) { - i1 = isBackward ? ri - 1 : ri; - i2 = isBackward ? ri : ri + 1; + // Remove some walls randomly + if (Math.random() < 0.3) { + return acc; + } - j1 = rj; - j2 = rj; - } else { - i1 = ri; - i2 = ri; + return acc.concat(`${i1}-${j1}-${i2}-${j2}`); + }, []); +}; - j1 = isBackward ? rj - 1 : rj; - j2 = isBackward ? rj : rj + 1; +Ricochet.prototype.freshObjective = function() { + const getRandomWall = () => { + if (!this.walls.length) { + this.randomUnoccupiedSquare(); } - const edge = `${i1}-${j1}-${i2}-${j2}`; + const wall = this.walls[Math.floor((Math.random() * this.walls.length))]; - if (edges.includes(edge)) { - n--; - } else { - edges.push(edge); - } - } + const [i1, j1, i2, j2] = wall.split('-'); - return edges; -}; + return (Math.random() < 0.5) ? { i: i1, j: j1 } : { i: i2, j: j2 }; + }; -Ricochet.prototype.freshObjective = function() { const rand = Math.floor(Math.random() * this.robotIds.length); const id = this.robotIds[rand]; - const { i, j } = this.randomUnoccupiedSquare(); + + const { i, j } = getRandomWall(); return { i,