#include <kernel/kernel.h>
#include <phantasmal/exit.h>
#include <phantasmal/log.h>
#include <phantasmal/phrase.h>
#include <phantasmal/map.h>
#include <phantasmal/obj_flags.h>
#include <phantasmal/lpc_names.h>
#include <type.h>
inherit OBJECT;
/* exit.c
Inherited by any exit type. An object which is an exit might contain
or inherit from one, though that design isn't set in stone yet...
*/
int direction; /* 8 compass directions */
int type; /* one-way, two-way, etc. */
int link_to; /* exit # that a two-way links to */
object from_location;
object destination;
/* Object flags uses flag values in obj_flags.h */
private int objflags;
static void create(varargs int clone) {
::create(clone);
if(clone) {
}
}
void upgraded(varargs int clone) {
::upgraded(clone);
}
void destructed(int clone) {
::destructed(clone);
}
void set_direction(int new_dir) {
if(previous_program() == EXITD) {
direction = new_dir;
} else error("Only EXITD can set exit directions!");
}
void set_from_location(object new_loc) {
if(previous_program() == EXITD) {
from_location = new_loc;
} else error("Only EXITD can set exit from locations!");
}
void set_destination(object new_dest) {
if(previous_program() == EXITD) {
destination = new_dest;
} else error("Only EXITD can set exit destinations!");
}
void set_exit_type(int new_type) {
if(previous_program() == EXITD) {
switch (new_type) {
case ET_ONEWAY:
case ET_TWOWAY:
type = new_type;
break;
default: /* unknown type */
type = ET_TWOWAY;
break;
}
} else error("Only EXITD can set exit types!");
}
void set_link(int new_link) {
if(previous_program() == EXITD) {
link_to = new_link;
} else error("Only EXITD can set links!");
}
int get_direction() {
return direction;
}
int get_exit_type() {
return type;
}
int get_link() {
return link_to;
}
object get_from_location() {
return from_location;
}
object get_destination() {
return destination;
}
/*
* string to_unq_flags(void)
*
* creates a string out of the object flags.
*/
static string to_unq_flags(void) {
object dest, shortphr, other_exit;
string ret, tmp_n, tmp_a;
int locale, opp_dir;
string** nouns, **adjectives;
ret = "";
dest = get_destination();
shortphr = EXITD->get_short_for_dir(get_direction());
ret += " ~rnumber{" + get_number() + "}\n"
+ " ~direction{" + get_direction() + "}\n"
+ " ~destination{" + dest->get_number() + "}\n"
+ " ~return{";
if(get_link() > 0 && dest) {
opp_dir = EXITD->opposite_direction(get_direction());
other_exit = dest->get_exit(opp_dir);
if(!other_exit) {
LOGD->write_syslog("Problem finding return exit!", LOG_WARN);
} else {
ret += other_exit->get_number() + "}\n";
}
} else {
ret += "-1}\n";
}
ret += " ~type{" + get_exit_type() + "}\n";
if(bdesc) {
ret += " ~rbdesc{" + bdesc->to_unq_text() + "}\n";
}
if(ldesc) {
ret += " ~rldesc{" + ldesc->to_unq_text() + "}\n";
}
if(edesc) {
ret += " ~redesc{" + edesc->to_unq_text() + "}\n";
}
/* Skip debug locale */
tmp_n = tmp_a = "";
nouns = get_immediate_nouns();
adjectives = get_immediate_adjectives();
for(locale = 1; locale < sizeof(nouns); locale++) {
if(sizeof(nouns[locale])) {
tmp_n += "~" + PHRASED->locale_name_for_language(locale) + "{"
+ implode(nouns[locale], ",") + "}";
}
if(sizeof(adjectives[locale])) {
tmp_a += "~" + PHRASED->locale_name_for_language(locale) + "{"
+ implode(adjectives[locale], ",") + "}";
}
}
/* The double-braces are intentional -- this uses the efficient
method of specifying nouns and adjectives rather than the human-
friendly one. */
if(tmp_n && tmp_n!="") {
ret += " ~rnouns{{" + tmp_n + "}}\n";
}
if(tmp_a && tmp_a!="") {
ret += " ~radjectives{{" + tmp_a + "}}\n";
}
ret += " ~rflags{" + objflags + "}";
return ret;
}
/*
* void from_dtd_flags(mixed *unq)
*
* loads data from the unq parsed with a room-derived dtd.
*/
static void from_dtd_tag(string tag, mixed value) {
int ctr;
if (tag=="rnumber") {
tr_num = value;
} else if (tag=="direction") {
direction = value;
} else if (tag=="destination") {
destination = value;
} else if (tag=="return") {
link_to = value;
} else if (tag=="type") {
type = value;
} else if (tag=="rbdesc") {
bdesc = value;
} else if (tag=="rldesc") {
ldesc = value;
} else if (tag=="redesc") {
edesc = value;
} else if (tag=="rflags") {
objflags = value;
} else if(tag=="rnouns") {
for(ctr = 0; ctr < sizeof(value); ctr++) {
add_noun(value[ctr]);
}
} else if(tag=="radjectives") {
for(ctr = 0; ctr < sizeof(value); ctr++) {
add_adjective(value[ctr]);
}
}
}
/*
* flag overrides
*/
int is_container() {
return objflags & OF_CONTAINER;
}
int is_open() {
return objflags & OF_OPEN;
}
int is_openable() {
return objflags & OF_OPENABLE;
}
int is_locked() {
return objflags & OF_LOCKED;
}
int is_lockable() {
return objflags & OF_LOCKABLE;
}
private void set_flags(int flags, int value) {
if(value) {
objflags |= flags;
} else {
objflags &= ~flags;
}
}
void set_all_flags(int flags) {
if(previous_program() != EXITD)
error("Only EXITD may set_all_flags!");
objflags = flags;
}
/* These may seem a little weird. The problem is, we need to access
* a different objects private function. The recursion takes care
* of this for us. I use get_link()>0 because == -1 for one-way and
* ==0 for non-existent link. */
void set_container(int value) {
object link_exit;
if(!SYSTEM() && !COMMON())
error("Only SYSTEM code can currently set an object as a container!");
if (get_link()>0 && previous_program() != EXIT) {
link_exit = EXITD->get_exit_by_num(get_link());
link_exit->set_container(value);
}
set_flags(OF_CONTAINER, value);
}
void set_open(int value) {
object link_exit;
string err;
if(!SYSTEM() && !COMMON())
error("Only SYSTEM code can currently set an object as open!");
if (get_link()>0 && previous_program() != EXIT) {
link_exit = EXITD->get_exit_by_num(get_link());
link_exit->set_open(value);
}
set_flags(OF_OPEN, value);
}
void set_openable(int value) {
object link_exit;
if(!SYSTEM() && !COMMON())
error("Only SYSTEM code can currently set an object as openable!");
if (get_link()>0 && previous_program() != EXIT) {
link_exit = EXITD->get_exit_by_num(get_link());
link_exit->set_openable(value);
}
set_flags(OF_OPENABLE, value);
}
void set_locked(int value) {
object link_exit;
if(!SYSTEM() && !COMMON())
error("Only SYSTEM code can currently set an object as a container!");
if (get_link()>0 && previous_program() != EXIT) {
link_exit = EXITD->get_exit_by_num(get_link());
link_exit->set_locked(value);
}
set_flags(OF_LOCKED, value);
}
void set_lockable(int value) {
object link_exit;
if(!SYSTEM() && !COMMON())
error("Only SYSTEM code can currently set an object as open!");
if (get_link()>0 && previous_program() != EXIT) {
link_exit = EXITD->get_exit_by_num(get_link());
link_exit->set_lockable(value);
}
set_flags(OF_LOCKABLE, value);
}
/* Return nil if a user can pass through a door, the reason if they cannot */
string can_pass(object user, object pass_object) {
if (!is_open())
return "The door is closed.";
}
/* Called when a user passes through the exit */
void pass(object pass_object) {
}