Spaces:
Running
Running
const Cast = require('../../util/cast'); | |
const Clone = require('../../util/clone'); | |
class Seperator { | |
static _createArrayOfLength(length, item) { | |
length = Cast.toNumber(length); | |
if (length <= 0) return []; | |
if (!isFinite(length)) return []; | |
const newArray = Array.from(Array(length).keys()).map(() => { | |
return item; | |
}); | |
return Clone.simple(newArray); | |
} | |
static _validateUnsignedInteger(int) { | |
int = Cast.toNumber(int); | |
if (int < 0) int = 0; | |
if (!isFinite(int)) int = 0; | |
return Math.round(int); | |
} | |
static _splitNumber(num) { | |
const number = Math.round(Cast.toNumber(num)); | |
if (number === 0) return [0, 0]; | |
if (!isFinite(number)) return [0, 0]; | |
return [ | |
Math.ceil(number / 2), | |
Math.floor(number / 2) | |
]; | |
} | |
/** | |
* Adds extra space in a grid so large pathers can still get around objects. | |
* @param {Grid} grid The grid that needs extra spacing | |
* @param {number} amount Amount of extra tiles you want to add on each side | |
* @returns The new grid with it's margins | |
*/ | |
static marginGrid(grid, amount) { | |
// amount must be round & not inf or less than 0 | |
amount = Seperator._validateUnsignedInteger(amount); | |
const newGrid = Clone.simple(grid); | |
// console.log(Clone.simple(newGrid), newGrid[0].length); | |
const gridLength = Seperator._validateUnsignedInteger(newGrid[0] ? newGrid[0].length : 0); | |
const fillerRow = Seperator._createArrayOfLength(gridLength, 0); | |
// add 0s to the top and bottom | |
for (let i = 0; i < amount; i++) { | |
// we need to push new copies | |
// otherwise we store the same array | |
// but in multiple indexes | |
const first = Clone.simple(fillerRow); | |
const last = Clone.simple(fillerRow); | |
newGrid.unshift(first); | |
newGrid.push(last); | |
} | |
// console.log(Clone.simple(newGrid), amount); | |
// add 0s to the individual rows to expand the sides | |
for (const row of newGrid) { | |
for (let i = 0; i < amount; i++) { | |
row.unshift(0); | |
row.push(0); | |
} | |
} | |
return newGrid; | |
} | |
/** | |
* Thickens the walls in the grid. Unlike marginGrid, this actually cuts the numbers in half properly. | |
* Odd numbers are split, see below which sides get the larger split. | |
* @param {Grid} grid The grid that needs thicker walls | |
* @param {number} width The width that will be thickened. Odd numbers will thicken the right, then the left. | |
* @param {number} height The height that will be thickened. Odd numbers will thicken the top, then the bottom. | |
* @returns The new grid with the padded walls. | |
*/ | |
static padGrid(grid, width, height) { | |
// split the width & height numbers so we can thicken the walls with them | |
// we need to subtract 1 without going negative so that wall thickness is reasonable | |
const reasonableW = Math.max(0, Cast.toNumber(width) - 1); | |
const reasonableH = Math.max(0, Cast.toNumber(height) - 1); | |
const splitW = Seperator._splitNumber(reasonableW); | |
const splitH = Seperator._splitNumber(reasonableH); | |
// we need the original grid so we dont thicken walls after we already thickened them | |
const originalGrid = Clone.simple(grid); | |
const newGrid = Clone.simple(grid); | |
// go through each row & tile of the grid | |
const idx = { | |
row: 0, | |
tile: 0 | |
} | |
for (const row of newGrid) { | |
for (const _ of row) { | |
// if not a wall, increment index & continue to next iteration | |
if (originalGrid[idx.row][idx.tile] <= 0) { | |
idx.tile++; | |
continue; | |
} | |
// console.log('can'); | |
// we are a wall, thicken | |
// thicken horizontally first as its the easiest | |
for (let i = 0; i < splitW[0]; i++) { | |
// right | |
const nextTile = idx.tile + (i + 1); | |
// dont continue if there is no next tile | |
// this can happen if we reach the boundary | |
// of the grid | |
if (typeof row[nextTile] !== 'number') continue; | |
// set next tile to a wall | |
row[nextTile] = 1; | |
} | |
for (let i = 0; i < splitW[1]; i++) { | |
// left | |
const nextTile = idx.tile - (i + 1); | |
// dont continue if there is no next tile | |
// this can happen if we reach the boundary | |
// of the grid | |
if (typeof row[nextTile] !== 'number') continue; | |
// set next tile to a wall | |
row[nextTile] = 1; | |
} | |
// thicken vertically | |
for (let i = 0; i < splitH[0]; i++) { | |
// top | |
const nextRow = idx.row - (i + 1); | |
// dont continue if there is no next row | |
// this can happen if we reach the boundary | |
// of the grid | |
if (!originalGrid[nextRow]) continue; | |
// get next row | |
const foundRow = newGrid[nextRow]; | |
// set tile to a wall | |
foundRow[idx.tile] = 1; | |
} | |
for (let i = 0; i < splitH[1]; i++) { | |
// bottom | |
const nextRow = idx.row + (i + 1); | |
// dont continue if there is no next row | |
// this can happen if we reach the boundary | |
// of the grid | |
if (!originalGrid[nextRow]) continue; | |
// get next row | |
const foundRow = newGrid[nextRow]; | |
// set tile to a wall | |
foundRow[idx.tile] = 1; | |
} | |
// if width & height are greater than 0, thicken diagonally | |
// this is the hardest one to do because we need to modify | |
// horizontal values in the vertical arrays | |
// we stack a for loop in a for loop in a for loop in a for loop | |
for (let i = 0; i < 2; i++) { | |
const isBottom = i === 1; | |
for (let j = 0; j < splitH[isBottom ? 1 : 0]; j++) { | |
// vertical | |
let nextRow = idx.row - (j + 1); | |
if (isBottom) nextRow = idx.row + (j + 1); | |
// dont continue if there is no next row | |
// this can happen if we reach the boundary | |
// of the grid | |
if (!originalGrid[nextRow]) continue; | |
// get next row | |
const foundRow = newGrid[nextRow]; | |
for (let k = 0; k < 2; k++) { | |
const isLeft = k === 1; | |
for (let l = 0; l < splitW[isLeft ? 1 : 0]; l++) { | |
// horizontal | |
let nextTile = idx.tile + (l + 1); | |
if (isLeft) nextTile = idx.tile - (l + 1); | |
// dont continue if there is no next tile | |
// this can happen if we reach the boundary | |
// of the grid | |
if (typeof foundRow[nextTile] !== 'number') continue; | |
// set next tile to a wall | |
foundRow[nextTile] = 1; | |
} | |
} | |
} | |
} | |
// increment index | |
idx.tile++; | |
} | |
// increment index and reset tile idx | |
idx.row++; | |
idx.tile = 0; | |
} | |
return newGrid; | |
} | |
} | |
module.exports = Seperator; |