/* Copyright 1989, 1990 by James Aspnes, David Applegate, and Bennet Yee */
/* See the file COPYING for distribution information */
#include <ctype.h>
#include "db.h"
#include "globals.h"
#include "externs.h"
extern set get_contents (datum);
datum lookup (datum obj, datum var)
{
struct object *o;
datum value;
/* handle special cases */
if (var < FIXED_STRINGS) {
if ((o = object (obj)) == 0) {
return NOTHING;
} else if (isflagname (var)) {
return flag_set (obj, name2flag (var));
} else
switch (var) {
case OWNER_NAME:
return o->owner;
case PARENT_NAME:
return o->parent;
default:
/* fall through, not special */
break;
}
}
while ((o = object (obj)) != 0) {
if (assoc (o->vars, var, &value))
return value;
else
obj = o->parent;
}
return NOTHING;
}
datum set_variable (datum obj, datum var, datum value)
{
struct object *o;
datum flag;
set loc_contents;
if (!controls (me, obj)
|| (o = object (obj)) == 0)
return 0;
/* handle special cases */
if (var < FIXED_STRINGS) {
if (isflagname (var)) {
flag = name2flag (var);
switch (flag) {
case F_ADMIN:
return 0; /* can't change admin status */
case F_WIZARD:
case F_CONNECTED:
if (!flag_set (me, F_ADMIN))
return 0;
break;
case F_PLAYER:
case F_BUILDER:
case F_PROGRAMMER:
if (!flag_set (me, F_WIZARD))
return 0;
break;
default:
break;
}
/* permission ok, do it */
if (value) {
o->flags |= flag;
} else {
o->flags &= ~flag;
}
return 1;
} else
switch (var) {
case OWNER_NAME:
if (!flag_set (me, F_WIZARD)) {
return 0;
} else {
o->owner = value;
return 1;
}
case PARENT_NAME:
if (is_ancestor (value, obj)) {
/* we'd create a loop */
return 0;
} else {
o->parent = value;
return 1;
}
case ALIASES_NAME:
/* nuke the name list on our location's contents */
/* other lists will just have to lose until the next GC pass */
if ((loc_contents = get_contents (o->location)) != 0) {
set_clear_name_list (loc_contents);
}
/* fall through to normal variable set */
break;
default:
/* nothing special, fall through */
break;
}
}
gc_mark_string (var); /* for incremental gc */
o->vars = set_assoc (o->vars, var, value);
return 1;
}
datum unset (datum obj, datum var)
{
struct object *o;
if (var < FIXED_STRINGS) {
/* let set_variable deal with it */
return set_variable (obj, var, NOTHING);
} else if (!controls (me, obj) || (o = object (obj)) == 0) {
return 0; /* no such object as far as I'm concerned */
} else {
/* it's real, nuke it */
o->vars = del_assocs (o->vars, var);
return 1;
}
}
datum lookup_action (datum obj, datum verb)
{
struct object *o;
datum value;
while ((o = object (obj)) != 0) {
if (assoc (o->actions, verb, &value))
return value;
else
obj = o->parent;
}
return NOTHING;
}
datum set_string (datum obj, datum var, datum value)
{
gc_mark_string (value);
return set_variable (obj, var, value);
}
datum set_action (datum obj, datum verb, datum value)
{
struct object *o;
if (controls (me, obj)
&& (o = object (obj)) != 0) {
gc_mark_string (verb);
gc_mark_string (value);
o->actions = set_assoc (o->actions, verb, value);
return 1;
} else {
return 0;
}
}
datum unset_action (datum obj, datum verb)
{
struct object *o;
if (controls (me, obj)
&& (o = object (obj)) != 0) {
o->actions = del_assocs (o->actions, verb);
return 1;
} else {
return 0;
}
}
static set lookup_setvar_internal (struct object *o, datum var)
{
datum value;
if (assoc (o->sets, var, &value)) {
return ((set) value);
} else {
return empty_set ();
}
}
set lookup_setvar (datum obj, datum var)
{
struct object *o;
if ((o = object (obj)) != 0) {
return lookup_setvar_internal (o, var);
} else {
return empty_set ();
}
}
/* no permissions checks */
datum add_to_internal (datum obj, datum var, datum value)
{
struct object *o;
if ((o = object (obj)) != 0) {
o->sets =
set_assoc (o->sets, var,
(datum) add_member (lookup_setvar_internal (o, var), value));
gc_mark_string (var);
return 1;
} else {
return 0;
}
}
datum add_to (datum obj, datum var, datum value)
{
if (controls (me, obj) && var != CONTENTS_NAME) {
return add_to_internal (obj, var, value);
} else {
return 0;
}
}
/* no permissions checks */
datum take_from_internal (datum obj, datum var, datum value)
{
struct object *o;
if ((o = object (obj)) != 0) {
o->sets =
set_assoc (o->sets, var,
(datum) del_member (lookup_setvar_internal (o, var), value));
return 1;
}
return 0;
}
datum take_from (datum obj, datum var, datum value)
{
if (controls (me, obj) && var != CONTENTS_NAME) {
return take_from_internal (obj, var, value);
} else {
return 0;
}
}
datum clear_set_var (datum obj, datum var)
{
datum value;
struct object *o;
if (controls (me, obj)
&& (o = object (obj)) != 0) {
if (assoc (o->sets, var, &value)) {
free_set ((set) value);
o->sets = del_assocs (o->sets, var);
}
return 1;
}
return 0;
}
datum contains (datum obj, datum setvar, datum thing)
{
return member (lookup_setvar (obj, setvar), thing);
}
datum count_set_var (datum obj, datum setvar)
{
set s;
s = lookup_setvar (obj, setvar);
return set_empty (s) ? 0 : set_count (s);
}
set get_contents (datum obj)
{
return lookup_setvar (obj, CONTENTS_NAME);
}