Skip to content

Instantly share code, notes, and snippets.

@hyakugei
Created March 14, 2013 07:36
Show Gist options
  • Save hyakugei/5159534 to your computer and use it in GitHub Desktop.
Save hyakugei/5159534 to your computer and use it in GitHub Desktop.
Following the rules (more or less) for the original Rogue map-generation algorithm, i made this addition to the rot.js lib. Please note, this is a early, ugly, bit of code. But it works. And makes cool dungeons!
ROT.Map.Classic = function(width, height, options) {
ROT.Map.call(this, width, height);
var getRoomSizes = function(size, cells)
{
var max = Math.floor((size/cells) * 0.8);
var min = Math.floor((size/cells) * 0.25);
if(min < 2) min = 2;
if(max < 2) min = 2;
return [min, max];
}
this._options = {
cellWidth: 3,
cellHeight: 3
}
for (var p in options) { this._options[p] = options[p]; }
/*
Set the room sizes according to the over-all width of the map,
and the cell sizes.
*/
if(!this._options.hasOwnProperty("roomWidth"))
{
this._options["roomWidth"] = getRoomSizes(width, this._options["cellWidth"]);
}
if(!this._options.hasOwnProperty["roomHeight"])
{
this._options["roomHeight"] = getRoomSizes(height, this._options["cellHeight"]);
}
this._map = this._fillMap(0);
console.log("Classic create. ");
}
ROT.Map.Classic.extend(ROT.Map);
ROT.Map.Classic.prototype.create = function(callback) {
var w = this._width;
var h = this._height;
var cw = this._options["cellWidth"];
var ch = this._options["cellHeight"];
var cwp = Math.floor(w/cw); // number of units/pixels in each cell width
var chp = Math.floor(h/ch); // number of units/pixels in each cell height
var cgx = 0;
var cgy = 0;
var connectedCells = [];
var map = [];
var roomSizes = [];
var rooms = [];
var room;
var connection;
var xOffset;
var yOffset;
var wall;
var connectingRoom;
var otherRoom;
var otherWall;
var wallx;
var wally;
// room.x
// room.y
// room.width
// room.heigh
// room.connections = [ [x,y], [x,y] ]
var dir = {};
dir[0] = [0,1];
dir[1] = [1,1];
dir[2] = [1,0];
dir[3] = [1,-1];
dir[4] = [0, -1];
dir[5] = [-1,-1];
dir[6] = [-1,0];
dir[7] = [-1,-1];
// create map
for(var i = 0; i < w; i++)
{
map.push([]);
for(var j = 0; j < h; j++)
{
map[i].push(1);
}
}
// create "grid"
var grid = [];
for(var i = 0; i < cw; i++)
{
//grid.push([]);
//roomSizes.push([]);
rooms.push([]);
for(var j = 0; j < ch; j++)
{
//grid[i].push(false);
//roomSizes[i].push([0,0]);
rooms[i].push({"x":0, "y":0, "width":0, "height":0, "connections":[], "cellx":i, "celly":j});
}
}
console.log(rooms);
//pick random starting grid
//var currentGrid = ROT.RNG.getRandomInt(1, (cw * ch)) - 1;
//console.log("First grid: " + currentGrid);
cgx = ROT.RNG.getRandomInt(0, cw-1);
cgy = ROT.RNG.getRandomInt(0, ch-1);
//grid[cgx][cgy] = false; // mark as connected;
//connectedCells.push([cgx,cgy]);
var idx;
var ncgx;
var ncgy;
// find unconnected neighbour cells
do
{
//var dirToCheck = [0,1,2,3,4,5,6,7];
var dirToCheck = [0,2,4,6];
dirToCheck = dirToCheck.randomize();
do
{
var found = false;
idx = dirToCheck.pop();
ncgx = cgx + dir[idx][0];
ncgy = cgy + dir[idx][1];
if(ncgx < 0 || ncgx >= cw) continue;
if(ncgy < 0 || ncgy >= ch) continue;
room = rooms[cgx][cgy];
if(room["connections"].length > 0)
{
if(room["connections"][0][0] == ncgx &&
room["connections"][0][1] == ncgy)
{
break;
}
}
otherRoom = rooms[ncgx][ncgy];
if(otherRoom["connections"].length == 0)
{
// console.log("Connecting cell:" + cgx + "," + cgy + " to " + ncgx + "," + ncgy);
// set this as the current cell.
//grid[ncgx][ncgy] = [cgx, cgy];
otherRoom["connections"].push([cgx,cgy]);
connectedCells.push([ncgx, ncgy]);
cgx = ncgx;
cgy = ncgy;
found = true;
}
}while(dirToCheck.length > 0 && found == false)
}while(dirToCheck.length > 0)
// console.log("Now checking for unconnected cells");
//While there are unconnected rooms, try to connect them to a random connected neighbor (if a room has no connected neighbors yet, just keep cycling, you'll fill out to it eventually).
var randomConnectedCell;
connectedCells = connectedCells.randomize();
for(var i = 0; i < cw; i++)
{
for(var j = 0; j < ch; j++)
{
room = rooms[i][j];
if(room["connections"].length == 0)
{
var directions = [0,2,4,6];
directions = directions.randomize();
var validRoom = false;
do
{
var dirIdx = directions.pop();
var newI = i + dir[dirIdx][0];
var newJ = j + dir[dirIdx][1];
if(newI < 0 || newI >= cw ||
newJ < 0 || newJ >= ch)
{
continue;
}
otherRoom = rooms[newI][newJ];
validRoom = true;
if(otherRoom["connections"].length == 0)
{
break;
}
for(var k = 0; k < otherRoom["connections"].length; k++)
{
if(otherRoom["connections"][k][0] == i &&
otherRoom["connections"][k][1] == j)
{
validRoom = false;
break;
}
}
if(validRoom) break;
}while(directions.length)
if(validRoom)
{
room["connections"].push( [otherRoom["cellx"], otherRoom["celly"]] );
}
else
{
console.log("-- Unable to connect room.");
}
}
}
}
//Make 0 or more random connections to taste; I find rnd(grid_width) random connections looks good.
// later
// Create Rooms
var roomw;
var roomh;
var roomWidth = this._options["roomWidth"];
var roomHeight = this._options["roomHeight"];
var sx;
var sy;
var tx;
var ty;
for(var i = 0; i < cw; i++)
{
for(var j = 0; j < ch; j++)
{
sx = cwp * i;
sy = chp * j;
if(sx == 0) sx = 1;
if(sy == 0) sy = 1;
roomw = ROT.RNG.getRandomInt(roomWidth[0], roomWidth[1]);
roomh = ROT.RNG.getRandomInt(roomHeight[0], roomHeight[1]);
if(j > 0)
{
otherRoom = rooms[i][j-1];
while(sy - (otherRoom["y"] + otherRoom["height"] ) < 3)
{
sy++;
}
}
if(i > 0)
{
otherRoom = rooms[i-1][j];
while(sx - (otherRoom["x"] + otherRoom["width"]) < 3)
{
sx++;
}
}
var sxOffset = Math.round(ROT.RNG.getRandomInt(0, cwp-roomw)/2);
var syOffset = Math.round(ROT.RNG.getRandomInt(0, chp-roomh)/2);
while(sx + sxOffset + roomw >= w) {
if(sxOffset)
{
sxOffset--;
}
else
{
roomw--;
}
}
while(sy + syOffset + roomh >= h) {
if(syOffset)
{
syOffset--;
}
else
{
roomh--;
}
}
sx = sx + sxOffset;
sy = sy + syOffset;
rooms[i][j]["x"] = sx;
rooms[i][j]["y"] = sy;
rooms[i][j]["width"] = roomw;
rooms[i][j]["height"] = roomh;
for(var ii = sx; ii < sx + roomw; ii++)
{
for(var jj = sy; jj < sy + roomh; jj++)
{
map[ii][jj] = 0;
}
}
}
}
// Draw Corridors between connected rooms
for(var i = 0; i < cw; i++)
{
for(var j = 0; j < ch; j++)
{
room = rooms[i][j];
//console.log(room);
for(var k = 0; k < room["connections"].length; k++)
{
connection = room["connections"][k]; // this is a 2 item array.
// console.log(connection);
otherRoom = rooms[connection[0]][connection[1]];
// figure out what wall our corridor will start one.
// figure out what wall our corridor will end on.
if(otherRoom["cellx"] > room["cellx"] )
{
wall = 2;
otherWall = 4;
}
else if(otherRoom["cellx"] < room["cellx"] )
{
wall = 4;
otherWall = 2;
}
else if(otherRoom["celly"] > room["celly"])
{
wall = 3;
otherWall = 1;
}
else if(otherRoom["celly"] < room["celly"])
{
wall = 1;
otherWall = 3;
}
var getWallPosition = function(aRoom, aDirection)
{
var rx;
var ry;
var door;
if(aDirection == 1 || aDirection == 3)
{
rx = ROT.RNG.getRandomInt(aRoom["x"] + 1, aRoom["x"] + aRoom["width"] - 2);
if(aDirection == 1)
{
ry = aRoom["y"] - 2;
door = ry + 1;
}
else
{
ry = aRoom["y"] + aRoom["height"] + 1;
door = ry -1;
}
map[rx][door] = 0;
}
else if(aDirection == 2 || aDirection == 4)
{
ry = ROT.RNG.getRandomInt(aRoom["y"] + 1, aRoom["y"] + aRoom["height"] - 2);
if(aDirection == 2)
{
rx = aRoom["x"] + aRoom["width"] + 1;
door = rx - 1;
}
else
{
rx = aRoom["x"] - 2;
door = rx + 1;
}
map[door][ry] = 0;
}
return [rx, ry];
}
var drawCorridore = function(startPosition, endPosition)
{
//console.log("drawCorridore " );
//console.log(startPosition[0] + "," + startPosition[1]);
//console.log(endPosition[0] + "," + endPosition[1]);
xOffset = endPosition[0] - startPosition[0];
yOffset = endPosition[1] - startPosition[1];
var xCount = 0;
var yCount = 0;
var counter = 0;
var tx;
var ty;
var path = [];
if(xOffset != 0)
xCount = xOffset > 0 ? 1 : -1;
if(yOffset != 0)
yCount = yOffset > 0 ? 1 : -1;
map[startPosition[0]][startPosition[1]] = 0;
map[endPosition[0]][endPosition[1]] = 0;
while(xOffset != 0 || yOffset != 0)
{
if(xOffset != 0 && counter == 0)
{
counter = 1;
xOffset -= xCount;
}
else if(yOffset != 0 && counter == 1)
{
counter = 0;
yOffset -= yCount;
}
if(xOffset == 0)
{
counter = 1;
}
if(yOffset == 0)
{
counter = 0;
}
tx = endPosition[0] - xOffset;
ty = endPosition[1] - yOffset;
map[tx][ty] = 0;
//map[tx-xCount][ty] = 0;
}
}
//console.log("dir: " + wall + " wall 1: " + getWallPosition(room, wall) + " dir " + otherWall + " wall 2: " + getWallPosition( otherRoom, otherWall));
drawCorridore(getWallPosition(room, wall), getWallPosition(otherRoom, otherWall));
}
}
}
if(callback)
{
for(var i = 0; i < w; i++)
{
for(var j = 0; j < h; j++)
{
callback(i, j, map[i][j]);
}
}
}
return this;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment