Spaces:
Running
Running
File size: 8,217 Bytes
30c32c8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
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; |