skylib_fluffos_v3/
skylib_fluffos_v3/bin/
skylib_fluffos_v3/bin/db/
skylib_fluffos_v3/fluffos-2.9-ds2.04/
skylib_fluffos_v3/fluffos-2.9-ds2.04/ChangeLog.old/
skylib_fluffos_v3/fluffos-2.9-ds2.04/Win32/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/simuls/
skylib_fluffos_v3/fluffos-2.9-ds2.04/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/clone/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/command/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/data/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/etc/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/master/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/log/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/compiler/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/efuns/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/operators/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/u/
skylib_fluffos_v3/fluffos-2.9-ds2.04/tmp/
skylib_fluffos_v3/fluffos-2.9-ds2.04/windows/
skylib_fluffos_v3/mudlib/
skylib_fluffos_v3/mudlib/cmds/
skylib_fluffos_v3/mudlib/cmds/admin/
skylib_fluffos_v3/mudlib/cmds/guild-race/
skylib_fluffos_v3/mudlib/cmds/living/broken/
skylib_fluffos_v3/mudlib/cmds/player/group_cmds/
skylib_fluffos_v3/mudlib/cmds/playtester/
skylib_fluffos_v3/mudlib/d/admin/
skylib_fluffos_v3/mudlib/d/admin/room/
skylib_fluffos_v3/mudlib/d/admin/room/we_care/
skylib_fluffos_v3/mudlib/d/admin/save/
skylib_fluffos_v3/mudlib/d/admin/text/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/buildings/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/map/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/roads/
skylib_fluffos_v3/mudlib/d/learning/chars/
skylib_fluffos_v3/mudlib/d/learning/functions/
skylib_fluffos_v3/mudlib/d/learning/handlers/
skylib_fluffos_v3/mudlib/d/learning/help_topics/
skylib_fluffos_v3/mudlib/d/learning/help_topics/npcs/
skylib_fluffos_v3/mudlib/d/learning/help_topics/objects/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/RCS/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/crowd/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/situations/
skylib_fluffos_v3/mudlib/d/learning/save/
skylib_fluffos_v3/mudlib/d/learning/school/
skylib_fluffos_v3/mudlib/d/learning/school/add_sc/
skylib_fluffos_v3/mudlib/d/learning/school/characters/
skylib_fluffos_v3/mudlib/d/learning/school/general/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/basic_commands/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/edtutor/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/unix_tutor/
skylib_fluffos_v3/mudlib/d/learning/school/items/
skylib_fluffos_v3/mudlib/d/learning/school/npc_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/room_basic/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/situations/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/terrain_tutor/
skylib_fluffos_v3/mudlib/d/learning/text/
skylib_fluffos_v3/mudlib/d/liaison/
skylib_fluffos_v3/mudlib/d/mudlib/
skylib_fluffos_v3/mudlib/d/mudlib/changes/
skylib_fluffos_v3/mudlib/d/playtesters/
skylib_fluffos_v3/mudlib/d/playtesters/effects/
skylib_fluffos_v3/mudlib/d/playtesters/handlers/
skylib_fluffos_v3/mudlib/d/playtesters/items/
skylib_fluffos_v3/mudlib/d/sage/
skylib_fluffos_v3/mudlib/doc/
skylib_fluffos_v3/mudlib/doc/creator/
skylib_fluffos_v3/mudlib/doc/driver/
skylib_fluffos_v3/mudlib/doc/driver/efuns/arrays/
skylib_fluffos_v3/mudlib/doc/driver/efuns/buffers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/calls/
skylib_fluffos_v3/mudlib/doc/driver/efuns/compile/
skylib_fluffos_v3/mudlib/doc/driver/efuns/filesystem/
skylib_fluffos_v3/mudlib/doc/driver/efuns/floats/
skylib_fluffos_v3/mudlib/doc/driver/efuns/functions/
skylib_fluffos_v3/mudlib/doc/driver/efuns/general/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mappings/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mixed/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mudlib/
skylib_fluffos_v3/mudlib/doc/driver/efuns/numbers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/parsing/
skylib_fluffos_v3/mudlib/doc/login/
skylib_fluffos_v3/mudlib/doc/lpc/basic_manual/
skylib_fluffos_v3/mudlib/doc/lpc/intermediate/
skylib_fluffos_v3/mudlib/doc/new/add_command/
skylib_fluffos_v3/mudlib/doc/new/events/
skylib_fluffos_v3/mudlib/doc/new/handlers/
skylib_fluffos_v3/mudlib/doc/new/living/race/
skylib_fluffos_v3/mudlib/doc/new/living/spells/
skylib_fluffos_v3/mudlib/doc/new/object/
skylib_fluffos_v3/mudlib/doc/new/player/
skylib_fluffos_v3/mudlib/doc/new/room/guild/
skylib_fluffos_v3/mudlib/doc/new/room/outside/
skylib_fluffos_v3/mudlib/doc/new/room/storeroom/
skylib_fluffos_v3/mudlib/doc/object/
skylib_fluffos_v3/mudlib/doc/playtesters/
skylib_fluffos_v3/mudlib/doc/policy/
skylib_fluffos_v3/mudlib/doc/weapons/
skylib_fluffos_v3/mudlib/global/
skylib_fluffos_v3/mudlib/global/creator/
skylib_fluffos_v3/mudlib/handlers/
skylib_fluffos_v3/mudlib/include/casino/
skylib_fluffos_v3/mudlib/include/cmds/
skylib_fluffos_v3/mudlib/include/effects/
skylib_fluffos_v3/mudlib/include/npc/
skylib_fluffos_v3/mudlib/include/room/
skylib_fluffos_v3/mudlib/include/shops/
skylib_fluffos_v3/mudlib/net/daemon/
skylib_fluffos_v3/mudlib/net/daemon/chars/
skylib_fluffos_v3/mudlib/net/inherit/
skylib_fluffos_v3/mudlib/net/obj/
skylib_fluffos_v3/mudlib/net/obj/BACKUPS/
skylib_fluffos_v3/mudlib/obj/amulets/
skylib_fluffos_v3/mudlib/obj/armours/plate/
skylib_fluffos_v3/mudlib/obj/b_day/
skylib_fluffos_v3/mudlib/obj/clothes/transport/horse/
skylib_fluffos_v3/mudlib/obj/faith/symbols/
skylib_fluffos_v3/mudlib/obj/fungi/
skylib_fluffos_v3/mudlib/obj/gatherables/
skylib_fluffos_v3/mudlib/obj/instruments/
skylib_fluffos_v3/mudlib/obj/media/
skylib_fluffos_v3/mudlib/obj/misc/player_shop/
skylib_fluffos_v3/mudlib/obj/monster/godmother/
skylib_fluffos_v3/mudlib/obj/monster/transport/
skylib_fluffos_v3/mudlib/obj/rings/
skylib_fluffos_v3/mudlib/obj/scabbards/
skylib_fluffos_v3/mudlib/obj/spells/
skylib_fluffos_v3/mudlib/obj/stationery/
skylib_fluffos_v3/mudlib/obj/stationery/envelopes/
skylib_fluffos_v3/mudlib/obj/toys/
skylib_fluffos_v3/mudlib/obj/vessels/
skylib_fluffos_v3/mudlib/obj/weapons/axes/
skylib_fluffos_v3/mudlib/obj/weapons/chains/
skylib_fluffos_v3/mudlib/obj/weapons/maces/BACKUPS/
skylib_fluffos_v3/mudlib/save/autodoc/
skylib_fluffos_v3/mudlib/save/book_handler/
skylib_fluffos_v3/mudlib/save/books/history/calarien/
skylib_fluffos_v3/mudlib/save/mail/
skylib_fluffos_v3/mudlib/save/new_soul/data/
skylib_fluffos_v3/mudlib/save/parcels/
skylib_fluffos_v3/mudlib/save/playerinfo/
skylib_fluffos_v3/mudlib/save/players/d/
skylib_fluffos_v3/mudlib/save/players/s/
skylib_fluffos_v3/mudlib/save/random_names/
skylib_fluffos_v3/mudlib/save/random_names/data/
skylib_fluffos_v3/mudlib/save/terrains/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_desert/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_grassy_field/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_mountain/
skylib_fluffos_v3/mudlib/save/todo_lists/
skylib_fluffos_v3/mudlib/secure/
skylib_fluffos_v3/mudlib/secure/cmds/admin/
skylib_fluffos_v3/mudlib/secure/cmds/lord/
skylib_fluffos_v3/mudlib/secure/config/
skylib_fluffos_v3/mudlib/secure/handlers/autodoc/
skylib_fluffos_v3/mudlib/secure/handlers/intermud/
skylib_fluffos_v3/mudlib/secure/include/global/
skylib_fluffos_v3/mudlib/secure/save/
skylib_fluffos_v3/mudlib/secure/save/handlers/
skylib_fluffos_v3/mudlib/secure/std/
skylib_fluffos_v3/mudlib/secure/std/classes/
skylib_fluffos_v3/mudlib/secure/std/modules/
skylib_fluffos_v3/mudlib/std/creator/
skylib_fluffos_v3/mudlib/std/dom/
skylib_fluffos_v3/mudlib/std/effects/
skylib_fluffos_v3/mudlib/std/effects/external/
skylib_fluffos_v3/mudlib/std/effects/fighting/
skylib_fluffos_v3/mudlib/std/effects/magic/
skylib_fluffos_v3/mudlib/std/effects/magic/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/other/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/priest/
skylib_fluffos_v3/mudlib/std/effects/room/
skylib_fluffos_v3/mudlib/std/environ/
skylib_fluffos_v3/mudlib/std/guilds/
skylib_fluffos_v3/mudlib/std/guilds/old/
skylib_fluffos_v3/mudlib/std/languages/
skylib_fluffos_v3/mudlib/std/liquids/
skylib_fluffos_v3/mudlib/std/npc/
skylib_fluffos_v3/mudlib/std/npc/goals/
skylib_fluffos_v3/mudlib/std/npc/goals/basic/
skylib_fluffos_v3/mudlib/std/npc/goals/misc/
skylib_fluffos_v3/mudlib/std/npc/plans/
skylib_fluffos_v3/mudlib/std/npc/plans/basic/
skylib_fluffos_v3/mudlib/std/npc/types/
skylib_fluffos_v3/mudlib/std/npc/types/helper/
skylib_fluffos_v3/mudlib/std/npcs/
skylib_fluffos_v3/mudlib/std/outsides/
skylib_fluffos_v3/mudlib/std/races/shadows/
skylib_fluffos_v3/mudlib/std/room/basic/BACKUPS/
skylib_fluffos_v3/mudlib/std/room/basic/topography/
skylib_fluffos_v3/mudlib/std/room/controller/
skylib_fluffos_v3/mudlib/std/room/inherit/topography/
skylib_fluffos_v3/mudlib/std/room/topography/area/
skylib_fluffos_v3/mudlib/std/room/topography/iroom/
skylib_fluffos_v3/mudlib/std/room/topography/milestone/
skylib_fluffos_v3/mudlib/std/shadows/curses/
skylib_fluffos_v3/mudlib/std/shadows/disease/
skylib_fluffos_v3/mudlib/std/shadows/fighting/
skylib_fluffos_v3/mudlib/std/shadows/healing/
skylib_fluffos_v3/mudlib/std/shadows/magic/
skylib_fluffos_v3/mudlib/std/shadows/poison/
skylib_fluffos_v3/mudlib/std/shadows/room/
skylib_fluffos_v3/mudlib/std/shops/controllers/
skylib_fluffos_v3/mudlib/std/shops/objs/
skylib_fluffos_v3/mudlib/std/shops/player_shop/
skylib_fluffos_v3/mudlib/std/socket/
skylib_fluffos_v3/mudlib/std/soul/d/
skylib_fluffos_v3/mudlib/std/soul/e/
skylib_fluffos_v3/mudlib/std/soul/i/
skylib_fluffos_v3/mudlib/std/soul/j/
skylib_fluffos_v3/mudlib/std/soul/k/
skylib_fluffos_v3/mudlib/std/soul/l/
skylib_fluffos_v3/mudlib/std/soul/n/
skylib_fluffos_v3/mudlib/std/soul/o/
skylib_fluffos_v3/mudlib/std/soul/q/
skylib_fluffos_v3/mudlib/std/soul/r/
skylib_fluffos_v3/mudlib/std/soul/u/
skylib_fluffos_v3/mudlib/std/soul/v/
skylib_fluffos_v3/mudlib/std/soul/y/
skylib_fluffos_v3/mudlib/std/soul/z/
skylib_fluffos_v3/mudlib/std/stationery/
skylib_fluffos_v3/mudlib/w/
skylib_fluffos_v3/mudlib/w/default/
skylib_fluffos_v3/mudlib/w/default/armour/
skylib_fluffos_v3/mudlib/w/default/clothes/
skylib_fluffos_v3/mudlib/w/default/item/
skylib_fluffos_v3/mudlib/w/default/npc/
skylib_fluffos_v3/mudlib/w/default/room/
skylib_fluffos_v3/mudlib/w/default/weapon/
skylib_fluffos_v3/mudlib/www/
skylib_fluffos_v3/mudlib/www/java/
skylib_fluffos_v3/mudlib/www/secure/
skylib_fluffos_v3/mudlib/www/secure/lpc/advanced/
skylib_fluffos_v3/mudlib/www/secure/lpc/intermediate/
skylib_fluffos_v3/win32/
/**
 * Handles the automatic loading and saving of objects into the
 * players inventories on log in/out.
 * @author Ember
 */
#include <move_failures.h>

#define CLONER "/global/player/cloner"

#define RECEIPT "/obj/misc/al_receipt"

#define AUTO_STR_LENGTH 3

#define AUTO_LOAD_TYPE 0
#define AUTO_LOAD_NAME 1
#define AUTO_LOAD_DATA 2

/* Stuff for the data elements themselves */
#define AUTO_LOAD_STATIC_ARG  0
#define AUTO_LOAD_DYNAMIC_ARG 1

// This makes the replacement of virtual objects to work.
#define REPLACE_VIRTUAL

private mixed auto_load;
private nosave int _no_calls;
private nosave function _finished;

private void auto_clone_alt( object thing, mixed *load_info,
                             object dest, object tell_pl, function move_f );
private object *int_auto_load( int type, string name, mixed *load_info,
                               object dest, object tell_pl, int now,
                               function move_f );
private void move_to_destination( object thing, object dest, object tell_pl,
                                  function move_f );

/** @ignore yes */
mixed fragile_auto_str_ob( object ob ) {
   /* this function was added by Ember 30-Oct-93 */
   /* it is a copy of auto_str_ob below, with all the catches taken out */
   /* it is intended for the newer style of saving/loading with receipts */
   mixed static_arg;
   mixed dynamic_arg;
   string fname;

   static_arg = ob->query_static_auto_load();
   dynamic_arg = ob->query_dynamic_auto_load();

   if( !static_arg && !dynamic_arg )
       return ({ });

   if( sscanf( file_name( ob ), "%s#%*d", fname) == 2 )
       return  ({ 1, fname, ({ static_arg, dynamic_arg }) });
   else
       return ({ 0, file_name(ob), ({ static_arg, dynamic_arg }) });

} /* fragile_auto_str_ob() */

/**
 * This method figures out the auto load string for the given object.
 * The returned array contains 3 elements.  The first element is a
 * flag which tells if the object is a clone or the original object.
 * The second element is the name of the file and the third is the array
 * containing the saved information.  The third array contains three
 * elements.  The first is the static auto load information, the
 * second is the dynamic autoload information and the third is the shadow
 * auto load information.  The shadow autoload information is reduant these days
 * effects should be used instead.
 * @param ob the object to get the auto load information for
 * @return the array containing the auto load information
 * @see help::effects
 */
private string *auto_str_ob(object ob) {
   string static_arg;
   string dynamic_arg;
   string catch_static;
   string catch_dynamic;
   string fname;
   int value;
   string ob_name;
   mixed* tmp;

   catch_static = catch( static_arg = (string)ob->query_static_auto_load() );
   catch_dynamic = catch( dynamic_arg = (string)ob->query_dynamic_auto_load() );
   if( !static_arg && !dynamic_arg ) {
       // create receipts?
       if( catch_static || catch_dynamic ) {
           catch( value = ob->query_value() );
           ob_name = "unknown object";
           catch( ob_name = ob->short(1) );
           catch( RECEIPT->set_object(file_name(ob)) );
           RECEIPT->set_obname(ob_name);
           RECEIPT->set_value(value);
           tmp = fragile_auto_str_ob( find_object("/obj/misc/al_receipt") );
           tmp[0] = 1;
           // This is a bit of a hack.  It could easily break if the receipt
           // inheritance changes.
           if( !undefinedp(tmp[2][1]["::"]["cloned by"]) ) {
               tmp[2][1]["::"]["cloned by"] = "greco";
           }
       } else {
           tmp = ({ });
       }
       return tmp;
   }

   if( sscanf( file_name( ob ), "%s#%*d", fname ) == 2 ) {
       return  ({ 1, fname, ({ static_arg, dynamic_arg }) });
   } else {
       return ({ 0, file_name( ob ), ({ static_arg, dynamic_arg }) });
   }

} /* auto_str_ob() */

/**
 * Creates the complete auto load array from the array of objects
 * passed into this object.  It returns an array of elements
 * as specified in auto_str_ob.  The arrays from auto_str_ob() are
 * added together, so every 3 elemnts in the array is a new
 * autoload object.
 * @param obs the objects to create an autoload string for
 * @param into_array place the results directly iunto the auto_load array
 * @return the auto load array
 * @see auto_str_ob()
 */
string *create_auto_load( object *obs, int into_array ) {
  int i;
  string *tmp;
  string *al_tmp;

  if( into_array ) {
      auto_load = ({ });
  } else {
      tmp = ({ });
  }
  /*
   * For some reason inventories are regenerated backwards,
   * if we go from the the bottom of this array, so go from the top.
   */
  for( i = sizeof(obs) - 1; i >= 0; i-- ) {
      reset_eval_cost();
      if( !objectp(obs[i]) ) {
          continue;
      }
      if( !catch( al_tmp = auto_str_ob(obs[i]) ) ) {
          if( into_array ) {
              auto_load += al_tmp;
          } else {
              tmp += al_tmp;
          }
      }
  }

  return tmp;

} /* create_auto_load() */

/**
 * The new method of handling auto loading of objects.  This determines
 * if the object failed to load and gives the player a recipt if it does
 * not.
 * <p>
 * The finished variable should <b>only</b> be set in outer
 * level calls to this.  If you set it inside containers when they call
 * this it will cause errors.  This will only be called from within
 * the player object itself.
 * @param auto_string the values specifing the objects to auto load
 * @param dest the destination to put the objects in
 * @param tell who to tell about errors
 * @param finished the function to call when the auto loading has completed
 * @see create_auto_load()
 * @see load_auto_load()
 */
void load_auto_load_alt( mixed *auto_string, object dest,
                         object tell_pl, function finished) {
   int i;

   reset_eval_cost();

   if( !auto_string || !sizeof( auto_string ) || !pointerp( auto_string ) )
       return;

   /*
    * This is to try to handle the slight over-weight problems that people
    * close to capacity may have due to mergers, e.g. money.
    */
   if( dest == TO && tell_pl == TO && !TO->query_no_check() ) {
       TO->set_no_check( 1 );
       TO->set_max_weight( 100 + TO->query_max_weight() );
   }

   _finished = finished;
   reset_eval_cost();

   for( i = 0; i < sizeof( auto_string ); i += AUTO_STR_LENGTH ) {
       _no_calls++;
       call_out( (: int_auto_load :), i / 3,
           auto_string[ i + AUTO_LOAD_TYPE ],
           auto_string[ i + AUTO_LOAD_NAME ],
           auto_string[ i + AUTO_LOAD_DATA ],
           dest, tell_pl, 0, (: $1->move($2) :) );
   }

} /* load_auto_load_alt() */

/**
 * This method creates all the objects and sets them up now.  This will
 * not move any of the objects anywhere...  Relying on the calling
 * code to handle this.
 * @param auto_string the values specifing the objects to auto load
 * @param dest the destination to put the objects in
 * @param tell who to tell about errors
 * @param finished the function to call when the auto loading has completed
 * @see create_auto_load()
 * @see load_auto_load()
 */
object *load_auto_load_to_array( mixed *auto_string, object tell_pl ) {
   object *obs;
   int i;

   obs = ({ });

   if( !tell_pl )
       tell_pl = TP || TO;

   for( i = 0; i < sizeof( auto_string ); i += AUTO_STR_LENGTH ) {
       _no_calls++;
       /* Set a null function so it always appears to succeed. */
       obs += int_auto_load( auto_string[ i + AUTO_LOAD_TYPE ],
                             auto_string[ i + AUTO_LOAD_NAME ],
                             auto_string[ i + AUTO_LOAD_DATA ],
                             0, tell_pl, 1, (: MOVE_OK :) );
   }

   return obs - ({ 0 });

} /* load_auto_load_to_array() */

/**
 * This method loads all the objects from the array and places them
 * into the inventory of the specified object.
 * @param auto_string the values specifing the objects to auto load
 * @param dest the destination to put the objects in
 * @param tell who to tell about errors
 * @param finished the function to call when the auto loading has completed
 * @see create_auto_load()
 * @see load_auto_load()
 */
void load_auto_load_to_inventory( mixed *auto_string, object dest,
                                  object tell_pl, function move_f ) {
   int i;

   if( !tell_pl )
       tell_pl = TP || TO;

   for( i = 0; i < sizeof( auto_string ); i += AUTO_STR_LENGTH) {
      _no_calls++;
      int_auto_load(auto_string[ i + AUTO_LOAD_TYPE ],
                    auto_string[ i + AUTO_LOAD_NAME ],
                    auto_string[ i + AUTO_LOAD_DATA ],
                    dest, tell_pl, 0, move_f);
   }
} /* load_auto_load_to_inventory() */

private object create_auto_load_object( string name, mixed *load_info,
                                        object dest, object tell_pl,
                                        function move_f ) {
   object thing;

   catch( name = (string)CLONER->other_file( name ) );

   if( !catch( thing = (object)CLONER->clone( name ) ) ) {
       if( thing ) {
           if( base_name( thing ) == name ) {
               auto_clone_alt( thing, load_info, dest, tell_pl, move_f );
           } else {
               move_to_destination( thing, dest, tell_pl, move_f );
           }
       } else {
           tell_object( tell_pl, "Could not clone "+ name +".\n" );
           thing = clone_object( RECEIPT );
           thing->set_object( name );
           thing->set_static_save( load_info );
           move_to_destination(thing, dest, tell_pl, move_f);
       }
   } else {
       tell_object( tell_pl, "Error in loading "+ name +".\n" );
       thing = clone_object( RECEIPT );
       thing->set_object( name );
       thing->set_static_save( load_info );
       move_to_destination(thing, dest, tell_pl, move_f);
   }

   return thing;

} /* create_auto_load_object() */

private object *int_auto_load(int type, string name, mixed *load_info,
                              object dest, object tell_pl, int now,
                              function move_f) {
   object thing;
   object new_thing;
   mixed *stuff;

   _no_calls--;
   if( type ) {
       // Do this first so we don't leak receipts.
       thing = create_auto_load_object( name, load_info, dest, tell_pl, move_f );
       if( name == RECEIPT ) {
           /* Try and reload the receipt */
           stuff = thing->query_static_save();
           if( stuff ) {
               new_thing = create_auto_load_object( name, load_info, dest,
                                                    tell_pl, move_f );
              if( new_thing ) {
                  thing->dest_me();
                  thing = new_thing;
              }
           }
       }
   } else {
       if( !find_object( name ) ) {
           if( !catch( load_object( name ) ) ) {
               thing = find_object( name );
               if( thing ) {
                   auto_clone_alt( thing, load_info, dest, tell_pl, move_f );
               } else {
                   tell_object( tell_pl, "Could not load "+ name +".\n" );
               }
           } else {
              tell_object( tell_pl, "Error in loading "+ name +".\n" );
           }
       } else {
           tell_object( tell_pl, "Object "+ name +" exists.\n" );
       }
   }

   // Check to see if we have finished.
   if( _no_calls == 0 && _finished ) {
       // NB: This has to be run at the end of the setup...
       // Because a container may attempt to reload some stuff.
       evaluate( _finished, TO );
       _finished = 0;
   }

   if( thing )
       return ({ thing });

   return ({ });

} /* int_auto_load() */

/** @ignore yes */
private string ident( object thing ) {
   mixed word;

   catch( word = (string)thing->query_short() );

   if( stringp( word ) )
       return "\""+ word +"\"";

   return file_name( thing );

} /* ident() */

/**
 * This moves the cloned object into the correct location and
 * loads up the arguments.  The arguments array contains three elements
 * the first is the object being cloned, the second is the auto load
 * string and the third is the destination to move the object too.  This is
 * used by the alternate system of loading objects.
 * @param arg the arg array
 * @see load_auto_load_alt()
 * @see create_auto_load()
 * @see auto_clone()
 */
private void auto_clone_alt( object thing, mixed *load_info,
                             object dest, object tell_pl,
                             function move_f ) {
   /*
    * The setting up the object was previously done after this...
    * Not sure why?  Moved it to here...  Oh!  I have an idea.  The
    * object which fail might not end up being moved into the right place
    * or somewhere the player can see at all.  Changed the movement stuff
    * to also try and move into the telling players environment if we
    * run out of options.
    *
    * This is a moot problem now however, since with the inventory
    * generation one the contents is generated slowly after a while
    * anyway...
    */
   reset_eval_cost();
   if( load_info[ AUTO_LOAD_STATIC_ARG ] ) {
       catch( thing->init_static_arg( load_info[ AUTO_LOAD_STATIC_ARG ],
                                      tell_pl ) );
   }

   catch( thing->set_player( tell_pl ) );
   catch( thing->init_dynamic_arg( load_info[ AUTO_LOAD_DYNAMIC_ARG ] ),
                                   tell_pl );

   move_to_destination( thing, dest, tell_pl, move_f );

} /* auto_clone_alt() */

private object replace_virtual( object ob, object tell_pl ) {
    string file, bit;
    string static_arg;
    string dynamic_arg;
    object thing;

    if( ( file = ob->query_property("virtual name") ) &&
        sscanf( file, "%s.%s", file, bit ) == 2 ) {
        file = (string)CLONER->other_file( file );
        if( file_exists(file+".c") ) {
            reset_eval_cost();
            static_arg = (string)ob->query_static_auto_load();
            dynamic_arg = (string)ob->query_dynamic_auto_load();
            if( !static_arg && !dynamic_arg )
                return ob;
            if( !thing = clone_object(file+".c") )
                return ob;
            if( static_arg )
                thing->init_static_arg( static_arg );
            thing->set_player( tell_pl );
            thing->init_dynamic_arg( dynamic_arg );
            thing->remove_property("virtual name");
            thing->remove_property("virtual time");
            user_event( TO, "inform", sprintf("Replacing %s (%O -> %O) for %s",
                ob->query_short() || ob->query_name(), file_name(ob),
                file_name(thing), tell_pl->query_cap_name() ), "admin" );
            return thing;
        }
        user_event( TO, "inform", sprintf("Failed to replace %s (%O -> %s) for %s",
            ob->query_short() || ob->query_name(), file_name(ob), file+".c",
            tell_pl->query_cap_name() ), "admin" );
    }

    return ob;

} /* replace_virtual() */

private void move_to_destination( object thing, object dest, object tell_pl,
                                  function move_f ) {
   object place;
   int ret_val;
   string catch_str;

#ifdef REPLACE_VIRTUAL
   if( !catch( place = replace_virtual( thing, tell_pl ) ) && thing != place ) {
       thing->dest_me();
       thing = place;
   }
#endif

   /* Move it into its correct location. */
   place = dest;
   ret_val = MOVE_OK - 1;
   while( place && ret_val != MOVE_OK ) {
      catch_str = catch( ret_val =  evaluate( move_f, thing, place ) );
      if( catch_str ) {
          tell_object( tell_pl, "Error moving object: " + catch_str + "\n");
          ret_val = MOVE_OK - 1;
      }

      if( ret_val != MOVE_OK ) {
          if( ENV( place ) ) {
              tell_object( tell_pl, "Cannot move "+ ident( thing ) +" into "+
                  ident( place ) +" (move returned " + ret_val + "); "
                  "attempting to move it into "+ident( ENV( place ) ) +".\n");
              place = ENV( place );
         /*
          * I don't think this case is needed.  I think it just
          * adds confusion to the issue.  Who thinks it just adds confusiong
          * to the issue, was this me? - pf
          */
          } else if( place != ENV(tell_pl) && ENV( tell_pl ) ) {
              tell_object( tell_pl, "Cannot move "+ ident( thing ) +" into "+
                  ident( place ) +" (move returned " + ret_val + "); "
                  "attempting to move it into environment of " +
                  tell_pl->query_cap_name()+".\n");
              place = ENV( tell_pl );
          } else  if( place != find_object("/room/broken") ) {
              tell_object( tell_pl, "Cannot move "+ ident( thing ) +" into "+
                  ident( place ) +" (move returned " + ret_val + "); moving "
                  "it to the room for broken objects --- please ask a "
                  "creator for help.\n");
              place = load_object("/room/broken");
          } else {
              // Error!  Error!
              tell_object( tell_pl, "Cannot move "+ ident( thing ) +" into "+
                  " the room for broken objects --- This is a serious "
                  "error!  Please tell a creator immediately.\n");
              place = 0;
          }
          /* Only use the strange move function for the first move. */
          move_f = (: $1->move($2) :);
      }
   }
} /* auto_clone_alt() */

/**
 * This method tells us if the player is in the inventory regeneration
 * phase still.
 * @return 1 if the inventory is being regenerated, 0 otherwise.
 */
int query_auto_loading() { return _no_calls > 0; }

/**
 * This method retrusn the auto load string which is used to
 * regenerate the players inventory.
 * @return the array of the auto load string
 * @see set_auto_load_string()
 */
protected mixed query_auto_load_string() { return auto_load; }

/**
 * This method sets the current auto load string to the specified value.
 * @see query_auto_load_string()
 */
protected void set_auto_load_string(mixed str) { auto_load = str; }