diff --git a/assets/scripts/nethack/dungeon.js b/assets/scripts/nethack/dungeon.js index 75d06e0..7277d9a 100644 --- a/assets/scripts/nethack/dungeon.js +++ b/assets/scripts/nethack/dungeon.js @@ -1,6 +1,5 @@ -const DEBUG = true; const NUMBER_OF_ROOMS = 12; -const TUNNEL_PASSES = 2; +const TUNNEL_PASSES = 3; class Cell { static CORRIDOR = "#"; @@ -92,6 +91,18 @@ class Rect { get height() { return this.size.height; } get area() { return this.size.width * this.size.height; } + *xCoordinates() { + for (let x = this.minX; x <= this.maxX; x++) { + yield x; + } + } + + *yCoordinates() { + for (let y = this.minY; y <= this.maxY; y++) { + yield y; + } + } + insetRect(inset) { const twiceInset = 2 * inset; @@ -255,13 +266,6 @@ class NRandomRoomsGenerator { room.transformCellAt(point, cell); cell.characterColor = p.color(255); - - if (DEBUG) { - if (x == room.minX + 1 && y == room.minY + 1) { - cell.character = (i % 10).toString(); - cell.characterColor = p.color(255, 128, 255); - } - } } } } @@ -361,8 +365,15 @@ class TunnelGenerator { let toRoom = rooms[i + offset]; let [fromPoint, toPoint] = this.#findPointFromRoomToRoom(fromRoom, toRoom); + if (!fromPoint || !toPoint) { + continue; + } for (let neighbor of fromPoint.neighbors()) { + if (!this.#grid.pointIsInBounds(neighbor)) { + continue; + } + let cell = this.#grid.cellAt(neighbor.x, neighbor.y); if ((neighbor.x === fromPoint.x || neighbor.y === fromPoint.y) && cell.canBecomeDoor()) { cell.doorClosed(); @@ -375,6 +386,10 @@ class TunnelGenerator { if (successfullyFoundTargetPoint) { for (let neighbor of toPoint.neighbors()) { + if (!this.#grid.pointIsInBounds(neighbor)) { + continue; + } + let cell = this.#grid.cellAt(neighbor.x, neighbor.y); if ((neighbor.x === toPoint.x || neighbor.y === toPoint.y) && cell.canBecomeDoor()) { cell.doorClosed(); @@ -408,8 +423,6 @@ class TunnelGenerator { let curX = fromX; let curY = fromY; - console.log(`Digging a corridor from (${fromX}, ${fromY}) to (${toX}, ${toY})`); - let dx = 0; let dy = 0; @@ -424,7 +437,6 @@ class TunnelGenerator { dy = -1; } - console.log("dx, dy", dx, dy); curX -= dx; curY -= dy; @@ -512,53 +524,148 @@ class TunnelGenerator { const fromRoomBounds = fromRoom.bounds; const toRoomBounds = toRoom.bounds; + let foundFromPoint = false; + let foundToPoint = false; + let fromPoint; let toPoint; - if (fromRoomBounds.maxX < (toRoomBounds.minX - 1)) { - // fromRoom is farther left than toRoomBounds. - do { - fromPoint = new Point(fromRoomBounds.maxX, fromRoomBounds.minY + 1 + randomInt(fromRoomBounds.height - 2)); - } while (!this.#canPlaceDoorAt(fromPoint)); + if (fromRoomBounds.maxX < toRoomBounds.minX) { + // fromRoom is farther left than toRoom + + fromPoint = new Point(fromRoomBounds.maxX, fromRoomBounds.minY + 1 + randomInt(fromRoomBounds.height - 2)); + foundFromPoint = this.#canPlaceDoorAt(fromPoint); - do { - toPoint = new Point(toRoomBounds.minX, toRoomBounds.minY + 1 + randomInt(toRoomBounds.height - 2)); - } while (!this.#canPlaceDoorAt(toPoint)); + for (let y of fromRoomBounds.yCoordinates()) { + fromPoint.y = y; + foundFromPoint = this.#canPlaceDoorAt(fromPoint); + if (foundFromPoint) { + break; + } + } + + if (!foundFromPoint) { + return []; + } + + toPoint = new Point(toRoomBounds.minX, toRoomBounds.minY + 1 + randomInt(toRoomBounds.height - 2)); + foundToPoint = this.#canPlaceDoorAt(toPoint); + + for (let y of toRoomBounds.yCoordinates()) { + toPoint.y = y; + foundToPoint = this.#canPlaceDoorAt(toPoint); + if (foundToPoint) { + break; + } + } + + if (!foundToPoint) { + return []; + } fromPoint.x += 1; toPoint.x -= 1; - } else if (fromRoomBounds.minX > (toRoomBounds.maxX + 1)) { + } else if (fromRoomBounds.minX > toRoomBounds.maxX) { // fromRoom is farther right than toRoomBounds. - do { - fromPoint = new Point(toRoomBounds.maxX, toRoomBounds.minY + 1 + randomInt(toRoomBounds.height - 2)); - } while (!this.#canPlaceDoorAt(fromPoint)); - do { - toPoint = new Point(fromRoomBounds.minX, fromRoomBounds.minY + 1 + randomInt(fromRoomBounds.height - 2)); - } while (!this.#canPlaceDoorAt(toPoint)); + fromPoint = new Point(toRoomBounds.maxX, toRoomBounds.minY + 1 + randomInt(toRoomBounds.height - 2)); + foundFromPoint = this.#canPlaceDoorAt(fromPoint); + + for (let y of toRoomBounds.yCoordinates()) { + fromPoint.y = y; + foundFromPoint = this.#canPlaceDoorAt(fromPoint); + if (foundFromPoint) { + break; + } + } + + if (!foundFromPoint) { + return []; + } + + toPoint = new Point(fromRoomBounds.minX, fromRoomBounds.minY + 1 + randomInt(fromRoomBounds.height - 2)); + foundToPoint = this.#canPlaceDoorAt(toPoint); + + for (let y of fromRoomBounds.yCoordinates()) { + toPoint.y = y; + foundToPoint = this.#canPlaceDoorAt(toPoint); + if (foundToPoint) { + break; + } + } + + if (!foundToPoint) { + return []; + } fromPoint.x -= 1; toPoint.x += 1; } else if (fromRoomBounds.maxY < (toRoomBounds.minY - 1)) { // fromRoom is above toRoom - do { - fromPoint = new Point(fromRoomBounds.minX + 1 + randomInt(fromRoomBounds.width - 2), fromRoomBounds.maxY); - } while (!this.#canPlaceDoorAt(fromPoint)); - do { - toPoint = new Point(toRoomBounds.minX + 1 + randomInt(toRoomBounds.width - 2), toRoomBounds.minY); - } while (!this.#canPlaceDoorAt(toPoint)); + fromPoint = new Point(fromRoomBounds.minX + 1 + randomInt(fromRoomBounds.width - 2), fromRoomBounds.maxY); + foundFromPoint = this.#canPlaceDoorAt(fromPoint); + + for (let x of fromRoomBounds.xCoordinates()) { + fromPoint.x = x; + foundFromPoint = this.#canPlaceDoorAt(fromPoint); + if (foundFromPoint) { + break; + } + } + + if (!foundFromPoint) { + return []; + } + + toPoint = new Point(toRoomBounds.minX + 1 + randomInt(toRoomBounds.width - 2), toRoomBounds.minY); + foundToPoint = this.#canPlaceDoorAt(toPoint); + + for (let x of toRoomBounds.xCoordinates()) { + toPoint.x = x; + foundToPoint = this.#canPlaceDoorAt(toPoint); + if (foundToPoint) { + break; + } + } + + if (!foundToPoint) { + return []; + } fromPoint.y += 1; toPoint.y -= 1; } else if (fromRoomBounds.minY > (toRoomBounds.maxY + 1)) { // fromRoom is below toRoom - do { - fromPoint = new Point(toRoomBounds.minX + 1 + randomInt(toRoomBounds.width - 2), toRoomBounds.maxY); - } while (!this.#canPlaceDoorAt(fromPoint)); - do { - toPoint = new Point(fromRoomBounds.minX + 1 + randomInt(fromRoomBounds.width - 2), fromRoomBounds.minY); - } while (!this.#canPlaceDoorAt(toPoint)); + fromPoint = new Point(toRoomBounds.minX + 1 + randomInt(toRoomBounds.width - 2), toRoomBounds.maxY); + foundFromPoint = this.#canPlaceDoorAt(fromPoint); + + for (let x of toRoomBounds.xCoordinates()) { + fromPoint.x = x; + foundFromPoint = this.#canPlaceDoorAt(fromPoint); + if (foundFromPoint) { + break; + } + } + + if (!foundFromPoint) { + return []; + } + + toPoint = new Point(fromRoomBounds.minX + 1 + randomInt(fromRoomBounds.width - 2), fromRoomBounds.minY); + foundToPoint = this.#canPlaceDoorAt(toPoint); + + for (let x of fromRoomBounds.xCoordinates()) { + toPoint.x = x; + foundToPoint = this.#canPlaceDoorAt(toPoint); + if (foundToPoint) { + break; + } + } + + if (!foundToPoint) { + return []; + } fromPoint.y += 1; toPoint.y -= 1;