123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /// <reference path="../Room.ts" />
- /// <reference path="RoomRandom.ts" />
- interface MapCoordinates {
- x : number;
- y : number;
- z : number;
- }
- class RoomRandomMap {
- private positionTable : {[x : number] : {[y : number] : RoomRandom}} = {};
- private roomMap = new Map<Room, Array<number>>();
- public lowestX = 0;
- public lowestY = 0;
- public highestX = 0;
- public highestY = 0;
- public limitsInvalid = false;
- /**
- * This is a count of how many connections are actually available, assuming rooms that can connect through some direction.
- * @type {number}
- */
- public availableConnections : Array<Array<MapCoordinates>>;
- /**
- * This is a count of rooms since the last cache clear. Used to mean more, but now is just a count of how many rooms were placed from the current region.
- * @type {number}
- */
- public rooms;
- /**
- * Clears the current room cache and creates a new one that is empty
- */
- public emptyCache () {
- this.availableConnections = [];
- Room.DIRECTIONS.forEach(() => {
- this.availableConnections.push([]);
- });
- this.rooms = 0;
- }
- public getAvailableConnections () {
- return this.availableConnections.reduce((previousValue, currentValue, currentIndex, array) => {
- return previousValue + (currentValue.length);
- }, 0);
- }
- public removeFromCache (coordinatesToRemove : MapCoordinates, direction : number) {
- let directionArray = this.availableConnections[direction];
- for (let k = 0, coordinates = directionArray[k]; coordinates != undefined; coordinates = directionArray[++k]) {
- if (coordinates.x == coordinatesToRemove.x && coordinates.y == coordinatesToRemove.y) {
- directionArray.splice(k, 1);
- return;
- }
- }
- }
- public addToCache (coordinatesToAdd : MapCoordinates, direction : number) {
- let directionArray = this.availableConnections[direction];
- for (let k = 0, coordinates = directionArray[k]; coordinates != undefined; coordinates = directionArray[++k]) {
- if (coordinates.x == coordinatesToAdd.x && coordinates.y == coordinatesToAdd.y) {
- return;
- }
- }
- directionArray.push(coordinatesToAdd);
- }
- public getAnyFromCache (direction : number) : RoomRandom {
- let array = this.availableConnections[direction];
- if (array.length > 0) {
- let randomIndex = Math.floor(Math.random() * (array.length));
- let randomCoordinates = array[randomIndex];
- if (randomCoordinates != undefined) {
- return this.getRoom(randomCoordinates.x, randomCoordinates.y);
- }
- }
- }
- public isFree (x : number, y : number) {
- return (this.positionTable[x] == undefined || this.positionTable[x][y] === undefined);
- }
- public isFreeSquare (centerX : number, centerY : number, distanceFromCenter : number) {
- for (let x = centerX - distanceFromCenter; x <= centerX + distanceFromCenter; x++) {
- for (let y = centerY - distanceFromCenter; y <= centerY + distanceFromCenter; y++) {
- if (!this.isFree(x,y)) {
- return false;
- }
- }
- }
- return true;
- }
- public block (x : number, y : number) {
- if (this.isFree(x, y)) {
- if (this.positionTable[x] == undefined) {
- this.positionTable[x] = {};
- }
- this.positionTable[x][y] = null;
- this.updateCacheOnPosition(x, y);
- this.updateLimits(x, y);
- }
- }
- public updateAllLimits () {
- this.highestX = 0;
- this.highestY = 0;
- this.lowestX = 0;
- this.lowestY = 0;
- for (let x in this.positionTable) {
- for (let y in this.positionTable[x]) {
- if (this.positionTable[x][y] != undefined && this.positionTable[x][y] != null) {
- this.updateLimits(parseInt(x), parseInt(y));
- }
- }
- }
- this.limitsInvalid = false;
- }
- public updateLimits (x, y) {
- if (x > this.highestX) this.highestX = x;
- if (y > this.highestY) this.highestY = y;
- if (y < this.lowestY) this.lowestY = y;
- if (x < this.lowestX) this.lowestX = x;
- }
- public map (room : RoomRandom, x : number, y : number) {
- if (this.positionTable[x] == undefined) {
- this.positionTable[x] = {};
- }
- this.positionTable[x][y] = room;
- this.roomMap.set(room, [x, y]);
- this.updateCacheOnPosition(x, y);
- // If we ever want to draw maps, this will be useful
- this.updateLimits(x, y);
- room.placed = true;
- room.lastMap = this;
- this.rooms++;
- }
- public unmap (x : number, y : number) {
- if (this.positionTable[x] != undefined && this.positionTable[x][y] != undefined) {
- let room = this.positionTable[x][y];
- room.placed = false;
- this.roomMap.delete(this.positionTable[x][y]);
- delete (this.positionTable[x][y]);
- this.rooms--;
- this.updateCacheOnPosition(x, y);
- this.limitsInvalid = true;
- }
- }
- private updateCacheOnPosition (x : number, y : number) {
- let coordinates = [x, y, 0];
- let coordinatesMap = <MapCoordinates> {x : x, y : y};
- let coordinatesBlocked = !this.isFree(x, y);
- let coordinatesRoom = this.getRoom(x, y);
- Room.DIRECTIONS.forEach(direction => {
- let oppositeDirection = OppositeDirection[Direction[direction]];
- let shifted = Room.shift(coordinates, direction);
- let shiftedMap = <MapCoordinates> {x : shifted[0], y : shifted[1]};
- let shiftedBlocked = !this.isFree(shifted[0], shifted[1]);
- let shiftedRoom = this.getRoom(shifted[0], shifted[1]);
- if (coordinatesRoom != undefined) {
- if (shiftedBlocked) {
- this.removeFromCache(coordinatesMap, direction);
- } else if (coordinatesRoom.isConnectableOn(direction)) {
- this.addToCache(coordinatesMap, direction);
- }
- } else {
- this.removeFromCache(coordinatesMap, direction);
- }
- if (shiftedRoom != undefined) {
- if (coordinatesBlocked) {
- this.removeFromCache(shiftedMap, oppositeDirection);
- } else if (shiftedRoom.isConnectableOn(oppositeDirection)) {
- this.addToCache(shiftedMap, oppositeDirection);
- }
- } else {
- this.removeFromCache(shiftedMap, oppositeDirection);
- }
- });
- }
- public getRoom (x : number, y : number) {
- if (this.positionTable[x] != undefined) {
- if (this.positionTable[x][y] != null) {
- return this.positionTable[x][y];
- }
- }
- return undefined;
- }
- public getCoordinates (room : Room) : Array<number> {
- return this.roomMap.get(room);
- }
- public getRoomCount () {
- return this.roomMap.size;
- }
- public getWidth () {
- return this.highestX - this.lowestX;
- }
- public getHeight () {
- return this.highestY - this.lowestY;
- }
- public static PREFERRED_GROWTH_HORIZONTAL = 0;
- public static PREFERRED_GROWTH_VERTICAL = 1;
- public static PREFERRED_GROWTH_ANY = 2;
- public getPreferredGrowth () {
- let ratio = this.getHeight() / this.getWidth();
- let idealRatio = 2.5; // This means we'd prefer a tall map that'd look good on our screen
- let difference = Math.abs(ratio - idealRatio);
- if (difference < 0.5) {
- return RoomRandomMap.PREFERRED_GROWTH_ANY;
- } else {
- if (ratio < idealRatio) {
- return RoomRandomMap.PREFERRED_GROWTH_VERTICAL;
- } else {
- return RoomRandomMap.PREFERRED_GROWTH_HORIZONTAL;
- }
- }
- }
- public static isDirectionPreferred (direction : number, growth : number) {
- if (growth == RoomRandomMap.PREFERRED_GROWTH_ANY) {
- return true;
- } else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
- return growth == RoomRandomMap.PREFERRED_GROWTH_VERTICAL;
- } else {
- return growth == RoomRandomMap.PREFERRED_GROWTH_HORIZONTAL;
- }
- }
- }
|