dw_fluffos_v2/
dw_fluffos_v2/fluffos-2.9-ds2.05/
dw_fluffos_v2/fluffos-2.9-ds2.05/ChangeLog.old/
dw_fluffos_v2/fluffos-2.9-ds2.05/Win32/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/simuls/
dw_fluffos_v2/fluffos-2.9-ds2.05/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/clone/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/command/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/data/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/etc/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/master/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/log/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/compiler/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/efuns/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/operators/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/u/
dw_fluffos_v2/fluffos-2.9-ds2.05/tmp/
dw_fluffos_v2/fluffos-2.9-ds2.05/windows/
dw_fluffos_v2/lib/
dw_fluffos_v2/lib/binaries/cmds/
dw_fluffos_v2/lib/binaries/cmds/creator/
dw_fluffos_v2/lib/binaries/cmds/living/
dw_fluffos_v2/lib/binaries/cmds/player/
dw_fluffos_v2/lib/binaries/d/admin/obj/
dw_fluffos_v2/lib/binaries/d/liaison/
dw_fluffos_v2/lib/binaries/global/virtual/
dw_fluffos_v2/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v2/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v2/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v2/lib/binaries/obj/misc/
dw_fluffos_v2/lib/binaries/obj/misc/buckets/
dw_fluffos_v2/lib/binaries/obj/monster/
dw_fluffos_v2/lib/binaries/obj/reactions/
dw_fluffos_v2/lib/binaries/obj/reagents/
dw_fluffos_v2/lib/binaries/secure/cmds/creator/
dw_fluffos_v2/lib/binaries/secure/master/
dw_fluffos_v2/lib/binaries/std/
dw_fluffos_v2/lib/binaries/std/dom/
dw_fluffos_v2/lib/binaries/std/effects/object/
dw_fluffos_v2/lib/binaries/std/guilds/
dw_fluffos_v2/lib/binaries/std/languages/
dw_fluffos_v2/lib/binaries/std/races/
dw_fluffos_v2/lib/binaries/std/room/
dw_fluffos_v2/lib/binaries/std/room/basic/
dw_fluffos_v2/lib/binaries/std/shops/
dw_fluffos_v2/lib/binaries/std/shops/inherit/
dw_fluffos_v2/lib/binaries/www/
dw_fluffos_v2/lib/cmds/guild-race/
dw_fluffos_v2/lib/cmds/guild-race/crafts/
dw_fluffos_v2/lib/cmds/guild-race/other/
dw_fluffos_v2/lib/cmds/playtester/
dw_fluffos_v2/lib/cmds/playtester/senior/
dw_fluffos_v2/lib/d/admin/
dw_fluffos_v2/lib/d/admin/log/
dw_fluffos_v2/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v2/lib/d/admin/meetings/
dw_fluffos_v2/lib/d/admin/obj/
dw_fluffos_v2/lib/d/admin/room/we_care/
dw_fluffos_v2/lib/d/admin/save/
dw_fluffos_v2/lib/d/dist/
dw_fluffos_v2/lib/d/dist/mtf/
dw_fluffos_v2/lib/d/dist/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/chars/
dw_fluffos_v2/lib/d/dist/pumpkin/desert/
dw_fluffos_v2/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v2/lib/d/dist/pumpkin/hospital/
dw_fluffos_v2/lib/d/dist/pumpkin/inherit/
dw_fluffos_v2/lib/d/dist/pumpkin/map/
dw_fluffos_v2/lib/d/dist/pumpkin/plain/
dw_fluffos_v2/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/save/
dw_fluffos_v2/lib/d/dist/pumpkin/squash/
dw_fluffos_v2/lib/d/dist/pumpkin/terrain/
dw_fluffos_v2/lib/d/dist/pumpkin/woods/
dw_fluffos_v2/lib/d/dist/start/
dw_fluffos_v2/lib/d/learning/TinyTown/buildings/
dw_fluffos_v2/lib/d/learning/TinyTown/map/
dw_fluffos_v2/lib/d/learning/TinyTown/roads/
dw_fluffos_v2/lib/d/learning/add_command/
dw_fluffos_v2/lib/d/learning/arms_and_weps/
dw_fluffos_v2/lib/d/learning/chars/
dw_fluffos_v2/lib/d/learning/cutnpaste/
dw_fluffos_v2/lib/d/learning/examples/npcs/
dw_fluffos_v2/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v2/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v2/lib/d/learning/functions/
dw_fluffos_v2/lib/d/learning/handlers/
dw_fluffos_v2/lib/d/learning/help_topics/npcs/
dw_fluffos_v2/lib/d/learning/help_topics/objects/
dw_fluffos_v2/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v2/lib/d/learning/items/
dw_fluffos_v2/lib/d/learning/save/
dw_fluffos_v2/lib/d/liaison/
dw_fluffos_v2/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v2/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v2/lib/db/
dw_fluffos_v2/lib/doc/
dw_fluffos_v2/lib/doc/creator/
dw_fluffos_v2/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v2/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v2/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v2/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v2/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v2/lib/doc/creator/autodoc/std/key/
dw_fluffos_v2/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v2/lib/doc/creator/autodoc/std/map/
dw_fluffos_v2/lib/doc/creator/autodoc/std/race/
dw_fluffos_v2/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v2/lib/doc/creator/files/
dw_fluffos_v2/lib/doc/creator/policy/
dw_fluffos_v2/lib/doc/creator/room/
dw_fluffos_v2/lib/doc/effects/
dw_fluffos_v2/lib/doc/ideas/
dw_fluffos_v2/lib/doc/known_command/
dw_fluffos_v2/lib/doc/lpc/basic_manual/
dw_fluffos_v2/lib/doc/lpc/intermediate/
dw_fluffos_v2/lib/doc/new/add_command/
dw_fluffos_v2/lib/doc/new/handlers/
dw_fluffos_v2/lib/doc/new/living/
dw_fluffos_v2/lib/doc/new/living/race/
dw_fluffos_v2/lib/doc/new/living/spells/
dw_fluffos_v2/lib/doc/new/player/
dw_fluffos_v2/lib/doc/new/room/guild/
dw_fluffos_v2/lib/doc/new/room/outside/
dw_fluffos_v2/lib/doc/new/room/storeroom/
dw_fluffos_v2/lib/doc/object/
dw_fluffos_v2/lib/doc/playtesters/
dw_fluffos_v2/lib/doc/policy/
dw_fluffos_v2/lib/doc/weapons/
dw_fluffos_v2/lib/global/handlers/
dw_fluffos_v2/lib/global/virtual/setup_compiler/
dw_fluffos_v2/lib/include/
dw_fluffos_v2/lib/include/cmds/
dw_fluffos_v2/lib/include/effects/
dw_fluffos_v2/lib/include/npc/
dw_fluffos_v2/lib/include/shops/
dw_fluffos_v2/lib/net/daemon/chars/
dw_fluffos_v2/lib/net/inherit/
dw_fluffos_v2/lib/net/intermud3/
dw_fluffos_v2/lib/net/intermud3/services/
dw_fluffos_v2/lib/net/obj/
dw_fluffos_v2/lib/net/save/
dw_fluffos_v2/lib/net/smnmp/
dw_fluffos_v2/lib/net/snmp/
dw_fluffos_v2/lib/obj/amulets/
dw_fluffos_v2/lib/obj/b_day/
dw_fluffos_v2/lib/obj/examples/
dw_fluffos_v2/lib/obj/food/alcohol/
dw_fluffos_v2/lib/obj/food/chocolates/
dw_fluffos_v2/lib/obj/food/fruits/
dw_fluffos_v2/lib/obj/food/meat/
dw_fluffos_v2/lib/obj/food/nuts/
dw_fluffos_v2/lib/obj/food/seafood/
dw_fluffos_v2/lib/obj/food/vegetables/
dw_fluffos_v2/lib/obj/fungi/
dw_fluffos_v2/lib/obj/furnitures/artwork/
dw_fluffos_v2/lib/obj/furnitures/bathroom/
dw_fluffos_v2/lib/obj/furnitures/beds/
dw_fluffos_v2/lib/obj/furnitures/cabinets/
dw_fluffos_v2/lib/obj/furnitures/chairs/
dw_fluffos_v2/lib/obj/furnitures/chests/
dw_fluffos_v2/lib/obj/furnitures/clocks/
dw_fluffos_v2/lib/obj/furnitures/crockery/
dw_fluffos_v2/lib/obj/furnitures/cupboards/
dw_fluffos_v2/lib/obj/furnitures/cushions/
dw_fluffos_v2/lib/obj/furnitures/fake_plants/
dw_fluffos_v2/lib/obj/furnitures/lamps/
dw_fluffos_v2/lib/obj/furnitures/mirrors/
dw_fluffos_v2/lib/obj/furnitures/outdoor/
dw_fluffos_v2/lib/obj/furnitures/safes/
dw_fluffos_v2/lib/obj/furnitures/shelves/
dw_fluffos_v2/lib/obj/furnitures/sideboards/
dw_fluffos_v2/lib/obj/furnitures/sofas/
dw_fluffos_v2/lib/obj/furnitures/stoves/
dw_fluffos_v2/lib/obj/furnitures/tables/
dw_fluffos_v2/lib/obj/furnitures/wardrobes/
dw_fluffos_v2/lib/obj/handlers/
dw_fluffos_v2/lib/obj/handlers/autodoc/
dw_fluffos_v2/lib/obj/jewellery/anklets/
dw_fluffos_v2/lib/obj/jewellery/bracelets/
dw_fluffos_v2/lib/obj/jewellery/earrings/
dw_fluffos_v2/lib/obj/jewellery/misc/
dw_fluffos_v2/lib/obj/jewellery/necklaces/
dw_fluffos_v2/lib/obj/jewellery/rings/
dw_fluffos_v2/lib/obj/media/
dw_fluffos_v2/lib/obj/misc/buckets/
dw_fluffos_v2/lib/obj/misc/jars/
dw_fluffos_v2/lib/obj/misc/papers/
dw_fluffos_v2/lib/obj/misc/player_shop/
dw_fluffos_v2/lib/obj/misc/shops/
dw_fluffos_v2/lib/obj/misc/traps/
dw_fluffos_v2/lib/obj/monster/
dw_fluffos_v2/lib/obj/monster/godmother/
dw_fluffos_v2/lib/obj/monster/transport/
dw_fluffos_v2/lib/obj/plants/inherit/
dw_fluffos_v2/lib/obj/potions/
dw_fluffos_v2/lib/open/boards/
dw_fluffos_v2/lib/save/autodoc/
dw_fluffos_v2/lib/save/bank_accounts/
dw_fluffos_v2/lib/save/boards/frog/
dw_fluffos_v2/lib/save/books/bed_catalog/
dw_fluffos_v2/lib/save/creators/
dw_fluffos_v2/lib/save/mail/
dw_fluffos_v2/lib/save/mail/p/
dw_fluffos_v2/lib/save/soul/data/
dw_fluffos_v2/lib/save/tasks/
dw_fluffos_v2/lib/save/vaults/
dw_fluffos_v2/lib/secure/cmds/lord/
dw_fluffos_v2/lib/secure/config/
dw_fluffos_v2/lib/secure/items/
dw_fluffos_v2/lib/secure/player/
dw_fluffos_v2/lib/soul/
dw_fluffos_v2/lib/soul/i/
dw_fluffos_v2/lib/soul/j/
dw_fluffos_v2/lib/soul/k/
dw_fluffos_v2/lib/soul/o/
dw_fluffos_v2/lib/soul/q/
dw_fluffos_v2/lib/soul/to_approve/
dw_fluffos_v2/lib/soul/u/
dw_fluffos_v2/lib/soul/v/
dw_fluffos_v2/lib/soul/wish_list/
dw_fluffos_v2/lib/soul/y/
dw_fluffos_v2/lib/soul/z/
dw_fluffos_v2/lib/std/creator/
dw_fluffos_v2/lib/std/effects/
dw_fluffos_v2/lib/std/effects/attached/
dw_fluffos_v2/lib/std/effects/external/
dw_fluffos_v2/lib/std/effects/fighting/
dw_fluffos_v2/lib/std/effects/other/
dw_fluffos_v2/lib/std/environ/
dw_fluffos_v2/lib/std/guilds/
dw_fluffos_v2/lib/std/hospital/
dw_fluffos_v2/lib/std/house/
dw_fluffos_v2/lib/std/house/onebedhouse/
dw_fluffos_v2/lib/std/house/onebedhut/
dw_fluffos_v2/lib/std/house/tworoomflat/
dw_fluffos_v2/lib/std/languages/
dw_fluffos_v2/lib/std/liquids/
dw_fluffos_v2/lib/std/nationality/
dw_fluffos_v2/lib/std/nationality/accents/
dw_fluffos_v2/lib/std/nationality/accents/national/
dw_fluffos_v2/lib/std/nationality/accents/regional/
dw_fluffos_v2/lib/std/npc/goals/
dw_fluffos_v2/lib/std/npc/goals/basic/
dw_fluffos_v2/lib/std/npc/goals/misc/
dw_fluffos_v2/lib/std/npc/inherit/
dw_fluffos_v2/lib/std/npc/plans/
dw_fluffos_v2/lib/std/npc/plans/basic/
dw_fluffos_v2/lib/std/outsides/
dw_fluffos_v2/lib/std/races/shadows/
dw_fluffos_v2/lib/std/room/basic/topography/
dw_fluffos_v2/lib/std/room/controller/
dw_fluffos_v2/lib/std/room/controller/topography/
dw_fluffos_v2/lib/std/room/furniture/games/
dw_fluffos_v2/lib/std/room/furniture/inherit/
dw_fluffos_v2/lib/std/room/inherit/carriage/
dw_fluffos_v2/lib/std/room/inherit/topography/
dw_fluffos_v2/lib/std/room/punishments/
dw_fluffos_v2/lib/std/room/topography/area/
dw_fluffos_v2/lib/std/room/topography/iroom/
dw_fluffos_v2/lib/std/room/topography/milestone/
dw_fluffos_v2/lib/std/shadows/
dw_fluffos_v2/lib/std/shadows/attached/
dw_fluffos_v2/lib/std/shadows/curses/
dw_fluffos_v2/lib/std/shadows/disease/
dw_fluffos_v2/lib/std/shadows/fighting/
dw_fluffos_v2/lib/std/shadows/room/
dw_fluffos_v2/lib/std/shops/controllers/
dw_fluffos_v2/lib/std/shops/objs/
dw_fluffos_v2/lib/std/shops/player_shop/
dw_fluffos_v2/lib/std/shops/player_shop/office_code/
dw_fluffos_v2/lib/std/socket/
dw_fluffos_v2/lib/www/
dw_fluffos_v2/lib/www/external/autodoc/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v2/lib/www/external/java/telnet/examples/
dw_fluffos_v2/lib/www/external/java/telnet/tools/
dw_fluffos_v2/lib/www/pics/
dw_fluffos_v2/lib/www/secure/creator/
dw_fluffos_v2/lib/www/secure/editors/
dw_fluffos_v2/lib/www/secure/survey_results/
dw_fluffos_v2/win32/
/*  -*- LPC -*-  */
/*
 * $Locker:  $
 */

/**
 * Handles npcs wanderting randomly around the place and npcs
 * following a route to a destination.
 * @see /obj/monster->move_me_to()
 * @see /std/effects/npc/goto_destination
 * @author Wodan
 * @author Pinkfish
 */
// rewritten by Wodan 19-6-97.
#include <player.h>

#define MH "/obj/handlers/map"
#define LAST_LOC_PROPERTY "last locations"

void do_move_after();

//recycled as long as the npc travels, only movetime changes
class route_traveller { //we use this to store npcs on a route
  object monster;
  int movetime;
  int delay;
  string dest;
}

//dumped after its movetime
class wander_group { //monsters that will move at movetime
  object *monsters;
  int movetime;
}

private class wander_group *wanderers = ({});
private mapping wanderpos = ([]);
private class route_traveller *travellers = ({});
private mapping travelpos = ([]);
private int move_call_out_id;
private int after_call_out_id;

private void do_move_after();
private void move_monsters();
void delete_move_after( object monster );
private void do_wander(int running_away, object monster);

/** @ignore yes */
mixed query_next_mover() {
  return wanderers[0];
} /* query_next_mover() */

/** @ignore yes */
mixed query_anything(string thing){
  return copy(fetch_variable(thing));
} /* query_anything() */

/**
 * Is this npc a moving npc?
 * @param ob the npc to check to see if it moves
 * @return 1 if it is moving, 0 if it is not.
 */
int query_moving_monster(object ob) {
  return member_array(ob, travellers) != -1;
} /* query_moving_monster() */

/** @ignore yes */
mixed query_route_monster() {
  return travellers[0];
} /* query_route_monster() */

/** @ignore yes */
int find_pos(mixed *arr, function func, int val, int ref found){
  //search for place to insert in the lists
  //searching algorithm ripped from the driver
  int mid, high, low;

  high = sizeof(arr) - 1;
  low = 0;
  while(high >= low){
    mid = (high + low) / 2;
    if(val < (*func)(arr[mid]))
      high = mid - 1;
    else if(val > (*func)(arr[mid]))
      low = mid + 1;
    else break;//found it
  }
  found = !(high < low);
  return mid;
} /* find_pos() */

/** @ignore yes */
private void add_traveller(class route_traveller new_traveller){
  if(sizeof(travellers)){
    int found, mid;
    //get list position
    mid = find_pos(travellers, (: $1->movetime :), new_traveller->movetime, 
                   ref found);

    if(!found){
      //no place yet
      if(new_traveller->movetime > travellers[mid]->movetime)
        mid++;
      if(mid == sizeof(travellers)){
        travellers += ({new_traveller});
        if(find_call_out(move_call_out_id) == -1 && sizeof(travellers) ) {
          move_call_out_id = call_out((: move_monsters :),
                                      travellers[0]->movetime - time() );
        }
        return;
      }
    }

    if(mid == 0){ //start of list
      travellers = ({new_traveller}) + travellers;
      remove_call_out(move_call_out_id);
      move_call_out_id = call_out((: move_monsters :),
                                      new_traveller->movetime - time());

    } else {
        travellers = insert(travellers, new_traveller, mid); 
    }

  } else { //no list yet
    travellers = ({ new_traveller });
    move_call_out_id = call_out((: move_monsters :),
                                      new_traveller->movetime - time());
  }
} /* add_traveller() */

/**
 * Called from the npc to start them mmoving.  This should not need to
 * be called inside your code.  It is called from the function
 * move_me_to in the npc code.
 * @see /obj/monster->move_me_to()
 * @param delay the delay between each move
 * @param dest the destination room for the npc
 * @return 0 if it failed and 1 on success
 */
int move_me_please(int delay, string dest) {
  class route_traveller new_traveller;
  object monster;

  monster = previous_object();
  if(!intp(delay))
    return 0;

  if(travelpos[monster]) //get the old one out
    //we don't really remove it because member_array doesn't work on arrays of
    //classes.
    travelpos[monster]->monster = 0;

  if(delay < 5)
    delay = 5;

  new_traveller = new (class route_traveller, monster:monster, delay:delay,
             movetime:time() + delay, dest:dest);
  travelpos[monster] = new_traveller;
  
  add_traveller(new_traveller);
} /* move_me_please() */

/**
 * Actually moves everyone around the place.
 */
private void move_monsters(){
  class route_traveller tmp;
  int virtual_move, right, refuse;
  object monster;
  string true_location, destination, direc;

  tmp = travellers[0];
  monster = tmp->monster;

  /* First remove it from the current list */
  if(sizeof(travellers) > 1)
    travellers = travellers[1..];
  else 
    travellers = ({});
  
  if (monster) {
    virtual_move = monster->query_virtual_move();
    true_location = monster->query_true_location();
    direc = monster->get_next_route_direction();
    if (direc) {
      if ( !virtual_move ){
//    We don't need to check it if we're doing it.
// catch only returns something on errors, mostly in loading rooms, so the move 
// did not happen, so we _do_ need to try again, don't remove code you don't
// understand, please!
        if(catch(monster->do_command(direc)))
          catch(monster->do_command(direc)); //we can still move in a room if an item
                                             //in that room doesn't load and
                                             //caused an error
      } else {
        if ( "/room/virtual" != file_name( environment( monster ) ) )
          right = 1;
        if ( right ) {
          environment( monster )->set_destination( direc );
          destination = environment( monster )->query_destination( direc, monster );
        } else
          destination = (string)MH->qdes( direc, true_location );
        if ( right ) {
          if ( monster->check_anyone_here() || find_object( destination ) ){
            if(catch(monster->do_command( direc )))
              catch(monster->do_command( direc ));
          } else {
            "/room/virtual"->force_load();
            monster->move( find_object( "/room/virtual" ) );
            true_location = destination;
            monster->set_true_location( true_location );
          }
        } else {
          if ( !find_object( destination ) ) {
            true_location = destination;
            monster->set_true_location( true_location );
          } else {
            object ob = environment(monster);
            ob->remove_exit(direc);
            ob->add_exit(direc, destination,
               "plain" );
            monster->do_command(direc);
            ob->remove_exit(direc);
          }
        }
      }
    }
    tmp->movetime = time() + tmp->delay; //next movetime

    /* Put it back into the list */
    if ( direc && (!(refuse = monster->query_stop_moving()))) {
      add_traveller( tmp );
    } else {
      if(!refuse)
        refuse = (file_name(environment(tmp->monster)) != tmp->dest);
      tmp->monster->stopped_route(!refuse);
      map_delete( travelpos, tmp->monster );
    }
  } else //remove elements with 0 as a key
    travelpos = filter(travelpos, (: $1 :));
  
  if(find_call_out(move_call_out_id) == -1 && sizeof(travellers) ) {
    move_call_out_id = call_out((: move_monsters :),
                                      travellers[0]->movetime - time() );
  }
} /* move_monsters() */

/** @ignore yes */
private void add_move_after(object monster, int movetime) {
  if(sizeof(wanderers)){
    int found, mid;
    //insert into the list
    
    reset_eval_cost();

    if(sizeof(wanderers) > 5000){
      //those faster clean ups must be killing us, didn't use to get this big
      wanderers=filter(wanderers, function(class wander_group thing){
        return sizeof(filter(thing->monsters, (:$1:)));
      });
      reset_eval_cost();
    }
   
    if (find_call_out(after_call_out_id) == -1)
      after_call_out_id = call_out((: do_move_after :), 0);

    mid = find_pos(wanderers, (: $1->movetime :), movetime, ref found);

    if(!found){
      //no place yet
      if(movetime > wanderers[mid]->movetime)
        mid++;

      if(mid == sizeof(wanderers)){ //end of list
        wanderers += ({ new(class wander_group, monsters:({monster}),
                            movetime:movetime) });
        wanderpos[monster] = wanderers[<1];
        return;
      }

      if(mid == 0){ //start of list
        wanderers = ({ new(class wander_group, monsters:({monster}),
                           movetime:movetime) }) + wanderers;
        wanderpos[monster] = wanderers[0];
        remove_call_out(after_call_out_id);
        after_call_out_id = call_out((: do_move_after :), movetime - time());
        return;
        }

      wanderers = insert(wanderers, new(class wander_group,
                                        monsters:({monster}),
                                        movetime:movetime), mid);
      wanderpos[monster] = wanderers[mid];
      return;
    } else { //add to list for this timeslot
      wanderers[mid]->monsters += ({ monster });
      wanderpos[monster] = wanderers[mid];
      return;
    }
  } else { //no list yet
    wanderers = ({ new(class wander_group, monsters:({monster}),
                       movetime:movetime) });
    wanderpos[monster] = wanderers[0];
    after_call_out_id = call_out((: do_move_after :), movetime - time());
  }
} /* add_move_after() */

/**
 * Put an npc into the random movement group.  This is called from
 * the set_move_after code in the npc object.  You should not need
 * to call this function directrly.
 * @see /obj/monster->set_move_after()
 * @param runaway is this a wimpy attempt?
 */
void move_after( int runaway ) {
  mixed move_after;
  
  if(runaway)
    return do_wander(runaway, previous_object());
  
  move_after = previous_object()->query_move_after();

  delete_move_after(previous_object());

  if (!arrayp(move_after) || (!move_after[0] && !move_after[1])) {
    return;
  }
  
  add_move_after(previous_object(), time() + move_after[ 0 ] + 
                 random( move_after[ 1 ] ));
} /* move_after() */

/**
 * Stops an npc wanderering aimlessly around the place.
 * @param monster the npc to stop wandering
 */
void delete_move_after(object monster) {
  if(wanderpos[monster]) {
    ((class wander_group)wanderpos[monster])->monsters -= ({monster});
  }
  map_delete(wanderpos, monster);
} /* delete_move_after() */

/**
 * The NPCs just wander around.  Not doing anything nessessarily.
 * They never stop, so we never remove them from the list.  Just
 * shuffle their position.
 */
private void do_wander(int running_away, object monster) {
  int right, virtual_move;
  string destination, *direcs, *room_zones, true_location, *move_zones,
         *last_locs;

  if ( !monster )
    return ;
  if ( !environment( monster ) || monster->query_property( PASSED_OUT_PROP ) )
    return ;
  if ( !running_away &&
       sizeof( (object *)monster->query_attacker_list() ) )
    return ;
  if ( (int)monster->query_hp() <= 0 )
    return ;

  /* Find the current location and the exits from it */
  virtual_move = monster->query_virtual_move();
  true_location = monster->query_true_location();
  if (1 || !virtual_move || 
       (virtual_move && "/room/virtual" != file_name(environment(monster))))
    right = 1;
  if ( right )
   direcs = (string *)environment( monster )->query_direc( monster );
  else
    direcs = (string *)MH->qdir( true_location );

  last_locs = monster->query_propery( LAST_LOC_PROPERTY );
  if (!pointerp(last_locs))
    last_locs = ({ });
  /* Determine which one to go down. */
   if (!direcs) direcs = ({ });
  direcs = shuffle( direcs );
  while ( sizeof( direcs ) ) {
    if ( right ) {
      direcs[ 0 ] = (string)environment( monster )->expand_alias( direcs[ 0 ] );
//      environment( monster )->set_destination( direcs[ 0 ] );
      destination = environment( monster )->query_destination( direcs[0], monster );
    } else
      destination = (string)MH->qdes( direcs[ 0 ], true_location );
    if ( (!destination && !virtual_move) || (sizeof(direcs) > 1 &&
                          member_array(destination, last_locs) != -1 ) ||
         (0 && stringp(destination) && !find_object(destination) && !virtual_move) ) {
      direcs = direcs[1..];
      continue;
    }
    /* Correct zones... */
    move_zones = (string *)monster->query_move_zones();
    if ( sizeof( move_zones ) ) {
      if ( find_object( destination ) )
        room_zones = (string *)destination->query_zones();
      else
        room_zones = (string *)MH->query_zones( destination );
      if (!room_zones ||
          (sizeof(room_zones) == sizeof(room_zones - move_zones))) {
        direcs = direcs[1..];
        continue;
      }
    }
    break;
  }

  last_locs += ({ destination });
  if (sizeof(last_locs) > 4)
    last_locs = last_locs[sizeof(last_locs)-4..];
  monster->add_property( LAST_LOC_PROPERTY, last_locs);

  /*
   * Ok, if we are not going to move virtualy, do something
   * exciting.
   */
  if (sizeof(direcs)) {
    if (1 || !virtual_move ||
        (right && monster->check_anyone_here()) ||
        (find_object( destination ) ) ) {
      object ob;
      if (!right) {
        /* This means we are in the void, fiddle the exits... 
         */
        ob = environment(monster);
        ob->remove_exit(direcs[0]);
        ob->add_exit(direcs[0], destination, "plain");
        reset_eval_cost();
      }
      monster->do_move(direcs[0]);
      if(!right)
        ob->remove_exit(direcs[0]);
    } else {
      /* virtual movement... */
      if (virtual_move) {
        "/room/virtual"->force_load();
        monster->move( find_object("/room/virtual"));
        monster->set_true_location(destination);
      } 
    }
  }
} /* do_wander() */

private void do_move_after() {
  object monster;
  int movetime, *move_after, zero;
  class wander_group tmp;

  reset_eval_cost();

  if(sizeof(wanderers) > 5000){
    //those faster clean ups must be killing us, didn't use to get this big
    wanderers=filter(wanderers, function(class wander_group thing){
      return sizeof(filter(thing->monsters, (:$1:)));
    });
    reset_eval_cost();
  }

  while (sizeof(wanderers) && wanderers[0]->movetime <= time()) {
    reset_eval_cost();
    tmp = wanderers[0];
    wanderers = wanderers[1..];
    foreach(monster in tmp->monsters){
      map_delete(wanderpos, monster);
      if (objectp(monster) && environment(monster)) {
        move_after = monster->query_move_after();
        if (move_after[0] || move_after[1]) {
          movetime = time() + move_after[ 0 ] + random( move_after[ 1 ] );
          if( movetime < (time() + 2) ) {
            movetime = time() + 2;
          }
          add_move_after( monster, movetime );
          reset_eval_cost();
          if (!travelpos[monster]) { //we should not be on a route
            do_wander(0, monster);
          }
        }
      } else {
        zero = 1;
      }
    }
  }

  if (find_call_out(after_call_out_id) == -1 && sizeof(wanderers)) {
    after_call_out_id = call_out((: do_move_after :),
                                        wanderers[0]->movetime - time());
  }

  if(zero) {
    wanderpos = filter(wanderpos, (: $1 :));
  }
} /* do_move_after() */

mapping query_dynamic_auto_load() {
   return ([
    "wanderers" : wanderers,
    "wanderpos" : wanderpos,
    "travellers" : travellers,
    "travelpos" : travelpos
     ]);
}

void init_dynamic_arg(mapping map) {
  if (map) {
     wanderers = map["wanderers"];
     wanderpos = map["wanderpos"];
     travellers = map["travellers"];
     travelpos = map["travelpos"];
     do_move_after();
  }
}