lychees's picture
Upload 569 files
87b3b3a
/**
* @class
* Dungeon feature; has own .create() method
*/
ROT.Map.Feature = function() {}
ROT.Map.Feature.prototype.isValid = function(canBeDugCallback) {}
ROT.Map.Feature.prototype.create = function(digCallback) {}
ROT.Map.Feature.prototype.debug = function() {}
ROT.Map.Feature.createRandomAt = function(x, y, dx, dy, options) {}
/**
* @class Room
* @augments ROT.Map.Feature
* @param {int} x1
* @param {int} y1
* @param {int} x2
* @param {int} y2
* @param {int} [doorX]
* @param {int} [doorY]
*/
ROT.Map.Feature.Room = function(x1, y1, x2, y2, doorX, doorY) {
this._x1 = x1;
this._y1 = y1;
this._x2 = x2;
this._y2 = y2;
this._doors = {};
if (arguments.length > 4) { this.addDoor(doorX, doorY); }
}
ROT.Map.Feature.Room.extend(ROT.Map.Feature);
/**
* Room of random size, with a given doors and direction
*/
ROT.Map.Feature.Room.createRandomAt = function(x, y, dx, dy, options) {
var min = options.roomWidth[0];
var max = options.roomWidth[1];
var width = min + Math.floor(ROT.RNG.getUniform()*(max-min+1));
var min = options.roomHeight[0];
var max = options.roomHeight[1];
var height = min + Math.floor(ROT.RNG.getUniform()*(max-min+1));
if (dx == 1) { /* to the right */
var y2 = y - Math.floor(ROT.RNG.getUniform() * height);
return new this(x+1, y2, x+width, y2+height-1, x, y);
}
if (dx == -1) { /* to the left */
var y2 = y - Math.floor(ROT.RNG.getUniform() * height);
return new this(x-width, y2, x-1, y2+height-1, x, y);
}
if (dy == 1) { /* to the bottom */
var x2 = x - Math.floor(ROT.RNG.getUniform() * width);
return new this(x2, y+1, x2+width-1, y+height, x, y);
}
if (dy == -1) { /* to the top */
var x2 = x - Math.floor(ROT.RNG.getUniform() * width);
return new this(x2, y-height, x2+width-1, y-1, x, y);
}
}
/**
* Room of random size, positioned around center coords
*/
ROT.Map.Feature.Room.createRandomCenter = function(cx, cy, options) {
var min = options.roomWidth[0];
var max = options.roomWidth[1];
var width = min + Math.floor(ROT.RNG.getUniform()*(max-min+1));
var min = options.roomHeight[0];
var max = options.roomHeight[1];
var height = min + Math.floor(ROT.RNG.getUniform()*(max-min+1));
var x1 = cx - Math.floor(ROT.RNG.getUniform()*width);
var y1 = cy - Math.floor(ROT.RNG.getUniform()*height);
var x2 = x1 + width - 1;
var y2 = y1 + height - 1;
return new this(x1, y1, x2, y2);
}
/**
* Room of random size within a given dimensions
*/
ROT.Map.Feature.Room.createRandom = function(availWidth, availHeight, options) {
var min = options.roomWidth[0];
var max = options.roomWidth[1];
var width = min + Math.floor(ROT.RNG.getUniform()*(max-min+1));
var min = options.roomHeight[0];
var max = options.roomHeight[1];
var height = min + Math.floor(ROT.RNG.getUniform()*(max-min+1));
var left = availWidth - width - 1;
var top = availHeight - height - 1;
var x1 = 1 + Math.floor(ROT.RNG.getUniform()*left);
var y1 = 1 + Math.floor(ROT.RNG.getUniform()*top);
var x2 = x1 + width - 1;
var y2 = y1 + height - 1;
return new this(x1, y1, x2, y2);
}
ROT.Map.Feature.Room.prototype.addDoor = function(x, y) {
this._doors[x+","+y] = 1;
}
/**
* @param {function}
*/
ROT.Map.Feature.Room.prototype.getDoors = function(callback) {
for (var key in this._doors) {
var parts = key.split(",");
callback(parseInt(parts[0]), parseInt(parts[1]));
}
}
ROT.Map.Feature.Room.prototype.clearDoors = function() {
this._doors = {};
return this;
}
ROT.Map.Feature.Room.prototype.debug = function() {
console.log("room", this._x1, this._y1, this._x2, this._y2);
}
ROT.Map.Feature.Room.prototype.isValid = function(isWallCallback, canBeDugCallback) {
var left = this._x1-1;
var right = this._x2+1;
var top = this._y1-1;
var bottom = this._y2+1;
for (var x=left; x<=right; x++) {
for (var y=top; y<=bottom; y++) {
if (x == left || x == right || y == top || y == bottom) {
if (!isWallCallback(x, y)) { return false; }
} else {
if (!canBeDugCallback(x, y)) { return false; }
}
}
}
return true;
}
/**
* @param {function} digCallback Dig callback with a signature (x, y, value). Values: 0 = empty, 1 = wall, 2 = door. Multiple doors are allowed.
*/
ROT.Map.Feature.Room.prototype.create = function(digCallback) {
var left = this._x1-1;
var right = this._x2+1;
var top = this._y1-1;
var bottom = this._y2+1;
var value = 0;
for (var x=left; x<=right; x++) {
for (var y=top; y<=bottom; y++) {
if (x+","+y in this._doors) {
value = 2;
} else if (x == left || x == right || y == top || y == bottom) {
value = 1;
} else {
value = 0;
}
digCallback(x, y, value);
}
}
}
ROT.Map.Feature.Room.prototype.getCenter = function() {
return [Math.round((this._x1 + this._x2)/2), Math.round((this._y1 + this._y2)/2)];
}
ROT.Map.Feature.Room.prototype.getLeft = function() {
return this._x1;
}
ROT.Map.Feature.Room.prototype.getRight = function() {
return this._x2;
}
ROT.Map.Feature.Room.prototype.getTop = function() {
return this._y1;
}
ROT.Map.Feature.Room.prototype.getBottom = function() {
return this._y2;
}
/**
* @class Corridor
* @augments ROT.Map.Feature
* @param {int} startX
* @param {int} startY
* @param {int} endX
* @param {int} endY
*/
ROT.Map.Feature.Corridor = function(startX, startY, endX, endY) {
this._startX = startX;
this._startY = startY;
this._endX = endX;
this._endY = endY;
this._endsWithAWall = true;
}
ROT.Map.Feature.Corridor.extend(ROT.Map.Feature);
ROT.Map.Feature.Corridor.createRandomAt = function(x, y, dx, dy, options) {
var min = options.corridorLength[0];
var max = options.corridorLength[1];
var length = min + Math.floor(ROT.RNG.getUniform()*(max-min+1));
return new this(x, y, x + dx*length, y + dy*length);
}
ROT.Map.Feature.Corridor.prototype.debug = function() {
console.log("corridor", this._startX, this._startY, this._endX, this._endY);
}
ROT.Map.Feature.Corridor.prototype.isValid = function(isWallCallback, canBeDugCallback){
var sx = this._startX;
var sy = this._startY;
var dx = this._endX-sx;
var dy = this._endY-sy;
var length = 1 + Math.max(Math.abs(dx), Math.abs(dy));
if (dx) { dx = dx/Math.abs(dx); }
if (dy) { dy = dy/Math.abs(dy); }
var nx = dy;
var ny = -dx;
var ok = true;
for (var i=0; i<length; i++) {
var x = sx + i*dx;
var y = sy + i*dy;
if (!canBeDugCallback( x, y)) { ok = false; }
if (!isWallCallback (x + nx, y + ny)) { ok = false; }
if (!isWallCallback (x - nx, y - ny)) { ok = false; }
if (!ok) {
length = i;
this._endX = x-dx;
this._endY = y-dy;
break;
}
}
/**
* If the length degenerated, this corridor might be invalid
*/
/* not supported */
if (length == 0) { return false; }
/* length 1 allowed only if the next space is empty */
if (length == 1 && isWallCallback(this._endX + dx, this._endY + dy)) { return false; }
/**
* We do not want the corridor to crash into a corner of a room;
* if any of the ending corners is empty, the N+1th cell of this corridor must be empty too.
*
* Situation:
* #######1
* .......?
* #######2
*
* The corridor was dug from left to right.
* 1, 2 - problematic corners, ? = N+1th cell (not dug)
*/
var firstCornerBad = !isWallCallback(this._endX + dx + nx, this._endY + dy + ny);
var secondCornerBad = !isWallCallback(this._endX + dx - nx, this._endY + dy - ny);
this._endsWithAWall = isWallCallback(this._endX + dx, this._endY + dy);
if ((firstCornerBad || secondCornerBad) && this._endsWithAWall) { return false; }
return true;
}
/**
* @param {function} digCallback Dig callback with a signature (x, y, value). Values: 0 = empty.
*/
ROT.Map.Feature.Corridor.prototype.create = function(digCallback) {
var sx = this._startX;
var sy = this._startY;
var dx = this._endX-sx;
var dy = this._endY-sy;
var length = 1+Math.max(Math.abs(dx), Math.abs(dy));
if (dx) { dx = dx/Math.abs(dx); }
if (dy) { dy = dy/Math.abs(dy); }
var nx = dy;
var ny = -dx;
for (var i=0; i<length; i++) {
var x = sx + i*dx;
var y = sy + i*dy;
digCallback(x, y, 0);
}
return true;
}
ROT.Map.Feature.Corridor.prototype.createPriorityWalls = function(priorityWallCallback) {
if (!this._endsWithAWall) { return; }
var sx = this._startX;
var sy = this._startY;
var dx = this._endX-sx;
var dy = this._endY-sy;
if (dx) { dx = dx/Math.abs(dx); }
if (dy) { dy = dy/Math.abs(dy); }
var nx = dy;
var ny = -dx;
priorityWallCallback(this._endX + dx, this._endY + dy);
priorityWallCallback(this._endX + nx, this._endY + ny);
priorityWallCallback(this._endX - nx, this._endY - ny);
}