///
module AIRules {
export var Wander = AI.rules.createAndAddRule({
name : "Wander",
firstPriority : AIRules.PRIORITY_ACTING_ON_IDLE,
conditions : (runner : RulebookRunner) => {
let person = runner.noun;
return person.AI.wanderer && (Math.random() * 100) > person.AI.wanderChance;
},
code : (runner : RulebookRunner) => {
let person = runner.noun;
let room = person.getRoom();
if (person.AI.wandersOn != undefined) {
// stick to region while wandering
if (person.AI.wandersOn.containsRoom(room)) {
// Alredy in region, so just wander off inside it
let connections = room.connections.slice();
let realConnections = [];
for (let i = 0; i < connections.length; i++) {
if (connections[i] != undefined && person.AI.wandersOn.containsRoom(connections[i])) {
realConnections.push(i);
}
}
let direction = ((new Shuffler(realConnections)).getOne());
return new ActionGo(person, direction);
} else {
// return to region
let regionRooms = person.AI.wandersOn.getRooms().filter((a : Room) => {
if (a instanceof RoomRandom && a.placed) {
return true;
}
});
// Ideally we'd actually make a path to it and check the distance, since mazes can make it be longer than it really is
// But this is quick and dirty enough. And since regions are closely packed, even if this is not really the closest room, the NPC will end up
// entering the region earlier by accident.
regionRooms.sort((a : RoomRandom, b : RoomRandom) => {
let dist = a.getDistanceTo(b);
if (dist != undefined) {
return -dist; // This means that the latest element will be the closest.
} else {
return 0; // This means that the first elements will be unreachable
}
});
let targetRoom = regionRooms.pop();
return new ActionGo(person, targetRoom);
}
} else {
// just wander in random direction
let direction = room.getConnectedDirection();
return new ActionGo(person, direction);
}
}
});
}