rot-js
Version:
A roguelike toolkit in JavaScript
107 lines (106 loc) • 3.26 kB
JavaScript
import Map from "./map.js";
import RNG from "../rng.js";
/**
* Icey's Maze generator
* See http://roguebasin.com/index.php/Simple_maze for explanation
*/
export default class IceyMaze extends Map {
constructor(width, height, regularity = 0) {
super(width, height);
this._regularity = regularity;
this._map = [];
}
create(callback) {
let width = this._width;
let height = this._height;
let map = this._fillMap(1);
width -= (width % 2 ? 1 : 2);
height -= (height % 2 ? 1 : 2);
let cx = 0;
let cy = 0;
let nx = 0;
let ny = 0;
let done = 0;
let blocked = false;
let dirs = [
[0, 0],
[0, 0],
[0, 0],
[0, 0]
];
do {
cx = 1 + 2 * Math.floor(RNG.getUniform() * (width - 1) / 2);
cy = 1 + 2 * Math.floor(RNG.getUniform() * (height - 1) / 2);
if (!done) {
map[cx][cy] = 0;
}
if (!map[cx][cy]) {
this._randomize(dirs);
do {
if (Math.floor(RNG.getUniform() * (this._regularity + 1)) == 0) {
this._randomize(dirs);
}
blocked = true;
for (let i = 0; i < 4; i++) {
nx = cx + dirs[i][0] * 2;
ny = cy + dirs[i][1] * 2;
if (this._isFree(map, nx, ny, width, height)) {
map[nx][ny] = 0;
map[cx + dirs[i][0]][cy + dirs[i][1]] = 0;
cx = nx;
cy = ny;
blocked = false;
done++;
break;
}
}
} while (!blocked);
}
} while (done + 1 < width * height / 4);
for (let i = 0; i < this._width; i++) {
for (let j = 0; j < this._height; j++) {
callback(i, j, map[i][j]);
}
}
this._map = [];
return this;
}
_randomize(dirs) {
for (let i = 0; i < 4; i++) {
dirs[i][0] = 0;
dirs[i][1] = 0;
}
switch (Math.floor(RNG.getUniform() * 4)) {
case 0:
dirs[0][0] = -1;
dirs[1][0] = 1;
dirs[2][1] = -1;
dirs[3][1] = 1;
break;
case 1:
dirs[3][0] = -1;
dirs[2][0] = 1;
dirs[1][1] = -1;
dirs[0][1] = 1;
break;
case 2:
dirs[2][0] = -1;
dirs[3][0] = 1;
dirs[0][1] = -1;
dirs[1][1] = 1;
break;
case 3:
dirs[1][0] = -1;
dirs[0][0] = 1;
dirs[3][1] = -1;
dirs[2][1] = 1;
break;
}
}
_isFree(map, x, y, width, height) {
if (x < 1 || y < 1 || x >= width || y >= height) {
return false;
}
return map[x][y];
}
}