MudOSa4DGD/
MudOSa4DGD/bin/
MudOSa4DGD/data/
MudOSa4DGD/doc/
MudOSa4DGD/doc/driver/
MudOSa4DGD/doc/efun/bitstrings/
MudOSa4DGD/doc/efun/command/
MudOSa4DGD/doc/efun/communication/
MudOSa4DGD/doc/efun/heart_beat/
MudOSa4DGD/doc/efun/interactive/
MudOSa4DGD/doc/efun/inventory/
MudOSa4DGD/doc/efun/living/
MudOSa4DGD/doc/efun/mappings/
MudOSa4DGD/doc/efun/strings/
MudOSa4DGD/doc/efun/uid/
MudOSa4DGD/doc/funs/
MudOSa4DGD/doc/language/
MudOSa4DGD/mudlib/dgd/doc/
MudOSa4DGD/mudlib/dgd/lib/include/dgd/
MudOSa4DGD/mudlib/dgd/lib/std/
MudOSa4DGD/mudlib/dgd/lib/sys/
MudOSa4DGD/mudlib/dgd/log/
MudOSa4DGD/mudlib/log/
MudOSa4DGD/mudlib/std/include/
MudOSa4DGD/mudlib/std/obj/
/*
 * inventory.c
 *
 * Handle that every objects should have an inventory and environment
 *
 * (C) Frank Schmidt, Jesus@NorseMUD
 *
 */

private static object env, *inv;


/* return environment */
nomask object __query_environment() {
  return env;
}

/* return inventory */
nomask object *__query_inventory() {
  if (arrayp(inv)) {
    /* clean up */
    inv -= ({ 0 });
    return copy(inv);
  }
  return ({ });
}


#ifdef MUDOS_INVENTORY_INDEX

/* return inventory by index*/
nomask object __query_inventory_index(int i) {
  if (arrayp(inv)) {
    int sz;
    /* clean up */
    inv -= ({ 0 });
    if ((sz=::sizeof(inv)) && i < sz)
      return inv[i];
  }
  return 0;
}

#endif


/* return deep-inventory */
nomask object *__query_deep_inventory() {
  if (arrayp(inv)) {
    /* clean up */
    int i;
    object *di;
    di = (inv -= ({ 0 }));
    /* return our + nested inventory */
    for (i=::sizeof(inv); --i >= 0; )
      catch(di += call_other(inv[i], "__query_deep_inventory"));
    return di;
  }
  return ({ });
}



/* return environment of an object */
static varargs object environment(object ob) {
  if (!ob) return env;
  return ob->__query_environment();
}


/* return inventory of an object */
static varargs object *all_inventory(object ob) {
  if (!ob) return __query_inventory();
  return ob->__query_inventory();
}


#ifdef MUDOS_INVENTORY_INDEX

/* return element in inventory according to index i */
static varargs object inventory_index(object ob, int i) {
  if (!ob) return __query_inventory_index(i);
  return ob->__query_inventory_index(i);
}

#endif


/* return deep-inventory of an object */
static varargs object *deep_inventory(object ob) {
  if (!ob) return __query_deep_inventory();
  return ob->__query_deep_inventory();
}



/* delete <ob> from inventory (used by move-func) */
nomask void __del_inventory(object ob) {
  /* don't allow anything but move to call this */
  if (AUTO_PRIV()) {
    if (arrayp(inv)) {
      /* clean up array */
      if (!::sizeof(inv -= ({ ob })))
	inv = 0;
    }
  }
}
  
/* add <ob> to inventory (used by move-func) */
nomask void __add_inventory(object ob) {
  /* don't allow anything but move to call this */
  if (AUTO_PRIV()) {
    if (arrayp(inv))
      inv += ({ ob });
    else
      inv = ({ ob });
  }
}



/* move this object to a destination */
varargs int __MOVE_DEF(object dest) {
  object oldply;
  object *envs;
  int i;

  if (!dest)
    /* ob->move() moved it to current object */
    dest = previous_object();

  if (dest) {
    if (dest == this_object()) {
      /* fy fy! */
      error("Can't move object inside itself");
      return 1;
    }
    /* moving to an object inside us? */
    if (member_array(dest, __query_deep_inventory()) != -1) {
      /* we solve it by "dropping" our stuff */
      for (i=::sizeof(inv); --i >= 0; )
	catch(call_other(inv[i], __MOVE_FUNC, env));
    }
  }
  else
    error("Bad argument 1 to move()");

  /* delete us from old environment */
  if (env) {
    env->__del_inventory(this_object());
  }

  /* assign us to new environment */
  env = dest;

  /* add us to new environment */
  if (env) {
    env->__add_inventory(this_object());
  }


#ifdef MUDOS_LIVING
  /* check for livings and if we should call init() */
  envs = all_inventory(env);
  oldply=this_player();
  if (living(this_object())) {
    /* call init in destination */
    GLOBAL->set_this_player(this_object());
    /* call init in environment() and objects in environment() */
    catch(call_other(env, __INIT_FUNC));
    for (i=::sizeof(envs); --i >= 0; )
      catch(call_other(envs[i], __INIT_FUNC));
  }

  /* call init in this_object() from all livings at destination */
  map_array(filter_array(envs, "isliving", GLOBAL),
               "do_init", GLOBAL, oldply);

  /* reset correct this_player() (removing priv. level) */
  GLOBAL->set_this_player(oldply);
#endif

  /* move succeded */
  return 0;
}


#ifdef MUDOS_MOVE_OBJECT

/* efun move_object, a bit more liberal than move() */
static varargs int move_object(mixed file, mixed dest) {
  object ob;
  mixed ret;
  if (!dest) {
    /* one arg only */
    dest = file;
    ob = this_object();
  }
  else {
    if (stringp(file)) {
      if (!(ob=find_object(file)))
	ob = compile_object(file);
    }
    else
      ob = file;
  }
  if (stringp(dest)) {
    if (!(dest=find_object(file=dest)))
      dest = compile_object(file);
  }

  if (ob) {
    /* perform the move */
    catch(ret=call_other(ob, __MOVE_FUNC, dest));
    return ret;
  }
  return 0;
}

#endif