rot-js
Version:
A roguelike toolkit in JavaScript
109 lines (108 loc) • 3.4 kB
JavaScript
import Map from "./map.js";
import RNG from "../rng.js";
/**
* @class Recursively divided maze, http://en.wikipedia.org/wiki/Maze_generation_algorithm#Recursive_division_method
* @augments ROT.Map
*/
export default class DividedMaze extends Map {
constructor() {
super(...arguments);
this._stack = [];
this._map = [];
}
create(callback) {
let w = this._width;
let h = this._height;
this._map = [];
for (let i = 0; i < w; i++) {
this._map.push([]);
for (let j = 0; j < h; j++) {
let border = (i == 0 || j == 0 || i + 1 == w || j + 1 == h);
this._map[i].push(border ? 1 : 0);
}
}
this._stack = [
[1, 1, w - 2, h - 2]
];
this._process();
for (let i = 0; i < w; i++) {
for (let j = 0; j < h; j++) {
callback(i, j, this._map[i][j]);
}
}
this._map = [];
return this;
}
_process() {
while (this._stack.length) {
let room = this._stack.shift(); /* [left, top, right, bottom] */
this._partitionRoom(room);
}
}
_partitionRoom(room) {
let availX = [];
let availY = [];
for (let i = room[0] + 1; i < room[2]; i++) {
let top = this._map[i][room[1] - 1];
let bottom = this._map[i][room[3] + 1];
if (top && bottom && !(i % 2)) {
availX.push(i);
}
}
for (let j = room[1] + 1; j < room[3]; j++) {
let left = this._map[room[0] - 1][j];
let right = this._map[room[2] + 1][j];
if (left && right && !(j % 2)) {
availY.push(j);
}
}
if (!availX.length || !availY.length) {
return;
}
let x = RNG.getItem(availX);
let y = RNG.getItem(availY);
this._map[x][y] = 1;
let walls = [];
let w = [];
walls.push(w); /* left part */
for (let i = room[0]; i < x; i++) {
this._map[i][y] = 1;
if (i % 2)
w.push([i, y]);
}
w = [];
walls.push(w); /* right part */
for (let i = x + 1; i <= room[2]; i++) {
this._map[i][y] = 1;
if (i % 2)
w.push([i, y]);
}
w = [];
walls.push(w); /* top part */
for (let j = room[1]; j < y; j++) {
this._map[x][j] = 1;
if (j % 2)
w.push([x, j]);
}
w = [];
walls.push(w); /* bottom part */
for (let j = y + 1; j <= room[3]; j++) {
this._map[x][j] = 1;
if (j % 2)
w.push([x, j]);
}
let solid = RNG.getItem(walls);
for (let i = 0; i < walls.length; i++) {
let w = walls[i];
if (w == solid) {
continue;
}
let hole = RNG.getItem(w);
this._map[hole[0]][hole[1]] = 0;
}
this._stack.push([room[0], room[1], x - 1, y - 1]); /* left top */
this._stack.push([x + 1, room[1], room[2], y - 1]); /* right top */
this._stack.push([room[0], y + 1, x - 1, room[3]]); /* left bottom */
this._stack.push([x + 1, y + 1, room[2], room[3]]); /* right bottom */
}
}