1
1

RoomRandomMap.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /// <reference path="../Room.ts" />
  2. /// <reference path="RoomRandom.ts" />
  3. interface MapCoordinates {
  4. x : number;
  5. y : number;
  6. z : number;
  7. }
  8. class RoomRandomMap {
  9. private positionTable : {[x : number] : {[y : number] : RoomRandom}} = {};
  10. private roomMap = new Map<Room, Array<number>>();
  11. public lowestX = 0;
  12. public lowestY = 0;
  13. public highestX = 0;
  14. public highestY = 0;
  15. public limitsInvalid = false;
  16. /**
  17. * This is a count of how many connections are actually available, assuming rooms that can connect through some direction.
  18. * @type {number}
  19. */
  20. public availableConnections : Array<Array<MapCoordinates>>;
  21. /**
  22. * 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.
  23. * @type {number}
  24. */
  25. public rooms;
  26. /**
  27. * Clears the current room cache and creates a new one that is empty
  28. */
  29. public emptyCache () {
  30. this.availableConnections = [];
  31. Room.DIRECTIONS.forEach(() => {
  32. this.availableConnections.push([]);
  33. });
  34. this.rooms = 0;
  35. }
  36. public getAvailableConnections () {
  37. return this.availableConnections.reduce((previousValue, currentValue, currentIndex, array) => {
  38. return previousValue + (currentValue.length);
  39. }, 0);
  40. }
  41. public removeFromCache (coordinatesToRemove : MapCoordinates, direction : number) {
  42. let directionArray = this.availableConnections[direction];
  43. for (let k = 0, coordinates = directionArray[k]; coordinates != undefined; coordinates = directionArray[++k]) {
  44. if (coordinates.x == coordinatesToRemove.x && coordinates.y == coordinatesToRemove.y) {
  45. directionArray.splice(k, 1);
  46. return;
  47. }
  48. }
  49. }
  50. public addToCache (coordinatesToAdd : MapCoordinates, direction : number) {
  51. let directionArray = this.availableConnections[direction];
  52. for (let k = 0, coordinates = directionArray[k]; coordinates != undefined; coordinates = directionArray[++k]) {
  53. if (coordinates.x == coordinatesToAdd.x && coordinates.y == coordinatesToAdd.y) {
  54. return;
  55. }
  56. }
  57. directionArray.push(coordinatesToAdd);
  58. }
  59. public getAnyFromCache (direction : number) : RoomRandom {
  60. let array = this.availableConnections[direction];
  61. if (array.length > 0) {
  62. let randomIndex = Math.floor(Math.random() * (array.length));
  63. let randomCoordinates = array[randomIndex];
  64. if (randomCoordinates != undefined) {
  65. return this.getRoom(randomCoordinates.x, randomCoordinates.y);
  66. }
  67. }
  68. }
  69. public isFree (x : number, y : number) {
  70. return (this.positionTable[x] == undefined || this.positionTable[x][y] === undefined);
  71. }
  72. public block (x : number, y : number) {
  73. if (this.isFree(x, y)) {
  74. if (this.positionTable[x] == undefined) {
  75. this.positionTable[x] = {};
  76. }
  77. this.positionTable[x][y] = null;
  78. this.updateCacheOnPosition(x, y);
  79. this.updateLimits(x, y);
  80. }
  81. }
  82. public updateAllLimits () {
  83. this.highestX = 0;
  84. this.highestY = 0;
  85. this.lowestX = 0;
  86. this.lowestY = 0;
  87. for (let x in this.positionTable) {
  88. for (let y in this.positionTable[x]) {
  89. if (this.positionTable[x][y] != undefined && this.positionTable[x][y] != null) {
  90. this.updateLimits(parseInt(x), parseInt(y));
  91. }
  92. }
  93. }
  94. this.limitsInvalid = false;
  95. }
  96. public updateLimits (x, y) {
  97. if (x > this.highestX) this.highestX = x;
  98. if (y > this.highestY) this.highestY = y;
  99. if (y < this.lowestY) this.lowestY = y;
  100. if (x < this.lowestX) this.lowestX = x;
  101. }
  102. public map (room : RoomRandom, x : number, y : number) {
  103. if (this.positionTable[x] == undefined) {
  104. this.positionTable[x] = {};
  105. }
  106. this.positionTable[x][y] = room;
  107. this.roomMap.set(room, [x, y]);
  108. this.updateCacheOnPosition(x, y);
  109. // If we ever want to draw maps, this will be useful
  110. this.updateLimits(x, y);
  111. room.placed = true;
  112. room.lastMap = this;
  113. this.rooms++;
  114. }
  115. public unmap (x : number, y : number) {
  116. if (this.positionTable[x] != undefined && this.positionTable[x][y] != undefined) {
  117. this.roomMap.delete(this.positionTable[x][y]);
  118. delete (this.positionTable[x][y]);
  119. this.rooms--;
  120. this.updateCacheOnPosition(x, y);
  121. this.limitsInvalid = true;
  122. }
  123. }
  124. private updateCacheOnPosition (x : number, y : number) {
  125. let coordinates = [x, y, 0];
  126. let coordinatesMap = <MapCoordinates> {x : x, y : y};
  127. let coordinatesBlocked = !this.isFree(x, y);
  128. let coordinatesRoom = this.getRoom(x, y);
  129. Room.DIRECTIONS.forEach(direction => {
  130. let oppositeDirection = OppositeDirection[Direction[direction]];
  131. let shifted = Room.shift(coordinates, direction);
  132. let shiftedMap = <MapCoordinates> {x : shifted[0], y : shifted[1]};
  133. let shiftedBlocked = !this.isFree(shifted[0], shifted[1]);
  134. let shiftedRoom = this.getRoom(shifted[0], shifted[1]);
  135. if (coordinatesRoom != undefined) {
  136. if (shiftedBlocked) {
  137. this.removeFromCache(coordinatesMap, direction);
  138. } else if (coordinatesRoom.isConnectableOn(direction)) {
  139. this.addToCache(coordinatesMap, direction);
  140. }
  141. } else {
  142. this.removeFromCache(coordinatesMap, direction);
  143. }
  144. if (shiftedRoom != undefined) {
  145. if (coordinatesBlocked) {
  146. this.removeFromCache(shiftedMap, oppositeDirection);
  147. } else if (shiftedRoom.isConnectableOn(oppositeDirection)) {
  148. this.addToCache(shiftedMap, oppositeDirection);
  149. }
  150. } else {
  151. this.removeFromCache(shiftedMap, oppositeDirection);
  152. }
  153. });
  154. }
  155. public getRoom (x : number, y : number) {
  156. if (this.positionTable[x] != undefined) {
  157. if (this.positionTable[x][y] != null) {
  158. return this.positionTable[x][y];
  159. }
  160. }
  161. return undefined;
  162. }
  163. public getCoordinates (room : Room) : Array<number> {
  164. return this.roomMap.get(room);
  165. }
  166. public getRoomCount () {
  167. return this.roomMap.size;
  168. }
  169. public getWidth () {
  170. return this.highestX - this.lowestX;
  171. }
  172. public getHeight () {
  173. return this.highestY - this.lowestY;
  174. }
  175. public static PREFERRED_GROWTH_HORIZONTAL = 0;
  176. public static PREFERRED_GROWTH_VERTICAL = 1;
  177. public static PREFERRED_GROWTH_ANY = 2;
  178. public getPreferredGrowth () {
  179. let ratio = this.getHeight() / this.getWidth();
  180. let idealRatio = 2.5; // This means we'd prefer a tall map that'd look good on our screen
  181. let difference = Math.abs(ratio - idealRatio);
  182. if (difference < 0.5) {
  183. return RoomRandomMap.PREFERRED_GROWTH_ANY;
  184. } else {
  185. if (ratio < idealRatio) {
  186. return RoomRandomMap.PREFERRED_GROWTH_VERTICAL;
  187. } else {
  188. return RoomRandomMap.PREFERRED_GROWTH_HORIZONTAL;
  189. }
  190. }
  191. }
  192. public static isDirectionPreferred (direction : number, growth : number) {
  193. if (growth == RoomRandomMap.PREFERRED_GROWTH_ANY) {
  194. return true;
  195. } else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
  196. return growth == RoomRandomMap.PREFERRED_GROWTH_VERTICAL;
  197. } else {
  198. return growth == RoomRandomMap.PREFERRED_GROWTH_HORIZONTAL;
  199. }
  200. }
  201. }