export function deriveWallLocations(tiles) { const verticalWalls = {}; const horizontalWalls = {}; // Determine wall segments tiles.forEach(tile => { const x = tile.positionX, y = tile.positionY; for (let dX = -1; dX <= 1; dX++) { for (let dY = -1; dY <= 1; dY++) { if (Math.abs(dX) === Math.abs(dY)) { continue; } let doInsert = true; tiles.forEach(otherTile => { if (otherTile.positionX === x + dX && otherTile.positionY === y + dY) { doInsert = false; } }); if (!doInsert) { continue; } if (dX === -1) { if (verticalWalls[x] === undefined) { verticalWalls[x] = []; } if (verticalWalls[x].indexOf(y) === -1) { verticalWalls[x].push(y); } } else if (dX === 1) { if (verticalWalls[x + 1] === undefined) { verticalWalls[x + 1] = []; } if (verticalWalls[x + 1].indexOf(y) === -1) { verticalWalls[x + 1].push(y); } } else if (dY === -1) { if (horizontalWalls[y] === undefined) { horizontalWalls[y] = []; } if (horizontalWalls[y].indexOf(x) === -1) { horizontalWalls[y].push(x); } } else if (dY === 1) { if (horizontalWalls[y + 1] === undefined) { horizontalWalls[y + 1] = []; } if (horizontalWalls[y + 1].indexOf(x) === -1) { horizontalWalls[y + 1].push(x); } } } } }); // Merge walls into longer segments const result = []; const walls = [verticalWalls, horizontalWalls]; for (let i = 0; i < 2; i++) { const wallList = walls[i]; for (let a in wallList) { a = parseInt(a, 10); wallList[a].sort((a, b) => { return a - b; }); let startPos = wallList[a][0]; const isHorizontal = i === 1; if (wallList[a].length === 1) { const startPosX = isHorizontal ? startPos : a; const startPosY = isHorizontal ? a : startPos; result.push({ startPosX, startPosY, isHorizontal, length: 1 }); } else { let consecutiveCount = 1; for (let b = 0; b < wallList[a].length - 1; b++) { if (b + 1 === wallList[a].length - 1) { if (wallList[a][b + 1] - wallList[a][b] > 1) { const startPosX = isHorizontal ? startPos : a; const startPosY = isHorizontal ? a : startPos; result.push({ startPosX, startPosY, isHorizontal, length: consecutiveCount }); consecutiveCount = 0; startPos = wallList[a][b + 1]; } const startPosX = isHorizontal ? startPos : a; const startPosY = isHorizontal ? a : startPos; result.push({ startPosX, startPosY, isHorizontal, length: consecutiveCount + 1 }); break; } else if (wallList[a][b + 1] - wallList[a][b] > 1) { const startPosX = isHorizontal ? startPos : a; const startPosY = isHorizontal ? a : startPos; result.push({ startPosX, startPosY, isHorizontal, length: consecutiveCount }); startPos = wallList[a][b + 1]; consecutiveCount = 0; } consecutiveCount++; } } } } return result; } export function deriveValidNextTilePositions(rooms, selectedTiles) { const result = [], newPosition = {x: 0, y: 0}; let isSurroundingTile; selectedTiles.forEach((tile) => { const x = tile.positionX; const y = tile.positionY; result.push({x, y}); for (let dX = -1; dX <= 1; dX++) { for (let dY = -1; dY <= 1; dY++) { if (Math.abs(dX) === Math.abs(dY)) { continue; } newPosition.x = x + dX; newPosition.y = y + dY; isSurroundingTile = true; for (let index in selectedTiles) { if (selectedTiles[index].positionX === newPosition.x && selectedTiles[index].positionY === newPosition.y) { isSurroundingTile = false; break; } } if (isSurroundingTile && findPositionInRooms(rooms, newPosition.x, newPosition.y) === -1) { result.push({x: newPosition.x, y: newPosition.y}); } } } }); return result; } export function findPositionInPositions(positions, positionX, positionY) { for (let i = 0; i < positions.length; i++) { const position = positions[i]; if (positionX === position.x && positionY === position.y) { return i; } } return -1; } export function findPositionInRooms(rooms, positionX, positionY) { for (let i = 0; i < rooms.length; i++) { const room = rooms[i]; if (findPositionInTiles(room.tiles, positionX, positionY) !== -1) { return i; } } return -1; } function findPositionInTiles(tiles, positionX, positionY) { let index = -1; for (let i = 0; i < tiles.length; i++) { const tile = tiles[i]; if (positionX === tile.positionX && positionY === tile.positionY) { index = i; break; } } return index; } export function findTileWithPosition(tiles, positionX, positionY) { for (let i = 0; i < tiles.length; i++) { if (tiles[i].positionX === positionX && tiles[i].positionY === positionY) { return tiles[i]; } } return null; } export function calculateRoomListBounds(rooms) { const min = {x: Number.MAX_VALUE, y: Number.MAX_VALUE}; const max = {x: -1, y: -1}; rooms.forEach((room) => { room.tiles.forEach((tile) => { if (tile.positionX < min.x) { min.x = tile.positionX; } if (tile.positionY < min.y) { min.y = tile.positionY; } if (tile.positionX > max.x) { max.x = tile.positionX; } if (tile.positionY > max.y) { max.y = tile.positionY; } }); }); max.x++; max.y++; const center = { x: min.x + (max.x - min.x) / 2.0, y: min.y + (max.y - min.y) / 2.0 }; return {min, center, max}; }