#include <lib.h>
#include <rooms.h>
#include <save.h>
#define ROOM_ZERO "/domains/campus/room/start"
inherit LIB_DAEMON;
mapping Workrooms = ([]);
mapping WorldMap = ([]);
mapping WorldGrid = ([]);
static string last_exit;
static int global_manual;
int debugging;
static string *cards = ({ "north", "south", "east", "west",
"northeast", "northwest", "southeast", "southwest",
"up", "down" });
static string *unsafes = ({ "/realms/", "/open/", "/estates/" });
void create(){
if(!WorldMap) WorldMap = ([]);
if(!WorldGrid) WorldGrid = ([]);
if( file_size( SAVE_ROOMS __SAVE_EXTENSION__ ) > 0 )
unguarded( (: restore_object, SAVE_ROOMS, 1 :) );
set_heart_beat(300);
}
void heart_beat(){
unguarded( (: save_object(SAVE_ROOMS, 1) :) );
}
int eventDestruct(){
unguarded( (: save_object(SAVE_ROOMS, 1) :) );
return daemon::eventDestruct();
}
int SetDebugging(int i){
if(!this_player() || !adminp(this_player())) return 0;
if(i) debugging = 1;
else debugging = 0;
return debugging;
}
mixed validate_last_room(string room, object player){
string location_str, current_room_name;
object location_ob, current_room;
mapping origin_room = ([]);
mapping origin_room_exits = ([]);
mixed tmp, ret;
if(debugging) tc("validate "+room+"?","blue");
if(player) location_str=player->GetProperty("LastLocation");
if(!location_str) return 0;
if(location_str) location_ob=load_object(location_str);
if(location_ob) tmp = this_object()->GetCoordinates(location_ob);
if(tmp) origin_room = this_object()->GetGrid(tmp);
current_room = room_environment(player);
current_room_name = base_name(room_environment(player));
if(debugging){
tc("Last Location: "+location_str);
tc("Last Location coords: "+ tmp);
if(sizeof(tmp) > 1)
tc("What those coordinates grid as: "+identify(origin_room));
}
if(room == ROOM_ZERO || (mapp(origin_room) &&
origin_room["room"] && origin_room["room"] == location_str)){
mapping exits = location_ob->GetExitMap();
if(location_ob->GetFlyRoom()){
exits["up"] = location_ob->GetFlyRoom();
}
foreach(mixed key, mixed val in exits){
if(val == current_room_name){
ret = ([ opposite_dir(key) : location_str ]);
}
}
if(debugging) tc("validation passed","blue");
if(!ret) ret = 1;
}
if(debugging) tc("validation failed","red");
return ret;
}
void zero(){
WorldMap = ([]);
WorldGrid = ([]);
Workrooms = ([]);
ROOM_ZERO->init();
}
mapping GetGridMap(){
return copy(WorldGrid);
}
mapping GetWorldMap(){
return copy(WorldMap);
}
string StrCoord(mapping TmpMap){
string ret = TmpMap["x"] + ",";
ret += TmpMap["y"] + ",";
ret += TmpMap["z"];
return ret;
}
varargs mixed SetGrid(string arg_room, string coord, object player, int unset){
string room, a, b, c, d, e, f, g, h, i, j, k, l, m, n;
string hashed_coord = crypt(coord, "xyz");
if(this_player() && adminp(this_player())){
room = arg_room;
}
else {
room = base_name(previous_object());
}
if(!player->GetProperty("LastLocation")) return 0;
if(debugging){
tc("SetGrid received: "+room+", "+coord+", "+
identify(player)+", "+unset,"blue");
}
a = hashed_coord[0..2];
b = hashed_coord[3..5];
c = hashed_coord[6..8];
d = hashed_coord[9..11];
e = hashed_coord[12..14];
f = hashed_coord[15..17];
g = hashed_coord[18..20];
h = hashed_coord[21..23];
i = hashed_coord[24..26];
j = hashed_coord[27..29];
k = hashed_coord[30..32];
l = hashed_coord[33..35];
m = hashed_coord[36..38];
n = hashed_coord[39..40];
if(!WorldGrid[a]) WorldGrid[a] = ([]);
if(!WorldGrid[a][b]) WorldGrid[a][b] = ([]);
if(!WorldGrid[a][b][c]) WorldGrid[a][b][c] = ([]);
if(!WorldGrid[a][b][c][d]) WorldGrid[a][b][c][d] = ([]);
if(!WorldGrid[a][b][c][d][e]) WorldGrid[a][b][c][d][e] = ([]);
if(!WorldGrid[a][b][c][d][e][f]) WorldGrid[a][b][c][d][e][f] = ([]);
if(!WorldGrid[a][b][c][d][e][f][g]) WorldGrid[a][b][c][d][e][f][g] = ([]);
if(!WorldGrid[a][b][c][d][e][f][g][h]) WorldGrid[a][b][c][d][e][f][g][h] = ([]);
if(!WorldGrid[a][b][c][d][e][f][g][h][i]) WorldGrid[a][b][c][d][e][f][g][h][i] = ([]);
if(!WorldGrid[a][b][c][d][e][f][g][h][i][j]) WorldGrid[a][b][c][d][e][f][g][h][i][j] = ([]);
if(!WorldGrid[a][b][c][d][e][f][g][h][i][j][k]) WorldGrid[a][b][c][d][e][f][g][h][i][j][k] = ([]);
if(!WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l]) WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l] = ([]);
if(!WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m]) WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m] = ([]);
if(!WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n]) WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n] = ([]);
if(unset && sizeof(WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n])){
if(debugging){
tc("Unsetting: "+identify(WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n]),"red");
}
WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n] = 0;
return 1;
}
if(sizeof(WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n]) ||
sizeof(this_object()->GetCoordinates(coord))){
if(debugging) tc("SetGrid coord "+coord+" (aka "+hashed_coord+
") is already "+ identify(WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n]));
return WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n];
}
else {
if(global_manual || validate_last_room(room, player)){
if(debugging) tc("Setting coord "+coord+" (aka "+hashed_coord+
") as "+room, "green");
global_manual = 0;
WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n] =
([ "room" : room, "coord" : coord ]);
}
return WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n];
}
}
mixed GetGrid(string str){
string hashed_coord = crypt(str, "xyz");
string a, b, c, d, e, f, g, h, i, j, k, l, m, n;
a = hashed_coord[0..2];
b = hashed_coord[3..5];
c = hashed_coord[6..8];
d = hashed_coord[9..11];
e = hashed_coord[12..14];
f = hashed_coord[15..17];
g = hashed_coord[18..20];
h = hashed_coord[21..23];
i = hashed_coord[24..26];
j = hashed_coord[27..29];
k = hashed_coord[30..32];
l = hashed_coord[33..35];
m = hashed_coord[36..38];
n = hashed_coord[39..40];
if(!WorldGrid[a] ||
!WorldGrid[a][b] ||
!WorldGrid[a][b][c] ||
!WorldGrid[a][b][c][d] ||
!WorldGrid[a][b][c][d][e] ||
!WorldGrid[a][b][c][d][e][f] ||
!WorldGrid[a][b][c][d][e][f][g] ||
!WorldGrid[a][b][c][d][e][f][g][h] ||
!WorldGrid[a][b][c][d][e][f][g][h][i] ||
!WorldGrid[a][b][c][d][e][f][g][h][i][j] ||
!WorldGrid[a][b][c][d][e][f][g][h][i][j][k] ||
!WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l] ||
!WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m] ||
!WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n]){
if(debugging) tc("No joy for "+str+" aka "+hashed_coord,"red");
return copy(WorldGrid[a]);
}
if(debugging) tc("Joy! "+str+" aka "+hashed_coord+" is "+
identify(WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n]),"white");
return copy(WorldGrid[a][b][c][d][e][f][g][h][i][j][k][l][m][n]);
}
int UnSetRoom(object arg_ob){
string creator, name, prefix, room_name;
string grid;
object ob;
if(this_player() && adminp(this_player())){
ob = arg_ob;
}
else{
ob = previous_object();
}
name = base_name(ob);
grid = this_object()->GetCoordinates(ob);
if(grid && grid != "0,0,0"){
SetGrid(name, grid, this_player(), 1);
}
prefix = path_prefix(name);
room_name = last_string_element(name, "/");
if(WorldMap[prefix] && WorldMap[prefix][room_name]){
WorldMap[prefix][room_name] = 0;
}
if(sscanf(name,"/realms/%s/workroom",creator)){
Workrooms[creator] = 0;
}
return 1;
}
varargs int SetRoom(object arg_ob, object player, string manual){
string last_str, creator, name, prefix, room_name, coord;
mapping tmpexits, backup_direction;
object ob;
if(this_player() && adminp(this_player())){
ob = arg_ob;
}
else{
ob = previous_object();
}
if(clonep(ob)){
return 0;
}
if(!(last_str = player->GetProperty("LastLocation"))){
return 0;
}
name = base_name(ob);
prefix = path_prefix(name);
room_name = last_string_element(name, "/");
if(!sizeof(WorldMap)){
if(name == ROOM_FURNACE){
return 0;
}
}
if(!manual && WorldMap[prefix] && WorldMap[prefix][room_name]){
if(StrCoord(WorldMap[prefix][room_name]["coords"]) == "0,0,0" &&
name != ROOM_ZERO){
UnSetRoom(ob);
}
else{
return 0;
}
}
sscanf(name,"/realms/%s/workroom",creator);
foreach(string element in unsafes){
if(!strsrch(last_str, element)){
if(strsrch(name, element) && !creator)
return 0;
}
}
if(!WorldMap[prefix]){
if(debugging) tc("Creating WorldMap["+identify(prefix)+"]","yellow");
WorldMap[prefix] = ([]);
}
if(!WorldMap[prefix][room_name]){
if(debugging) tc("Creating WorldMap["+identify(prefix)+"]"+
"["+identify(room_name)+"]","cyan");
WorldMap[prefix][room_name] = ([ "date" : time(),
"coords" : ([ "x" : 0, "y" : 0, "z" : 0 ]),
"exits" : ob->GetExitMap(),
]);
}
if(debugging){
}
if(creator){
int x,y,z,next = sizeof(Workrooms);
if(Workrooms[creator]){
return 1;
}
x = 1000000000;
y = 1000000000;
z = -1000000000;
x += ( next * 10000 );
manual = x+","+y+","+z;
Workrooms[creator] = ([ "grid" : manual,
"coords" : ([ "x" : x, "y" :y, "z" : z ]),
"time" : time(), "number" : next ]);
}
if(manual){
int res, x, y, z;
res = sscanf(manual,"%d,%d,%d",x,y,z);
if(res == 3){
if(debugging) tc("Setting manually.","red");
WorldMap[prefix][room_name]["coords"] =
([ "x" : x, "y" :y, "z" : z ]);
global_manual = 1;
SetGrid(name, manual, player);
return 1;
}
}
if(!(backup_direction = validate_last_room(name, player))){
if(debugging) tc("Unknown origin. Not mapping.","red");
if(WorldMap[prefix] && WorldMap[prefix][room_name] &&
StrCoord(WorldMap[prefix][room_name]["coords"]) == "0,0,0"){
WorldMap[prefix][room_name] = 0;
}
if(!creator) return 0;
}
tmpexits = WorldMap[prefix][room_name]["exits"];
if(!sizeof(tmpexits) || member_array(player->GetProperty("LastLocation"),
values(tmpexits)) == -1){
if(debugging)
tc("USING BACKUP DIRECTION: "+identify(backup_direction),"red");
tmpexits = backup_direction;
}
else {
if(debugging){
tc("Using tmpexits from WorldMap[\""+prefix+"\"][\""+
room_name+"\"] which is: "+identify(WorldMap[prefix][room_name]["exits"]),"white");
}
}
if(!mapp(tmpexits)) tmpexits = ([]);
if(debugging) tc("tmpexits: "+identify(tmpexits),"white");
foreach(string key, mixed val in tmpexits){
string sub_pre = path_prefix(val);
string sub_name = last_string_element(val, "/");
int breakout;
if(member_array(key, cards) == -1) continue;
if(debugging){
tc("sub_pre: "+sub_pre);
tc("sub_name: "+sub_name);
if(WorldMap[sub_pre] && WorldMap[sub_pre][sub_name])
tc("WorldMap["+identify(sub_pre)+"]["+identify(sub_name)+
"]: "+identify(WorldMap[sub_pre][sub_name]));
tc("prefix: "+prefix,"yellow");
tc("room_name: "+room_name,"yellow");
if(WorldMap[prefix] && WorldMap[prefix][room_name])
tc("WorldMap["+identify(prefix)+"]["+identify(room_name)+
"]: "+identify(WorldMap[prefix][room_name]),"yellow");
}
if(WorldMap[sub_pre] && WorldMap[sub_pre][sub_name]){
last_exit = key;
switch(key){
case "north" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"];
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"] - 1;
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"];
breakout = 1;
break;
case "south" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"];
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"] + 1;
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"];
breakout = 1;
break;
case "east" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"] - 1;
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"];
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"];
breakout = 1;
break;
case "west" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"] + 1;
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"];
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"];
breakout = 1;
break;
case "northeast" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"] - 1;
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"] - 1;
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"];
breakout = 1;
break;
case "northwest" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"] + 1;
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"] - 1;
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"];
breakout = 1;
break;
case "southeast" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"] - 1;
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"] + 1;
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"];
breakout = 1;
break;
case "southwest" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"] + 1;
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"] + 1;
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"];
breakout = 1;
break;
case "up" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"];
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"];
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"] - 1;
breakout = 1;
break;
case "down" : WorldMap[prefix][room_name]["coords"]["x"] =
WorldMap[sub_pre][sub_name]["coords"]["x"];
WorldMap[prefix][room_name]["coords"]["y"] =
WorldMap[sub_pre][sub_name]["coords"]["y"];
WorldMap[prefix][room_name]["coords"]["z"] =
WorldMap[sub_pre][sub_name]["coords"]["z"] + 1;
breakout = 1;
break;
}
}
if(breakout) break;
}
coord = WorldMap[prefix][room_name]["coords"]["x"]+","+
WorldMap[prefix][room_name]["coords"]["y"]+","+
WorldMap[prefix][room_name]["coords"]["z"];
if(debugging){
tc("SetRoom About to send: SetGrid("+identify(name)+", "+
identify(coord)+", "+identify(player)+")");
}
SetGrid(name, coord, player);
return 1;
}
string GetCoordinates(mixed ob){
string name, prefix, room_name, ret;
int err;
if(clonep(ob)){
object env = room_environment(ob);
if(env && !clonep(env)) ob = env;
else return "";
}
name = base_name(ob);
prefix = path_prefix(name);
room_name = last_string_element(name, "/");
if(!WorldMap[prefix] || !WorldMap[prefix][room_name]){
return "";
}
ret = WorldMap[prefix][room_name]["coords"]["x"]+","+
WorldMap[prefix][room_name]["coords"]["y"]+","+
WorldMap[prefix][room_name]["coords"]["z"];
return ret;
}
mapping GetCoordinateMap(mixed ob){
string name = base_name(ob);
string prefix = path_prefix(name);
string room_name = last_string_element(name, "/");
if(!WorldMap[prefix] || !WorldMap[prefix][room_name]){
return ([]);
}
return ([ "x" : WorldMap[prefix][room_name]["coords"]["x"],
"y" : WorldMap[prefix][room_name]["coords"]["y"],
"z" : WorldMap[prefix][room_name]["coords"]["z"], ]);
}
mixed GetRoom(mixed ob){
string name, prefix, room_name;
if(clonep(ob)) return 0;
name = base_name(ob);
prefix = path_prefix(name);
room_name = last_string_element(name, "/");
if(!WorldMap[prefix]) return "No such prefix.";
if(!WorldMap[prefix][room_name]) return "No such room.";
return ([ name : copy(WorldMap[prefix][room_name]) ]);
}