/* New Room v2.01. Angel & Zilanthius, 1994.
* Revision and updates, August, 1995.
* Version based on old 'room2' modules. All functions used from this
* older room version, so this new ob saves overhead
*/
#include <mudlib.h>
inherit BASE;
#include <room.spc>
#include <vowel.h>
#include <exit_con.h>
#include <weather.h>
#include <i_to_str.h>
#include <door_mac.h>
#include <newline.h>
#define ALT "external"
#define GUILD_OB "guild_object"
#define BLIND present("Blindness",this_player())
#define NAME (string)this_player()->query_name()
#define CAP (string)this_player()->query_cap_name()
#define REAL (string)this_player()->query_name(1)
#define QUERY_INT (int)this_player()->query_intelligence()
#define QUERY_LOCKS (int)this_player()->query_locks()
#define QUERY_TRAPS (int)this_player()->query_traps()
string *dest_dir; /* list of exit room|directions */
string *extra_objects; /* list of objects that can be taken */
string *items; /* list of items that can be looked at */
string *night_items; /* list of items in night_desc */
string *day_items; /* list of items in day_desc */
string *search_array;
int search_complex;
string day_desc; /* extra description of long in daylight */
string night_desc; /* extra description of long at night */
string enter_msg; /* string written after entering a room */
string exit_msg; /* string written before leaving room */
int climb; /* climbing difficulty for up|down */
int fall_dam; /* damage taken if one falls whilst climbing */
int swim; /* chance to drown in the sea */
int swim_dam; /* damage taken if one fails to swim */
int no_track; /* This will prevent you from looking into the
room magically */
int no_summon, no_fight; /* This will prevent fighting and
summoning from a particular room; */
string custom_exits; /* "" == no exit list in long */
mixed *doors; /* list of doors */
mixed *detect_attempts;
mixed *disarm_attempts;
mixed *lock_attempts;
/***********************************************************************/
void reset(status arg) {
reset_doors(0); /* reset_doors(1) will erase secret door finders */
if(arg) return;
}
string query_object_type() { return "Room"; }
void init() {
int i, size;
string act, tmp;
::init();
fix_day(); /* night-day cycler */
/* i'd rather this in the reset */
if(!smell_msg) set_smell("You smell nothing special.\n");
if(!listen_msg) set_listen("You hear nothing special.\n");
if(!dest_dir) dest_dir = ({});
if(!doors) doors = ({});
if(!extra_objects) extra_objects = ({});
if(!items) items = ({});
if(!night_items) night_items = ({});
if(!day_items) day_items = ({});
if(!search_array) search_array = ({});
/* normal exits */
for(i = 1, size=sizeof(dest_dir); i < size; i += 2) {
act = dest_dir[i];
sscanf(act,"%s %s",act,tmp);
add_action("ready_to_move", act);
add_action("ready_to_move", convert_to_brief(act));
}
/* doors */
if((size = sizeof(doors))) {
for(i = 0; i < size; i++) {
if(!(act = DOOR_ID)) continue;
sscanf(act,"%s %s",act,tmp);
add_action("door_to_move", act);
add_action("door_to_move",convert_to_brief(act));
}
}
if(sizeof(extra_objects)) {
add_action("get_extra_object", "get");
add_action("get_extra_object", "take");
}
add_action("close","close");
add_action("open","open");
add_action("lock","lock");
add_action("unlock","unlock");
add_action("disarm_trap","disarm");
add_action("arm_trap","arm");
add_action("detect","detect");
add_action("pick_lock", "pick");
add_action("search_room","search");
}
void long(status wiz) {
int i, day;
object obj;
if(wiz) {
write("File: "+file_name(this_object()) +"\n\n");
}
::long(wiz);
if(query_day()) {
if(day_desc) write(process_msg(day_desc));
}
else {
if(night_desc) write(process_msg(night_desc));
}
}
/* ids of items in room */
status id(string str) {
int i, size;
if(get_id_index(str,items) != -1) {
return 1;
}
else if(get_id_index(str,extra_objects) != -1) {
return 1;
}
else if(query_day() && get_id_index(str,day_items) != -1) {
return 1;
}
else if(!query_day() && get_id_index(str,night_items) != -1) {
return 1;
}
else {
if(!doors) doors = ({});
for(i = 0, size = sizeof(doors); i < size; i++) {
if(DOOR_ID == str) {
if(SECRET_DOOR && member_array(REAL,SECRET_DOOR_FINDERS) == -1) {
return 0; /* haven't found the secret door */
}
return 1;
}
}
}
return 0; /* nothing in 'room' matching id matching 'str' */
}
/*********************************************************************/
/* sets */
string set_day_desc(string str) { return day_desc = str; }
string set_night_desc(string str) { return night_desc = str; }
string set_enter_msg(string s) { return enter_msg = s; }
string set_exit_msg(string s) { return exit_msg = s; }
string *set_exits(string *arr) {
dest_dir = (arr) ? arr : ({});
update_actions();
return dest_dir;
}
string *set_extra_objects(string *arr) {
extra_objects = arr;
update_actions();
return extra_objects;
}
string *set_items(string *arr) { return items = arr; }
string *set_day_items(string *arr) { return day_items = arr; }
string *set_night_items(string *arr) { return night_items = arr; }
string *set_search_array(string *arr) { return search_array = arr; }
int set_search_complex(int i) { return search_complex = i; }
mixed *set_doors(mixed *arr) {
doors = (arr) ? arr : ({});
update_actions();
return doors;
}
int set_climb(int i) { return climb = i; }
int set_fall_dam(int i) { return fall_dam = i; }
int set_swim(int i) { return swim = i; }
int set_swim_dam(int i){ return swim_dam = i; }
mixed *set_detect_attempts(mixed *arg) { return detect_attempts = arg; }
mixed *set_disarm_attempts(mixed *arg) { return disarm_attempts = arg; }
mixed *set_lock_attempts(mixed *arg) { return lock_attempts = arg; }
int set_no_fight(int i) { return no_fight = i; }
int set_no_track(int i) { return no_track = i; }
int set_no_summon(int i) { return no_summon = i; }
/**********************************************************************/
/* queries */
string query_day_desc() { return day_desc; }
string query_night_desc() { return night_desc; }
string query_enter_msg() { return enter_msg; }
string query_exit_msg() { return exit_msg; }
string *query_dest_dir() { return dest_dir; }
string *query_extra_objects() { return extra_objects; }
string *query_items() { return items; }
string *query_day_items() { return day_items; }
string *query_night_items() { return night_items; }
string *query_search_array(string *arr) { return search_array; }
int query_search_complex(int i) { return search_complex; }
mixed *query_doors() { return doors; }
mixed *query_detect_attempts() { return detect_attempts; }
mixed *query_disarm_attempts() { return disarm_attempts; }
mixed *query_lock_attempts() { return lock_attempts; }
string query_exit_filename(string str) {
int i;
if(!(sizeof(dest_dir) || str)) return 0;
if((i = member_array(str,dest_dir)) > -1) return dest_dir[i-1];
return 0;
}
string query_file_exitname(string file) {
int i;
if(!file) return 0;
sscanf(file,"/%",file);
if((i = member_array(file, dest_dir)) > -1) return dest_dir[i+1];
return 0;
}
varargs string *query_door_exits(int arg) { /* get door exits only */
int i;
string *door_exits;
door_exits = ({});
for(i = 0; i < sizeof(doors); i++) {
if(!arg || (arg == 1 && !CLOSED_FLAG) ||
(arg == 2 && CLOSED_FLAG) ||
(arg == 3 && SECRET_DOOR) ||
(arg == 4 && TRAIL)) {
door_exits += ({ doors[i][0], doors[i][1], });
}
}
return door_exits;
}
string *query_all_exits() { return dest_dir + query_door_exits(); }
string *query_open_exits() { return dest_dir + query_door_exits(1); }
string *query_closed_exits() { return query_door_exits(2); }
string *query_exits() { return dest_dir; }
int query_no_fight() { return no_fight; }
int query_no_track() {return no_track; }
int query_no_summon() { return no_summon; }
/************************************************************************/
/* exits */
/*
* write the exits to the room
*/
static status test_next_door(int i, int door_size, string finder) {
i += 1;
if(i >= door_size) return 0;
if((SECRET_DOOR || TRAIL) &&
member_array(finder,SECRET_DOOR_FINDERS) == -1) {
return test_next_door(i,door_size,finder);
}
return 1;
}
void exits(status brief) {
string str, name, pad;
int i, size;
int count;
if(custom_exits) {
write(custom_exits);
return;
}
brief = (status)this_player()->query_brief();
/* door exits */
for(i = 0, size = sizeof(doors); i < size; i++) {
if((SECRET_DOOR || TRAIL)
&& member_array(REAL,SECRET_DOOR_FINDERS) == -1) continue;
if(!count) str = "There is ";
if(str == "") write("\n");
str += (!count) ? "" : ((test_next_door(i,size,REAL)) ? ", " : " and ");
str += (vowel(DOOR_ID)) ? "an " : "a ";
if(DOOR_ID != "trail")
str += DOOR_ID + ((CLOSED_FLAG) ? "(closed)" : "(open)");
else
str += DOOR_ID;
if(strlen(str) > 70) {
write(str);
str = "";
}
count += 1;
}
if(count) write(str +".\n");
size = sizeof(dest_dir);
if(!(count || size)) {
write("No Obvious Exits.\n");
return;
}
if(!size) return;
/* exits */
str = "There "+((size == 2) ? "is " : "are ")+int_to_str(size/2)+" obvious";
str += " exit"+ ((size == 2) ? ": " : "s: ");
pad = " ";
pad = extract(pad,0,strlen(str)-1);
for(i = 1; i < size; i += 2) {
if(str == "") {
write("\n");
str = pad;
}
str += " "+ ((brief) ? convert_to_brief(dest_dir[i]) : dest_dir[i]);
str += (i == size - 1) ? "." : ((i == size - 2) ? " and" : ",");
if(strlen(str) > 70) {
write(str);
str = "";
}
}
write(str +"\n");
}
/**************************************************************************/
/* get ready to move */
status ready_to_move(string str) {
string direction, func;
int climb_skill, swim_skill, i;
direction = query_verb();
direction = convert_exit_name(direction);
if(str) direction += " " + str;
if((direction == "up" || direction == "down") && climb > 0){
climb_skill = (int)this_player()->query_climb();
if(climb_skill < 1) climb_skill = 1;
/*** there is always a 1 in "climb" chance of climbing ***/
if(random(climb) > random(climb_skill)) {
write("You fall down.....\naahhhhhhhhhhhhhh!!\nThud!\n");
say(this_player()->query_name() + " falls down.\n");
/*** fall damage should be no greater then 6 ***/
if(fall_dam) this_player()->hit_player(random(fall_dam));
if(direction == "up") return 1;
}
}
if(swim)
if(member_array(direction, dest_dir) != -1) {
swim_skill = (int)this_player()->query_swim();
if(swim_skill < 1) swim_skill = 1;
if(random(swim) > random(swim_skill)) {
write("\nYou nearly drown...!!\n\n");
say((string)this_player()->query_name()+" nearly drowns!\n");
if(swim_dam) this_player()->hit_player(random(swim_dam));
}
write("You swim "+direction+"...\n\n");
}
if((i = member_array(direction,dest_dir)) == -1) return 0;
if(direction == "trail") {
if(!(int)this_player()->query_tracking()) {
write("What?\n");
return 1;
}
write("\nYou walk along the trail...\n\n");
}
if(sscanf(dest_dir[i-1],"@%s",func) == 1) { /* requested by tamsyn */
return (status)call_other(this_object(),func,direction);
}
str = direction +"#"+ dest_dir[i-1];
/*** its always slower to move in stealth ***/
if(this_player()->query_stealth_on()){
write("You sneak slowly "+ direction +"...\n");
call_out("room_move", 1, str);
}
else {
room_move(str);
}
return 1;
}
/****************************************************************************/
/* move player */
void room_move(string str) {
string tmp_msg;
if(!this_player()->move_player(str)) return; /* failed to move */
if(exit_msg) write(process_msg(exit_msg));
if((tmp_msg = (string)environment(this_player())->query_enter_msg())) {
write(process_msg(tmp_msg));
}
}
/***************************************************************************/
/* look direction */
status look_dir(string dir) {
int i;
status wiz;
if(!dir) return 0;
dir = convert_exit_name(dir);
if((i = member_array(dir, dest_dir)) == -1) return 0; /* failure */
wiz = (this_player()->query_security_level()) ? 1 : 0;
call_other(dest_dir[i-1],"long",wiz);
return 1;
}
/************************************************************************/
/* dynamic exits */
status add_weight(int i) { return 1; } /* so we can drop things! */
status add_exit(string where, string dest) {
int i;
if(!dest_dir) dest_dir = ({});
if((i = member_array(dest, dest_dir)) > -1) return 0; /* failure */
dest_dir += ({ where, dest });
update_actions();
return 1;
}
status remove_exit(string dest) {
int i, size;
if((i=member_array(dest,dest_dir)) < 0) return 0; /* failure */
if((size = sizeof(dest_dir)) == 2)
dest_dir = ({});
else
dest_dir = dest_dir[0..i-2] + dest_dir[i+1..size];
update_actions();
return 1;
}
status change_exit_room(string old_dest,string new_dest) {
int i;
if((i=member_array(old_dest,dest_dir)) == -1) return 0;
dest_dir[i] = new_dest;
update_actions();
return 1;
}
/**********************************************************************/
/* dynamic items */
varargs status add_item(string id_item, string item_str, mixed type) {
int i;
string str;
str = type +"";
switch(str) {
case "1": case "day":
if(!day_items) day_items = ({});
if((i = member_array(id_item, day_items)) != -1) return 0;
day_items += ({ id_item, item_str, });
break;
case "2": case "night":
if(!night_items) night_items = ({});
if((i = member_array(id_item, night_items)) != -1) return 0;
night_items += ({ id_item, item_str, });
break;
default:
if(!items) items = ({});
if((i = member_array(id_item, items)) != -1) return 0;
items += ({ id_item, item_str, });
break;
}
return 1;
}
varargs status remove_item(string id_item, mixed type) {
int i, size;
string str;
str = type +"";
switch(str) {
case "1": case "day":
if(!day_items) day_items = ({});
if((i=get_id_index(id_item, day_items)) == -1) return 0;
if((size = sizeof(day_items)) == 2)
day_items = ({});
else
day_items = day_items[0..i-1]+ day_items[i+2..size];
break;
case "2": case "night":
if(!night_items) night_items = ({});
if((i=get_id_index(id_item, night_items)) == -1) return 0;
if((size = sizeof(night_items)) == 2)
night_items = ({});
else
night_items = night_items[0..i-1]+ night_items[i+2..size];
break;
default:
if(!items) items = ({});
if((i=get_id_index(id_item, items)) == -1) return 0;
if((size = sizeof(items)) == 2)
items = ({});
else
items = items[0..i-1]+ items[i+2..size];
break;
}
return 1;
}
varargs status change_item(string id_item, string item_str, mixed type) {
int i;
string str;
str = type +"";
switch(str) {
case "1": case "day":
if(!day_items) day_items = ({});
if((i = get_id_index(id_item, day_items)) == -1) return 0;
day_items[i+1] = item_str;
break;
case "2": case "night":
if(!night_items) night_items = ({});
if((i = get_id_index(id_item, night_items)) == -1) return 0;
night_items[i+1] = item_str;
break;
default:
if(!items) items = ({});
if((i = get_id_index(id_item, items)) == -1) return 0;
items[i+1] = item_str;
break;
}
return 1;
}
/**********************************************************************/
/* extra objects */
status add_extra_object(string id_extra_object, string file_extra_object) {
int i;
if(!extra_objects) extra_objects = ({});
if((i = member_array(id_extra_object,extra_objects)) != -1) return 0;
extra_objects += ({ id_extra_object, file_extra_object, });
return 1;
}
status remove_extra_object(string id_extra_object) {
int i, size;
if((i=member_array(id_extra_object,extra_objects)) == -1) return 0;
if((size = sizeof(extra_objects)) == 2)
extra_objects = ({});
else
extra_objects = extra_objects[0..i-1]+extra_objects[i+2..size];
return 1;
}
status get_extra_object(string id_extra_object) {
int i;
object ob;
if(!id_extra_object) {
write("Usage: get <item>\n");
return 1;
}
if(present(id_extra_object,this_object())) return 0;
if((i = get_id_index(id_extra_object,extra_objects)) == -1) return 0;
ob = clone_object(extra_objects[i+1]);
if(!this_player()->add_weight((int)ob->query_weight())) {
write(capitalize(id_extra_object)+" is too heavy for you.\n");
destruct(ob);
return 1;
}
#ifdef NATIVE_MODE
ob->move(this_player());
#else
move_object(ob, this_player());
#endif /* NATIVE_MODE */
write("You get the "+capitalize(id_extra_object)+".\n");
say(this_player()->query_name()+" gets a "+id_extra_object+".\n");
return 1;
}
/****************************************************************************/
/* item_look */
status look_at(string str) {
int i, size;
string lock;
if(!str) return 0;
/* look thru items list */
if((i = get_id_index(str,items)) != -1) {
write(process_msg(add_newline(items[i+1])));
return 1;
}
/* look thru day items list */
if(query_day() && (i = get_id_index(str,day_items)) != -1) {
write(process_msg(add_newline(day_items[i+1])));
return 1;
}
/* look thru night items list */
if(!query_day() && (i = get_id_index(str,night_items)) != -1) {
write(process_msg(add_newline(night_items[i+1])));
return 1;
}
/* look thru extra objects */
else if((i = get_id_index(str,extra_objects)) != -1) {
call_other(extra_objects[i+1],"long");
return 1;
}
/* look in a direction */
else if(look_dir(str)) {
return 1;
}
/* look at doors */
sscanf(str,"%s on %s", lock, str);
sscanf(str,"%s on %s", lock, str);
for(i = 0, size = sizeof(doors); i < size; i++) {
if(DOOR_ID == str) {
if((SECRET_DOOR || TRAIL)
&& member_array(REAL,SECRET_DOOR_FINDERS) == -1) {
return 0; /* haven't found the secret door */
}
if(LOCK_ID && LOCK_ID == lock) {
write(process_msg(add_newline(LOCK_DESC)));
return 1;
}
if(!(str = DOOR_DESC)) {
write("It looks like a door. Perhaps you should "+
((CLOSED_FLAG) ? "open" : "close") +" it.\n");
}
else {
write(process_msg(add_newline(str)));
}
if(!CLOSED_FLAG) {
write("Through the "+ DOOR_ID +" you see,\n");
call_other(DOOR_DEST,"long");
}
else if(LOCKED_FLAG) {
write("The "+ DOOR_ID +" appears to be locked.\n");
}
return 1;
}
}
return 0; /* nothing in 'room' matching id matching 'str' */
}
/***************************************************************************/
/* load door */
void load_door(mixed *arg) {
int j, i, old_door;
string door_id;
if(!doors) doors = ({});
i = sizeof(doors);
doors += ({ allocate(DOOR_MAC_SIZE), });
CLOSED_FLAG = 1; /* default is closed */
for(j = 0; j < sizeof(arg); j++) {
if(!stringp(arg[j])) continue;
switch(arg[j]) {
case "destination": case "file": DOOR_DEST = arg[++j]; break;
case "direction": case "name": DOOR_ID = arg[++j]; break;
case "closed": CLOSED_FLAG = 1; break;
case "open": CLOSED_FLAG = 0; break;
case "locked": LOCKED_FLAG = 1; break;
case "unlocked": LOCKED_FLAG = 0; break;
case "long": case "desc": case "description": DOOR_DESC = arg[++j]; break;
case "lock id": LOCK_ID = arg[++j]; break;
case "lock description": LOCK_DESC = arg[++j]; break;
case "lock difficulty": DOOR_LOCK = arg[++j]; break;
case "key": case "key id": DOOR_KEY = arg[++j]; break;
case "secret": case "secret door": SECRET_DOOR = arg[++j]; break;
case "trail" : TRAIL = arg[++j]; break;
case "door number": case "number": DOOR_NUM = arg[++j]; break;
case "trap on": TRAP_ON = 1; break;
case "trap off": TRAP_ON = 0; break;
case "trap description": case "trap desc": TRAP_DESC = arg[++j]; break;
case "trap damage": DOOR_TRAP = arg[++j]; break;
case "trap message": DOOR_TRAP_MSG = arg[++j]; break;
case "trap room message": DOOR_TRAP_MSG_ROOM = arg[++j]; break;
case "secret door finders": SECRET_DOOR_FINDERS = arg[++j]; break;
}
}
/* defaults */
if(!DOOR_KEY) DOOR_KEY = "no_key";
if(!LOCK_ID && LOCK_DESC) LOCK_ID = "lock";
if(!DOOR_ID) DOOR_ID = "door";
if(!DOOR_DESC) DOOR_DESC = "A "+ DOOR_ID +".\n";
if(DOOR_KEY == "city key") LOCKED_FLAG = 0; /* city doors are unlocked */
/* remove old versions */
door_id = DOOR_ID;
for(j = i,i = 0; i < sizeof(doors); i++) {
if(door_id == DOOR_ID && i < j) {
old_door += 1;
}
}
while(old_door--) remove_door(door_id);
update_actions();
}
/***************************************************************************/
/* set door attribute - change an attibute on an existing door */
status set_door_attribute(mixed door_id, string attribute, mixed arg) {
int i;
string file;
status call_by_other_room;
if(!doors) doors = ({});
if(!sizeof(doors)) return 0;
if(intp(door_id)) {
if(previous_object()) {
file = file_name(previous_object());
for(i = 0; i < sizeof(doors); i++) {
if(DOOR_DEST == file && DOOR_NUM == door_id) break;
}
if(i == sizeof(doors)) return 0;
call_by_other_room = 1;
}
else {
return 0;
}
}
else { /* assume stringp */
for(i = 0; i < sizeof(doors) && DOOR_ID != door_id; i++);
if(i == sizeof(doors)) return 0;
}
switch(attribute) {
case "destination": case "file": DOOR_DEST = arg; break;
case "direction": case "name": DOOR_ID = arg; break;
case "closed": CLOSED_FLAG = 1; break;
case "open": CLOSED_FLAG = 0; break;
case "locked": LOCKED_FLAG = 1; break;
case "unlocked": LOCKED_FLAG = 0; break;
case "long": case "desc": case "description": DOOR_DESC = arg; break;
case "lock id": LOCK_ID = arg; break;
case "lock description": LOCK_DESC = arg; break;
case "lock difficulty": DOOR_LOCK = arg; break;
case "key": case "key id": DOOR_KEY = arg; break;
case "secret": case "secret door": SECRET_DOOR = arg; break;
case "secret door finders": SECRET_DOOR_FINDERS = arg; break;
case "trail" : TRAIL = arg; break;
case "trap on": TRAP_ON = 1; break;
case "trap off": TRAP_ON = 0; break;
case "trap description": case "trap desc": TRAP_DESC = arg; break;
case "trap damage": DOOR_TRAP = arg; break;
case "trap message": DOOR_TRAP_MSG = arg; break;
case "trap room message": DOOR_TRAP_MSG_ROOM = arg; break;
case "door number": DOOR_NUM = arg; break;
default:
return 0;
break;
}
if(call_by_other_room) return 1;
if(catch(call_other(DOOR_DEST,"set_door_attribute",DOOR_NUM,attribute,arg))){
write("Error loading "+ DOOR_DEST +"\n");
}
return 1;
}
/***************************************************************************/
/* query door attribute - on an existing door */
mixed query_door_attribute(string door_id, string attribute) {
int i;
if(!doors) doors = ({});
if(!sizeof(doors)) return -1;
for(i = 0; i < sizeof(doors) && DOOR_ID != door_id; i++);
if(i == sizeof(doors)) return -1;
switch(attribute) {
case "destination": case "file": return DOOR_DEST;
case "direction": case "name": return DOOR_ID;
case "closed": return CLOSED_FLAG;
case "open": return !CLOSED_FLAG;
case "locked": return LOCKED_FLAG;
case "unlocked": return !LOCKED_FLAG;
case "long": case "desc": case "description": return DOOR_DESC;
case "lock id": return LOCK_ID;
case "lock description": return LOCK_DESC;
case "lock difficulty": return DOOR_LOCK;
case "key": case "key id": return DOOR_KEY;
case "secret": case "secret door": return SECRET_DOOR;
case "trail" : return TRAIL;
case "trap on": return TRAP_ON;
case "trap off": return !TRAP_ON;
case "trap description": case "trap desc": return TRAP_DESC;
case "trap damage": return DOOR_TRAP;
case "trap message": return DOOR_TRAP_MSG;
case "trap room message": return DOOR_TRAP_MSG_ROOM;
case "door number": return DOOR_NUM;
case "secret door finders": return SECRET_DOOR_FINDERS;
default:
return -1;
break;
}
return -1;
}
/*****************************************************************/
/* remove a door from room */
status remove_door(string str) {
int i, size;
if(!str) return 0;
for(i = 0, size = sizeof(doors); i < size; i++) {
if(str == DOOR_ID) {
if(size == 1)
doors = ({});
else
doors = doors[0..i-1] + doors[i+1..size-1];
return 1;
}
}
return 0;
}
/**********************************************************************/
/* start movement thru door (from add_action) */
status door_to_move(string str) {
string direction;
int i, size;
direction = query_verb();
direction = convert_exit_name(direction);
/* default door exit appendages */
if(!str && id(direction +" door")) str = "door";
if(!str && id(direction +" gate")) str = "gate";
if(str) direction += " " + str;
for(i = 0, size = sizeof(doors); i < size; i++) {
if(direction == DOOR_ID) {
if((SECRET_DOOR || TRAIL)
&& member_array(REAL,SECRET_DOOR_FINDERS) < 0) {
return 0; /* haven't found the secret door */
}
if(CLOSED_FLAG) {
write("The "+ DOOR_ID +" is closed\n");
return 1;
}
/*** its always slower to move in stealth ***/
if(this_player()->query_stealth_on()){
write("You sneak slowly "+ direction +"...\n");
call_out("room_move", 1, DOOR_ID+"#"+DOOR_DEST);
}
else {
room_move(DOOR_ID+"#"+DOOR_DEST);
}
if(SECRET_DOOR) {
CLOSED_FLAG = 1;
CLOSE_NEXT_ROOM(1);
write("The "+DOOR_ID+" closes behind you.\n");
}
return 1;
}
}
return 0; /* nothing in that direction */
}
/***************************************************************************/
/* here */
status ob_here(string str) {
if(!str) return 0;
return (present(str) || present(str,this_player())) ? 1 : 0;
}
/***************************************************************************/
/* search room for secret doors */
int search_room(string str) {
int i, size, search;
string race;
object alt;
status found_flag; /* search finds something */
string tmp1, tmp2;
if(!str) {
notify_fail("search what?\n");
return 0;
}
search = QUERY_INT;
for(i=1; alt=present(ALT+" "+i, this_player()); i++) {
search += (int)alt->query_search_bonus();
}
for(i=1; alt=present(GUILD_OB+" "+i, this_player()); i++) {
search += (int)alt->query_search_bonus();
}
if((race = (string)this_player()->query_race())) {
if(sscanf(race,"%self%s", tmp1, tmp2)) {
search += 3; /* racial search bonus */
}
}
if(id(str)) {
if((i = get_id_index(str,search_array)) != -1) {
if(random(search_complex+1) <= random(search)) {
write(process_msg(add_newline(search_array[i+1])));
return 1;
}
}
notify_fail("You find nothing of interest.\n");
return 0;
}
else if(str != "room") {
if(present(str, this_object())) {
command("examine "+str, this_object());
return 1;
}
notify_fail("There is no "+ str +" here.\n");
return 0;
}
for(i = 0, size = sizeof(doors); i < size; i++) {
if(SECRET_DOOR) {
if(random(SECRET_DOOR) <= random(search)) {
if(member_array(REAL,SECRET_DOOR_FINDERS) < 0) {
SECRET_DOOR_FINDERS += ({ REAL, });
if(!found_flag)
write("You find a secret door!\n");
else
write("You find another secret door!\n");
found_flag = 1;
}
}
}
if(TRAIL && (int)this_player()->query_tracking()) {
if(random(TRAIL) <= random(search)) {
if(member_array(REAL, SECRET_DOOR_FINDERS) < 0) {
SECRET_DOOR_FINDERS += ({ REAL, });
if(!found_flag)
write("You found a wilderness trail!\n");
else
write("You found another wilderness trail!\n");
found_flag = 1;
}
}
}
}
if(!found_flag) {
write("You find nothing of interest.\n");
}
return 1;
}
/************************************************************************/
/* open the door */
status open(string str) {
int i, size;
if(!str) {
notify_fail("open what?\n");
return 0;
}
for(i = 0, size = sizeof(doors); i < size; i++) {
if(DOOR_ID == str) {
if((SECRET_DOOR || TRAIL)
&& member_array(REAL,SECRET_DOOR_FINDERS) == -1) {
return 0; /* its a secret door */
}
if(str == "trail") {
notify_fail("You can't open a trail.\n");
return 0;
}
if(DOOR_TRAP && TRAP_ON) { /* Is door trap set? */
TRAP_ON = 0; /* trap_flag off */
TRAP_NEXT_ROOM(0);
write(process_msg(DOOR_TRAP_MSG));
say(process_msg(DOOR_TRAP_MSG_ROOM));
if(this_object()->trap_sprung(i)) return 1;
this_player()->hit_player(DOOR_TRAP);
}
if(!CLOSED_FLAG) {
write("The "+ str +" is already open.\n");
say(NAME +" tries to open an OPEN "+ str +"!!\n");
}
else {
if(!LOCKED_FLAG || DOOR_KEY == "no_key") {
write("You open the "+ str +".\n");
say(NAME +" opens the "+ str +".\n");
CLOSED_FLAG = 0; /* open the door */
CLOSE_NEXT_ROOM(0);
}
else {
write("The "+ str +" appears to be locked.\n");
say(NAME +" cannot open the "+ str +".\n");
if(DOOR_KEY && DOOR_KEY != "no_key") {
write("There is a "+ LOCK_ID +".\n");
}
}
}
return 1;
}
}
if(id(str) || ob_here(str))
notify_fail("You can't do that!\n");
else
notify_fail("There is no "+ str +" here.\n");
return 0;
}
/***************************************************************************/
/* close the door */
status close(string str) {
int i, size;
if(!str) {
notify_fail("close what?\n");
return 0;
}
for(i = 0, size = sizeof(doors); i < size; i++) {
if(DOOR_ID == str) {
if((SECRET_DOOR || TRAIL)
&& member_array(REAL,SECRET_DOOR_FINDERS) == -1) {
return 0; /* its a secret door */
}
if(str == "trail") {
notify_fail("You can't close a trail.\n");
return 0;
}
if(DOOR_TRAP && TRAP_ON) { /* Is door trap set? */
TRAP_ON = 0; /* trap_flag off */
TRAP_NEXT_ROOM(0);
write(process_msg(DOOR_TRAP_MSG));
say(process_msg(DOOR_TRAP_MSG_ROOM));
if(this_object()->trap_sprung(i)) return 1;
this_player()->hit_player(DOOR_TRAP);
}
if(!CLOSED_FLAG) {
write("You close the "+ str +".\n");
say(NAME +" closes the "+ str +".\n");
CLOSED_FLAG = 1;
CLOSE_NEXT_ROOM(1);
}
else {
write("The "+ str +" is already closed.\n");
say(NAME +" runs into the "+ str +".\n");
}
return 1;
}
}
if(id(str) || ob_here(str))
notify_fail("You can't do that!\n");
else
notify_fail("There is no "+ str +" here.\n");
return 0;
}
/**************************************************************************/
/* lock door */
status lock(string str) {
object key;
int i;
string verb;
string key_name;
if(!str || sscanf(str,"%s with %s", str, key_name) != 2) {
notify_fail("lock <what> with <item>?\n");
return 0;
}
for(i = sizeof(doors); i--; ) {
if(DOOR_ID == str) {
if(LOCKED_FLAG) {
write("The "+ str +" is already locked.\n");
return 1;
}
if(!(key = present(key_name, this_player()))){
write("But you don't have a "+ capitalize(key_name) +"!\n");
return 1;
}
if(key->id(DOOR_KEY) || DOOR_KEY == "no_key") {
if(!CLOSED_FLAG) {
write("You close the "+ str +".\n");
CLOSED_FLAG = 1;
CLOSE_NEXT_ROOM(1);
}
write("You lock the "+ str +" with the "+ key_name +".\n");
say(NAME +" locks the "+ str +".\n");
LOCKED_FLAG = 1;
LOCK_NEXT_ROOM(1);
return 1;
}
}
}
if(id(str) || ob_here(str))
notify_fail("You can't do that!\n");
else
notify_fail("There is no "+ capitalize(str) +" here.\n");
return 0;
}
/**************************************************************************/
/* unlock door */
status unlock(string str) {
object key;
int i;
string verb;
string key_name;
if(!str || sscanf(str,"%s with %s", str, key_name) != 2) {
notify_fail("unlock <what> with <item>?\n");
return 0;
}
for(i = sizeof(doors); i--; ) {
if(DOOR_ID == str) {
if(!LOCKED_FLAG) {
write("The "+ str +" is already unlocked.\n");
return 1;
}
if(!(key = present(key_name, this_player()))){
write("But you don't have a "+ capitalize(key_name) +"!\n");
return 1;
}
if(key->id(DOOR_KEY) || DOOR_KEY == "no_key") {
write("You unlock the "+ str +" with the "+ key_name +".\n");
say(NAME +" unlocks the "+ str +".\n");
LOCKED_FLAG = 0;
LOCK_NEXT_ROOM(0);
return 1;
}
}
}
if(id(str) || ob_here(str))
notify_fail("You can't do that!\n");
else
notify_fail("There is no "+ capitalize(str) +" here.\n");
return 0;
}
/**************************************************************************/
/* pick lock */
status pick_lock(string str) {
object ob;
int i, j;
if(QUERY_LOCKS == 0) {
notify_fail("You do not have the skill to pick locks.\n");
return 0;
}
if(!str || sscanf(str,"lock on %s",str) != 1) {
notify_fail("pick lock on what?\n");
return 0;
}
for(i = sizeof(doors); i--; ) {
if(DOOR_ID == str) {
if(SECRET_DOOR && member_array(REAL,SECRET_DOOR_FINDERS) == -1) {
return 0; /* its a secret door */
}
if(DOOR_TRAP && TRAP_ON) { /* Is door trap set? */
TRAP_ON = 0; /* trap_flag off */
TRAP_NEXT_ROOM(0);
write(process_msg(DOOR_TRAP_MSG));
say(process_msg(DOOR_TRAP_MSG_ROOM));
if(this_object()->trap_sprung(i)) return 1;
this_player()->hit_player(DOOR_TRAP);
}
if(!CLOSED_FLAG) {
write("You close the "+ DOOR_ID +".\n");
CLOSED_FLAG = 1;
CLOSE_NEXT_ROOM(1);
}
write("You attempt to pick the lock.\n");
if(!lock_attempts) lock_attempts = ({});
if((j = member_array(str,lock_attempts)) == -1) {
lock_attempts += ({ str, ({}), });
j = member_array(str, lock_attempts);
}
if(member_array(REAL, lock_attempts[j+1]) != -1) {
write("You give up...\n");
return 1;
}
if(member_array(CAP, lock_attempts) != -1 ||
random(QUERY_LOCKS+1) >= random(DOOR_LOCK+1)) {
LOCKED_FLAG = !LOCKED_FLAG;
tell_room(environment(this_player()),"Click!\n");
write("You "+((LOCKED_FLAG) ? "" : "un")+"lock the "+ DOOR_ID +".\n");
if(member_array(CAP, lock_attempts[j+1]) == -1) {
lock_attempts[j+1] += ({ CAP, });
}
}
else {
write("You give up...\n");
lock_attempts += ({ REAL, });
}
NEXT_ROOM_LOCKS();
return 1;
}
}
if(id(str) || ob_here(str))
notify_fail("You can't do that!\n");
else
notify_fail("There is no "+ str +" here.\n");
return 0;
}
/**************************************************************************/
/* disarm door trap */
status disarm_trap(string str) {
int i, j;
if(!str || sscanf(str,"trap on %s",str) != 1) {
notify_fail("disarm trap on what?\n");
return 0;
}
if(!detect_attempts) detect_attempts = ({});
if((i = member_array(str, detect_attempts)) == -1 ||
(member_array(REAL,detect_attempts[i+1]) == -1
&& member_array(CAP,detect_attempts[i+1]) == -1)) {
notify_fail("You have to detect a trap before you can disarm it.\n");
return 0;
}
if(member_array(REAL,detect_attempts[i+1]) != -1) {
write("You have not found a trap to disarm.\n");
return 1;
}
if(!disarm_attempts) disarm_attempts = ({});
if((j = member_array(str, disarm_attempts)) == -1) {
disarm_attempts += ({ str, ({}), });
j = member_array(str, disarm_attempts);
}
if(member_array(REAL, disarm_attempts[j+1]) != -1) {
write("You think you have disarmed it already.\n");
return 1;
}
for(i = sizeof(doors); i--; ) {
if(DOOR_ID == str) {
if(random(DOOR_LOCK+1) <= random(QUERY_LOCKS+1)) {
TRAP_ON = 0;
TRAP_NEXT_ROOM(0);
}
write("You think you have disarmed the trap.\n");
break;
}
}
disarm_attempts[j+1] += ({ REAL, });
NEXT_ROOM_DISARMS();
return 1;
}
/***************************************************************************/
/* arm door trap */
status arm_trap(string str) {
int i, j, k;
string door_id;
if(!str || sscanf(str,"trap on %s",str) != 1) {
notify_fail("arm trap on what?\n");
return 0;
}
if(!detect_attempts) detect_attempts = ({});
if((k = member_array(str, detect_attempts)) == -1 ||
(member_array(REAL,detect_attempts[k+1]) == -1
&& member_array(CAP,detect_attempts[k+1]) == -1)) {
notify_fail("You have to detect any traps first.\n");
return 0;
}
if(member_array(REAL,detect_attempts[k+1]) != -1) {
write("You have not found a trap to arm.\n");
return 1;
}
if(!disarm_attempts) disarm_attempts = ({});
if((j = member_array(str, disarm_attempts)) == -1) {
disarm_attempts += ({ str, ({}), });
j = member_array(str, disarm_attempts);
}
for(i = sizeof(doors); i--; ) {
if(DOOR_ID == str) {
if(random(DOOR_LOCK+1) <= random(QUERY_LOCKS+1)) {
TRAP_ON = 1;
TRAP_NEXT_ROOM(1);
disarm_attempts[j+1] = ({});
detect_attempts[k+1] = ({ CAP, });
write("You arm the trap.\n");
NEXT_ROOM_DISARMS();
NEXT_ROOM_DETECTS();
}
else {
TRAP_ON = 0; /* trap_flag off */
TRAP_NEXT_ROOM(0);
write(process_msg(DOOR_TRAP_MSG));
say(process_msg(DOOR_TRAP_MSG_ROOM));
if(this_object()->trap_sprung(i)) return 1;
this_player()->hit_player(DOOR_TRAP);
}
return 1;
}
}
return 1;
}
/**********************************************************************/
/* detect door trap */
status detect(string str) {
int i, j;
if(QUERY_TRAPS == 0) {
notify_fail("You do not have the skill to detect traps.\n");
return 0;
}
if(!str || sscanf(str,"trap on %s",str) != 1) {
notify_fail("detect trap on what?\n");
return 0;
}
say(this_player()->query_name()+" examines the door for traps.\n");
for(i = sizeof(doors); i--; ) {
if(DOOR_ID == str) {
if(SECRET_DOOR && member_array(REAL,SECRET_DOOR_FINDERS) == -1) {
break; /* its a secret door */
}
if(!detect_attempts) detect_attempts = ({});
if((j = member_array(str,detect_attempts)) == -1) {
detect_attempts += ({ str, ({}), });
j = member_array(str, detect_attempts);
}
if(!DOOR_TRAP || member_array(REAL,detect_attempts[j+1]) != -1) {
write("There are no traps that you can detect.\n");
if(member_array(REAL, detect_attempts[j+1]) == -1) {
detect_attempts[j+1] += ({ REAL, });
}
return 1;
}
if(member_array(CAP,detect_attempts[j+1]) != -1) {
write(process_msg(TRAP_DESC));
return 1;
}
if(random(DOOR_LOCK+1) <= random(QUERY_TRAPS+1)) {
TRAP_ON = 0;
TRAP_NEXT_ROOM(0);
detect_attempts[j+1] += ({ CAP, });
write(process_msg(TRAP_DESC));
}
NEXT_ROOM_DETECTS();
return 1;
}
}
if(id(str) || ob_here(str))
notify_fail("You can't do that!\n");
else
notify_fail("There is no "+ str +" here.\n");
return 0;
}
/***************************************************************************/
/* set door trap flag */
varargs status set_door_trap(string filename, status trap, int door_num) {
int i, size;
for(i = 0, size = sizeof(doors); i < size; i++) {
if(DOOR_DEST == filename) {
if(door_num != DOOR_NUM) continue;
TRAP_ON = trap;
return 1;
}
}
return 0;
}
/**************************************************************************/
/* set door closed flag */
varargs status set_door_closed(string filename, status close, int door_num) {
int i, size;
for(i = 0, size = sizeof(doors); i < size; i++) {
if(DOOR_DEST == filename) {
if(door_num != DOOR_NUM) continue;
CLOSED_FLAG = close;
tell_room(this_object(),
"The "+DOOR_ID+((close) ? " closes" : " opens")+".\n");
return 1;
}
}
return 0;
}
/**************************************************************************/
/* set door locked flag */
varargs status set_door_lock(string filename, status locked, int door_num) {
int i, size;
for(i = 0, size = sizeof(doors); i < size; i++) {
if(DOOR_DEST == filename) {
if(door_num != DOOR_NUM) continue;
LOCKED_FLAG = locked;
tell_room(this_object(),"Click!.\n");
return 1;
}
}
return 0;
}
/***************************************************************************/
/* close all doors */
void reset_doors(status arg) {
int i, size;
object room;
if(!doors) doors = ({});
for(i = 0, size = sizeof(doors); i < size; i++) {
TRAP_ON = 1;
TRAP_NEXT_ROOM(1);
CLOSED_FLAG = 1;
CLOSE_NEXT_ROOM(1);
LOCKED_FLAG = (DOOR_KEY == "city key") ? 0 : 1;
LOCK_NEXT_ROOM(LOCKED_FLAG);
detect_attempts = ({});
NEXT_ROOM_DETECTS();
disarm_attempts = ({});
NEXT_ROOM_DISARMS();
lock_attempts = ({});
NEXT_ROOM_LOCKS();
if(arg) SECRET_DOOR_FINDERS = ({});
}
}
/***************************************************************************/
/* get index */
int get_id_index(string str,string *arr) {
int i;
string *ids;
if(!arr) return -1;
for(i = 0; i < sizeof(arr); i += 2) {
if(!arr[i]) continue;
#ifdef OLD_EXPLODE
ids = explode(arr[i]+"#", "#");
#else
ids = explode(arr[i], "#");
#endif
if(member_array(str,ids) != -1) return i;
}
return -1;
}
/****************************************************************************/
/* set_sign */
varargs void set_sign_message(string str, string lang) {
object obj;
if(!str) return;
obj = clone_object("inherit/sign");
obj->set_message(str);
if(lang) obj->set_language(lang);
#ifdef NATIVE_MODE
obj->move(this_object());
#else
move_object(obj, this_object());
#endif /* NATIVE_MODE */
}
string query_name() { return file_name(this_object()); }
status can_put_and_get() { return 1; }