123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- /// <reference path="../../Elements/Classes/Say.ts" />
- enum Direction {
- NORTH, NORTHEAST, EAST,
- SOUTHEAST, SOUTH, SOUTHWEST,
- WEST, NORTHWEST, UP, DOWN
- }
- var DirectionNames : {[id: string] : string} = (() => {
- enum names {
- NORTH = "North",
- SOUTH = "South",
- EAST = "East",
- WEST = "West",
- SOUTHEAST = "Southeast",
- NORTHWEST = "Northwest",
- SOUTHWEST = "Southwest",
- NORTHEAST = "Northeast",
- UP = "Down",
- DOWN = "Up"
- };
- let obj : {[id: string] : string} = {};
- for (let name in names) {
- obj[name] = names[name];
- obj[Direction[name]] = names[name];
- }
- return obj;
- })();
- var OppositeDirection : {[id : number] : Direction} = (() => {
- let obj = {};
- obj[Direction.NORTH] = Direction.SOUTH;
- obj[Direction.SOUTH] = Direction.NORTH;
- obj[Direction.EAST] = Direction.WEST;
- obj[Direction.WEST] = Direction.EAST;
- obj[Direction.SOUTHEAST] = Direction.NORTHWEST;
- obj[Direction.NORTHWEST] = Direction.SOUTHEAST;
- obj[Direction.SOUTHWEST] = Direction.NORTHEAST;
- obj[Direction.NORTHEAST] = Direction.SOUTHWEST;
- obj[Direction.UP] = Direction.DOWN;
- obj[Direction.DOWN] = Direction.UP;
- // Make it work with the name too
- for (let i = 0; i < Object.keys(Direction).length / 2; i++) {
- obj[Direction[i]] = obj[i];
- }
- return obj;
- })();
- class Room implements Printable {
- protected name : string;
- public connections : Array<Room>;
- public description : Say = new Say();
- public fodder : boolean;
- public visited : boolean = false;
- public constructor (id? : string, fodder? : boolean) {
- this.name = id == undefined ? "Room" : id;
- this.connections = new Array(Room.DIRECTIONS.length); // Array the same size as directions, but filled with undefined
- this.fodder = fodder;
- if (fodder != true) {
- Room.addRoom(this);
- }
- }
- public getName () {
- return this.name;
- }
- public place (thing : Thing) {
- Thing.InsideRoomRelation.setRelation(this, thing);
- }
- public remove (thing : Thing) {
- // Don't remove stuff from other rooms
- if (Thing.InsideRoomRelation.getLeft(thing) == this) {
- Thing.InsideRoomRelation.unsetRight(thing);
- }
- }
- public getContained () : Array<Thing> {
- return <Array<Thing>> Thing.InsideRoomRelation.getRight(this);
- }
- public getContainedAndVisibleTo (observer : Thing) : Array<Thing> {
- let contained = this.getContained();
- let result = [];
- contained.forEach((value) => {
- if (value.visible && value !== observer) {
- result.push(value);
- }
- });
- return result;
- }
- public static DIRECTIONS : Array<Direction> = (() => {
- let directions : Array<Direction> = [];
- for (let i = 0; i < Object.keys(Direction).length / 2; i++) {
- directions.push(i);
- }
- return directions;
- })();
- public getContainedAndVisible () : Array<Thing> {
- return this.getContainedAndVisibleTo(WorldState.player);
- }
- public mapRoom (r : Room, direction : Direction) {
- let oppositeDirection = OppositeDirection[direction];
- if (this.connections[direction] != undefined) {
- console.warn("Replacing a connected room.", this, " connected through ", direction, " to ", this.connections[direction]);
- this.connections[direction].unmapRoom(oppositeDirection);
- }
- this.connections[direction] = r;
- if (r.connections[oppositeDirection] != undefined) {
- console.warn("Replacing a connected room.", r, " connected through ", oppositeDirection, " to ", r.connections[oppositeDirection]);
- r.unmapRoom(oppositeDirection);
- }
- r.connections[oppositeDirection] = this;
- }
- public unmapRoom (direction : Direction) {
- if (this.connections[direction] != undefined) {
- let r = this.connections[direction];
- this.connections[direction] = undefined;
- r.unmapRoom(OppositeDirection[direction]);
- }
- }
- public getPrintedName () {
- return this.name;
- }
- public getConnectedRooms () : Array<Room> {
- let rooms = [];
- this.connections.forEach(room => {
- if (room != undefined) {
- rooms.push(room);
- }
- });
- return rooms;
- }
- /**
- * This returns the best direction to follow if going from the current room to another room.
- * THIS CODE IS REALLY EXPENSIVE AND SHOULD ONLY BE USED AS A LAST RESORT
- * WARNING: THIS CODE WILL FAIL IF THE TARGET ROOM IS TOO FAR FROM THE CURRENT ROOM (FOR SECURITY REASONS).
- * This code runs through every. single. room. to find the best route to take.
- * If you need an NPC to stick to a region, don't let it go out of it in the first place!
- * @param room
- * @param validityCode
- * @returns {any}
- */
- // TODO: Make this shit fast
- public bestDirectionTo (room : Room, validityCode? : (room : Room) => boolean) {
- if (validityCode == undefined) validityCode = () => {return true};
- /**
- * Maximum amount of steps that will be considered for a route.
- * This is useful to prevent the code from spanning too many rooms, as each room can have Room.DIRECTIONS.length directions to make another call, etc.
- *
- * @type {number}
- */
- let maxSteps = 10;
- maxSteps = maxSteps > WorldState.getMaximumRememberedRooms() ? maxSteps : WorldState.getMaximumRememberedRooms();
- let recursiveBestPath = (cPath : Array<Room>, cRoom : Room, destination : Room) => {
- // Ignore "bad" rooms
- if (!validityCode(cRoom)) {
- return;
- }
- // Prevent the code from straying too far
- if (cRoom == destination) {
- maxSteps = maxSteps > cPath.length ? cPath.length : maxSteps; // Stop considering worse routes
- return cPath;
- } else if (cPath.length > maxSteps) {
- return undefined;
- } else {
- let paths = [];
- for (let index in Room.DIRECTIONS) {
- let direction = Room.DIRECTIONS[index];
- let nextRoom = cRoom.connections[direction];
- if (nextRoom != undefined && cPath.indexOf(nextRoom) == -1 && validityCode(nextRoom)) {
- let path = recursiveBestPath(cPath.concat([nextRoom]), nextRoom, destination);
- if (path != undefined) {
- paths.push(path);
- }
- }
- }
- let shortestIndex = 0;
- paths.forEach((value, index, array) => {
- if (value.length < paths[shortestIndex].length) {
- shortestIndex = index;
- }
- });
- return paths[shortestIndex];
- }
- };
- let paths = Array(Room.DIRECTIONS.length);
- let shortestIndex;
- for (let index in Room.DIRECTIONS) {
- let direction = Room.DIRECTIONS[index];
- let nextRoom = this.connections[direction];
- if (nextRoom != undefined) {
- paths[direction] = recursiveBestPath([this, nextRoom], nextRoom, room);
- if (paths[direction] != undefined && (shortestIndex == undefined || paths[shortestIndex].length > paths[direction].length)) {
- shortestIndex = direction;
- }
- }
- }
- return shortestIndex;
- }
- public static getDirectionXYZ (direction : Direction) {
- var y = 0;
- if ([Direction.NORTH, Direction.NORTHEAST, Direction.NORTHWEST].indexOf(direction) != -1) {
- y = 1;
- } else if ([Direction.SOUTH, Direction.SOUTHEAST, Direction.SOUTHWEST].indexOf(direction) != -1) {
- y = -1;
- }
- var x = 0;
- if ([Direction.EAST, Direction.SOUTHEAST, Direction.NORTHEAST].indexOf(direction) != -1) {
- x = 1;
- } else if ([Direction.WEST, Direction.SOUTHWEST, Direction.NORTHWEST].indexOf(direction) != -1) {
- x = -1;
- }
- var z = direction == Direction.UP ? 1 :
- direction == Direction.DOWN ? -1 :
- 0;
- return [x, y, z];
- }
- public static shift (coordinates : Array<number>, direction : number) {
- let coordinatesVector = Room.getDirectionXYZ(direction);
- coordinates.forEach((value, index, array) => {
- coordinatesVector[index] += coordinates[index];
- });
- return coordinatesVector;
- }
- protected static rooms : {[id : string] : Room} = {};
- protected static addRoom (room : Room) {
- Room.rooms[room.name] = room;
- }
- public static getRooms () : Array<Room> {
- let rooms = [];
- for (let name in Room.rooms) {
- rooms.push(Room.rooms[name]);
- }
- return rooms;
- }
- public static getRoom (id : string) {
- return Room.rooms[id];
- }
- }
|