final_realms_fluffos_v1/
final_realms_fluffos_v1/bin/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/ChangeLog.old/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/Win32/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/compat/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/compat/simuls/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/include/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/clone/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/command/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/data/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/etc/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/include/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/inherit/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/inherit/master/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/log/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/tests/compiler/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/tests/efuns/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/tests/operators/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/u/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/tmp/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/windows/
final_realms_fluffos_v1/lib/baseobs/guilds/
final_realms_fluffos_v1/lib/baseobs/misc/
final_realms_fluffos_v1/lib/baseobs/races/shadows/
final_realms_fluffos_v1/lib/cmds/god/
final_realms_fluffos_v1/lib/cmds/handlers/
final_realms_fluffos_v1/lib/cmds/handlers/cmds/
final_realms_fluffos_v1/lib/d/heaven/
final_realms_fluffos_v1/lib/d/heaven/heaven/ave/
final_realms_fluffos_v1/lib/d/mudlib/
final_realms_fluffos_v1/lib/d/newbie/
final_realms_fluffos_v1/lib/d/newbie/docs/
final_realms_fluffos_v1/lib/d/newbie/drow/armour/
final_realms_fluffos_v1/lib/d/newbie/drow/items/
final_realms_fluffos_v1/lib/d/newbie/drow/mobs/
final_realms_fluffos_v1/lib/d/newbie/drow/oldmobs/
final_realms_fluffos_v1/lib/d/newbie/drow/weapons/
final_realms_fluffos_v1/lib/d/newbie/duergar/weapons/
final_realms_fluffos_v1/lib/d/newbie/dwarf/weapons/
final_realms_fluffos_v1/lib/d/newbie/elf/cafe/
final_realms_fluffos_v1/lib/d/newbie/elf/chars/equip/
final_realms_fluffos_v1/lib/d/newbie/elf/items/armours/
final_realms_fluffos_v1/lib/d/newbie/elf/items/obj/
final_realms_fluffos_v1/lib/d/newbie/elf/items/weapons/
final_realms_fluffos_v1/lib/d/newbie/elf/quick_fix/
final_realms_fluffos_v1/lib/d/newbie/gnome/armour/
final_realms_fluffos_v1/lib/d/newbie/gnome/buildings/
final_realms_fluffos_v1/lib/d/newbie/gnome/items/
final_realms_fluffos_v1/lib/d/newbie/gnome/npcs/clones/
final_realms_fluffos_v1/lib/d/newbie/gnome/rooms/northrooms/
final_realms_fluffos_v1/lib/d/newbie/gnome/weapons/
final_realms_fluffos_v1/lib/d/newbie/goblin/armour/
final_realms_fluffos_v1/lib/d/newbie/goblin/items/
final_realms_fluffos_v1/lib/d/newbie/grads/log/
final_realms_fluffos_v1/lib/d/newbie/grads/npcs/
final_realms_fluffos_v1/lib/d/newbie/grads/rooms/
final_realms_fluffos_v1/lib/d/newbie/grads/rooms/cave1/
final_realms_fluffos_v1/lib/d/newbie/grads/temp/
final_realms_fluffos_v1/lib/d/newbie/guests/weapons/
final_realms_fluffos_v1/lib/d/newbie/half-elf/items/
final_realms_fluffos_v1/lib/d/newbie/half-elf/newroomss/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/castle/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/drows/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/savannah/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/secret/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/town/
final_realms_fluffos_v1/lib/d/newbie/halfling/
final_realms_fluffos_v1/lib/d/newbie/halfling/misc/
final_realms_fluffos_v1/lib/d/newbie/halfling/rooms/cave/
final_realms_fluffos_v1/lib/d/newbie/human/
final_realms_fluffos_v1/lib/d/newbie/human/armour/
final_realms_fluffos_v1/lib/d/newbie/human/monsters/
final_realms_fluffos_v1/lib/d/newbie/human/obj/
final_realms_fluffos_v1/lib/d/newbie/human/weapons/
final_realms_fluffos_v1/lib/d/newbie/lizard/armour/
final_realms_fluffos_v1/lib/d/newbie/lizard/items/
final_realms_fluffos_v1/lib/d/newbie/lizard/underwater/
final_realms_fluffos_v1/lib/d/newbie/lizard/weapons/
final_realms_fluffos_v1/lib/d/newbie/logs/
final_realms_fluffos_v1/lib/d/newbie/new_halfelf/
final_realms_fluffos_v1/lib/d/newbie/new_halfelf/npcs/
final_realms_fluffos_v1/lib/d/newbie/newdrow/npcs/
final_realms_fluffos_v1/lib/d/newbie/newdrow/rooms/
final_realms_fluffos_v1/lib/d/newbie/newelf/
final_realms_fluffos_v1/lib/d/newbie/newelf/chars/
final_realms_fluffos_v1/lib/d/newbie/newelf/npcs/
final_realms_fluffos_v1/lib/d/newbie/newelf/npcs/recopied/
final_realms_fluffos_v1/lib/d/newbie/newelf/obj/
final_realms_fluffos_v1/lib/d/newbie/newelf/quest_docs./
final_realms_fluffos_v1/lib/d/newbie/newken/
final_realms_fluffos_v1/lib/d/newbie/newken/chars/
final_realms_fluffos_v1/lib/d/newbie/newken/misc/
final_realms_fluffos_v1/lib/d/newbie/newken/npcs/
final_realms_fluffos_v1/lib/d/newbie/newken/obj/
final_realms_fluffos_v1/lib/d/newbie/newliz/
final_realms_fluffos_v1/lib/d/newbie/newliz/cave/
final_realms_fluffos_v1/lib/d/newbie/newliz/npcs/
final_realms_fluffos_v1/lib/d/newbie/orc/items/misc/
final_realms_fluffos_v1/lib/d/newbie/orc/items/weapons/
final_realms_fluffos_v1/lib/d/newbie/orc/tower/
final_realms_fluffos_v1/lib/d/vehicle/
final_realms_fluffos_v1/lib/doc/
final_realms_fluffos_v1/lib/doc/driver/
final_realms_fluffos_v1/lib/doc/driver/concepts/
final_realms_fluffos_v1/lib/doc/driver/driver/
final_realms_fluffos_v1/lib/doc/driver/efuns/arrays/
final_realms_fluffos_v1/lib/doc/driver/efuns/bitstrings/
final_realms_fluffos_v1/lib/doc/driver/efuns/communication/
final_realms_fluffos_v1/lib/doc/driver/efuns/core/
final_realms_fluffos_v1/lib/doc/driver/efuns/debugging/
final_realms_fluffos_v1/lib/doc/driver/efuns/filesystem/
final_realms_fluffos_v1/lib/doc/driver/efuns/interactive/
final_realms_fluffos_v1/lib/doc/driver/efuns/mappings/
final_realms_fluffos_v1/lib/doc/driver/efuns/objects/
final_realms_fluffos_v1/lib/doc/driver/efuns/security/
final_realms_fluffos_v1/lib/doc/driver/efuns/strings/
final_realms_fluffos_v1/lib/doc/driver/efuns/system/
final_realms_fluffos_v1/lib/doc/driver/efuns/types/
final_realms_fluffos_v1/lib/doc/driver/lpc/constructs/
final_realms_fluffos_v1/lib/doc/driver/lpc/types/
final_realms_fluffos_v1/lib/doc/driver/platforms/
final_realms_fluffos_v1/lib/doc/lpc/
final_realms_fluffos_v1/lib/doc/mail/
final_realms_fluffos_v1/lib/doc/man/
final_realms_fluffos_v1/lib/doc/man/html/
final_realms_fluffos_v1/lib/doc/man/html/applies/
final_realms_fluffos_v1/lib/doc/man/html/applies/parsing/
final_realms_fluffos_v1/lib/doc/man/html/driver/
final_realms_fluffos_v1/lib/doc/man/html/efuns/
final_realms_fluffos_v1/lib/doc/man/html/efuns/arrays/
final_realms_fluffos_v1/lib/doc/man/html/efuns/buffers/
final_realms_fluffos_v1/lib/doc/man/html/efuns/compile/
final_realms_fluffos_v1/lib/doc/man/html/efuns/floats/
final_realms_fluffos_v1/lib/doc/man/html/efuns/functions/
final_realms_fluffos_v1/lib/doc/man/html/efuns/general/
final_realms_fluffos_v1/lib/doc/man/html/efuns/numbers/
final_realms_fluffos_v1/lib/doc/man/html/efuns/parsing/
final_realms_fluffos_v1/lib/doc/man/local/
final_realms_fluffos_v1/lib/doc/man/local/applies/
final_realms_fluffos_v1/lib/doc/man/local/applies/interactive/
final_realms_fluffos_v1/lib/doc/man/local/applies/master/
final_realms_fluffos_v1/lib/doc/man/local/concepts/
final_realms_fluffos_v1/lib/doc/man/local/defines/
final_realms_fluffos_v1/lib/doc/man/local/driver/
final_realms_fluffos_v1/lib/doc/man/local/efuns/
final_realms_fluffos_v1/lib/doc/man/local/efuns/arrays/
final_realms_fluffos_v1/lib/doc/man/local/efuns/buffers/
final_realms_fluffos_v1/lib/doc/man/local/efuns/calls/
final_realms_fluffos_v1/lib/doc/man/local/efuns/compile/
final_realms_fluffos_v1/lib/doc/man/local/efuns/filesystem/
final_realms_fluffos_v1/lib/doc/man/local/efuns/floats/
final_realms_fluffos_v1/lib/doc/man/local/efuns/functions/
final_realms_fluffos_v1/lib/doc/man/local/efuns/general/
final_realms_fluffos_v1/lib/doc/man/local/efuns/interactive/
final_realms_fluffos_v1/lib/doc/man/local/efuns/internals/
final_realms_fluffos_v1/lib/doc/man/local/efuns/mappings/
final_realms_fluffos_v1/lib/doc/man/local/efuns/mudlib/
final_realms_fluffos_v1/lib/doc/man/local/efuns/numbers/
final_realms_fluffos_v1/lib/doc/man/local/efuns/objects/
final_realms_fluffos_v1/lib/doc/man/local/efuns/parsing/
final_realms_fluffos_v1/lib/doc/man/local/efuns/sockets/
final_realms_fluffos_v1/lib/doc/man/local/efuns/strings/
final_realms_fluffos_v1/lib/doc/man/local/efuns/system/
final_realms_fluffos_v1/lib/doc/man/local/historical/
final_realms_fluffos_v1/lib/doc/man/local/lfun/QC/
final_realms_fluffos_v1/lib/doc/man/local/lfun/events/
final_realms_fluffos_v1/lib/doc/man/local/lfun/monster/
final_realms_fluffos_v1/lib/doc/man/local/lfun/properties/
final_realms_fluffos_v1/lib/doc/man/local/lpc/
final_realms_fluffos_v1/lib/doc/man/local/lpc/constructs/
final_realms_fluffos_v1/lib/doc/man/local/lpc/types/
final_realms_fluffos_v1/lib/doc/man/local/standards/
final_realms_fluffos_v1/lib/doc/man/local/tutorials/
final_realms_fluffos_v1/lib/doc/man/local/tutorials/basic/
final_realms_fluffos_v1/lib/doc/man/local/tutorials/intermediate/
final_realms_fluffos_v1/lib/doc/man/mudos/applies/
final_realms_fluffos_v1/lib/doc/man/mudos/applies/interactive/
final_realms_fluffos_v1/lib/doc/man/mudos/applies/parsing/
final_realms_fluffos_v1/lib/doc/man/mudos/concepts/
final_realms_fluffos_v1/lib/doc/man/mudos/driver/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/arrays/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/buffers/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/calls/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/compile/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/filesystem/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/floats/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/functions/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/general/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/mappings/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/mixed/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/mudlib/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/numbers/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/parsing/
final_realms_fluffos_v1/lib/doc/man/mudos/lpc/constructs/
final_realms_fluffos_v1/lib/doc/man/mudos/lpc/types/
final_realms_fluffos_v1/lib/doc/races/
final_realms_fluffos_v1/lib/doc/races/old_race/
final_realms_fluffos_v1/lib/global/virtual/
final_realms_fluffos_v1/lib/global/wiz_backup/
final_realms_fluffos_v1/lib/net/config/
final_realms_fluffos_v1/lib/net/daemon/chars/
final_realms_fluffos_v1/lib/net/inherit/
final_realms_fluffos_v1/lib/net/intermud3/
final_realms_fluffos_v1/lib/net/intermud3/cmds/
final_realms_fluffos_v1/lib/net/intermud3/save/
final_realms_fluffos_v1/lib/net/intermud3/services/
final_realms_fluffos_v1/lib/net/obj/
final_realms_fluffos_v1/lib/net/old/
final_realms_fluffos_v1/lib/net/old/intermud/
final_realms_fluffos_v1/lib/net/old/intermud/adm/
final_realms_fluffos_v1/lib/net/old/intermud/services/
final_realms_fluffos_v1/lib/net/old/intermud/udp/
final_realms_fluffos_v1/lib/net/virtual/
final_realms_fluffos_v1/lib/obj/b_day/
final_realms_fluffos_v1/lib/obj/chars/
final_realms_fluffos_v1/lib/obj/handlers/lists/
final_realms_fluffos_v1/lib/obj/handlers/useless/
final_realms_fluffos_v1/lib/obj/monsters/
final_realms_fluffos_v1/lib/obj/roomgen/
final_realms_fluffos_v1/lib/obj/soul/
final_realms_fluffos_v1/lib/obj/vegetation/
final_realms_fluffos_v1/lib/obj/weapons/oldsys/
final_realms_fluffos_v1/lib/open/
final_realms_fluffos_v1/lib/players/g/
final_realms_fluffos_v1/lib/releasefiles/d/heaven/
final_realms_fluffos_v1/lib/releasefiles/d/mudlib/
final_realms_fluffos_v1/lib/releasefiles/d/newbie/
final_realms_fluffos_v1/lib/releasefiles/doc/
final_realms_fluffos_v1/lib/releasefiles/players/g/
final_realms_fluffos_v1/lib/releasefiles/save/
final_realms_fluffos_v1/lib/releasefiles/save/environ/
final_realms_fluffos_v1/lib/releasefiles/save/roomgen/
final_realms_fluffos_v1/lib/releasefiles/secure/
final_realms_fluffos_v1/lib/releasefiles/w/
final_realms_fluffos_v1/lib/releasefiles/w/god/
final_realms_fluffos_v1/lib/room/
final_realms_fluffos_v1/lib/save/
final_realms_fluffos_v1/lib/save/environ/
final_realms_fluffos_v1/lib/save/roomgen/
final_realms_fluffos_v1/lib/scripts/
final_realms_fluffos_v1/lib/secure/crerem/
final_realms_fluffos_v1/lib/secure/dom/
final_realms_fluffos_v1/lib/secure/log/
final_realms_fluffos_v1/lib/secure/misc/
final_realms_fluffos_v1/lib/std/adnd/
final_realms_fluffos_v1/lib/std/commands/shadows/
final_realms_fluffos_v1/lib/std/creator/
final_realms_fluffos_v1/lib/std/curses/
final_realms_fluffos_v1/lib/std/curses/old_sys/
final_realms_fluffos_v1/lib/std/curses/shadows/
final_realms_fluffos_v1/lib/std/dom/
final_realms_fluffos_v1/lib/std/effects/
final_realms_fluffos_v1/lib/std/effects/healing/
final_realms_fluffos_v1/lib/std/effects/other/
final_realms_fluffos_v1/lib/std/effects/poisons/
final_realms_fluffos_v1/lib/std/environ/
final_realms_fluffos_v1/lib/std/guilds/
final_realms_fluffos_v1/lib/std/guilds/priests/samples/
final_realms_fluffos_v1/lib/std/guilds/wizards/
final_realms_fluffos_v1/lib/std/living/baldy/
final_realms_fluffos_v1/lib/std/living/divstuff/
final_realms_fluffos_v1/lib/std/paran/
final_realms_fluffos_v1/lib/std/poisons/
final_realms_fluffos_v1/lib/std/poisons/shadows/
final_realms_fluffos_v1/lib/std/poisons/weapons/
final_realms_fluffos_v1/lib/std/race_groups/
final_realms_fluffos_v1/lib/std/room/
final_realms_fluffos_v1/lib/std/room/old/
final_realms_fluffos_v1/lib/std/rooms/
final_realms_fluffos_v1/lib/std/shadows/
final_realms_fluffos_v1/lib/std/shadows/test_shad/
final_realms_fluffos_v1/lib/std/socket/
final_realms_fluffos_v1/lib/std/spells/
final_realms_fluffos_v1/lib/std/vaults/
final_realms_fluffos_v1/lib/tmp/
final_realms_fluffos_v1/lib/w/
final_realms_fluffos_v1/lib/w/god/
final_realms_fluffos_v1/old/
final_realms_fluffos_v1/win32/
/*
 * Originally..
 * 'the bit of the soul that all players should have ;)'
 * By Pinkfish, presumably
 *
 * This is the action queue, now, however.  Soul stuff removed.
 * This file has no soul.  It also uses private stuff.  Imagine that!
 *
 * By Wonderflug, 1996.
 * And Baldrick hacked some on it to make it worse dec '97.
 */

#include "action_queue.h"
#include "cmd.h"

/*
 * These must be saved in permanent storage; in fact, these should be
 * permanent stats of a character and handled as such.
 */

private int max_time;          /* Maximum 'spare' time this object can have  */
private int default_time;      /* Used for non-trivial actions w/o times set */


/* the actionq can contain function pointers or strings ;
 * function pointers are evaluated, strings are passed to
 * command() when the action is due to be done.
 * The actionq is allocate()'d, since commands will constantly be added
 * and deleted from it, and growing and shrinking it would be needless
 * waste.  Admittedly this means the majority of the queue slots are empty
 * most of the time.
 *
 * Actually it's not; we let it grow and shrink dynamically, to save heaps
 * and heaps of memory.  I do have the old implementation lying around
 * ready to be plugged in though, should we be able to spare the memory,
 * and not the cpu. (the other version isn't particularly faster though)
 */
private static mixed* actionq;

/*
 * Security array; this is an array of flags, each corresponding to
 * an action in the action queue, indicating if the action was forced by
 * some other object or not.
 */
private static int* action_forcedq;

/* If the current command was forced or not; 
 * -1 means no command is in progress (and thus, to most checks, has the
 * conservative view that the action WAS forced)
 */
private static int curr_forced;

private static int time_left;  /* Time left for this round. */

/* Allows prompts to be disabled after a given command completes */
private static int show_prompt;

/* for bookkeeping purposes */
private static string command_in_progress; /* copy of a command in progress */
private static int time_adjusted;          /* flag if time's been adjusted  */
private static int trivial_actions_performed;  /* number performed this hb  */
private static int trivial_action_in_progress;  /* flag if command trivial  */
private static int notified;
private static int hb_command_done; 


/* interruptable action stuff */
private static int ia_in_progress; /* flag indicating in the middle of an ia */
private static mixed ia_abort;     /* function/message on abort              */
private static mixed ia_complete;  /* function/message on complete           */
private static string ia_message;  /* message on any command not an abort    */

mixed* debug_actionq() { return actionq; }
void debug_resetq() {  actionq = ({ }); }

/* debug of course */
int query_bits_per_beat() { return 10; }

void create() 
{
  time_left = this_object()->query_bits_per_beat();

  actionq = ({ });
  action_forcedq = ({ });
  curr_forced = -1;

  if ( undefinedp(max_time) )
    max_time = this_object()->query_bits_per_beat();
  if ( undefinedp(default_time) )
    default_time = max_time;

  command_in_progress = "";
  time_adjusted = 0;
  trivial_actions_performed = 0;
  ia_in_progress = 0;
  ia_abort = 0;
  ia_complete = 0;
  ia_message = "";

  show_prompt = 1;
} /* create() */

int query_time_left() { return time_left; }
int adjust_time_left(int i) 
{ 
  time_adjusted = 1;
  return time_left += i; 
}

int query_max_time() { return max_time; }
int set_max_time(int i)
{
  if ( i < 0 )
    return max_time = 0;
  else
    return max_time = i;
}

int query_default_action_time() { return default_time; }
int set_default_action_time(int i) { return default_time = i; }

void set_notified(int fi)
  {
  notified = fi;
  return;
}

/* Maybe not needed anyway, Baldrick
 *
void set_hb_command_done(int fi)
  {
  hb_command_done = fi;
  return;
}
*/

void set_trivial_action() 
{ 
  trivial_action_in_progress = 1; 
  trivial_actions_performed++;
}

int set_interruptable_action(
  int time,
  string message,
  mixed abort,
  mixed complete )
{
  if ( ia_in_progress )
    return AQ_ERROR;

  if ( !stringp(abort) && !functionp(abort) )
    return AQ_ERROR;

  ia_in_progress = 1;
  this_object()->adjust_time_left( -time );

  ia_message = "Command queued since "+message+"Type 'abort' to attempt to "
    "end prematurely.\n";

  ia_abort = abort;
  ia_complete = complete;

  return AQ_OK;
}

/*
 * Attempts to abort any interruptable action in progress
 * Returns AQ_OK if, after returning, there is no interruptable action 
 * in progress, or AQ_ERROR otherwise.
 */
int abort_interruptable_action()
{
  if ( !ia_in_progress )
    return AQ_OK;

  if ( functionp( ia_abort ) && !evaluate(ia_abort) )
    return AQ_ERROR;
  else if ( stringp( ia_abort ) )
    tell_object( this_object(), ia_abort );

  ia_in_progress = 0;
  ia_abort = 0;
  ia_complete = 0;
  ia_message = 0;
  time_left = 0;
  
  return AQ_OK;
}
    
/*
 * Small interface functions used in the prompting system
 */
int query_busy()
{
  if ( time_left < 0 )
  {
    if ( ia_in_progress )
      return INTERRUPTABLE_BUSY;
    else
      return NON_INTERRUPTABLE_BUSY;
  }
  else if ( trivial_actions_performed > MAXIMUM_COMMANDS_PER_HB )
    return NON_INTERRUPTABLE_BUSY;
  return NOT_BUSY;
}

void set_no_prompt() { show_prompt = 0; }

/****
 * Queue maintenance routines
 ****/

/*
 * Determines who originated the current thread of execution. (action)
 * Returns 0 if this_object(); 1 if another object or it cannot
 * be determined for sure that it was this_object()
 * See queue_security (in some doc dir) to see the argument for
 * correctness of this.
 */
nomask private int aq_determine_forced()
{
  /* this_player(1) determines it for sure, if set */
  if ( this_player(1) )
  {
    if ( this_player(1) == this_object() )
      return 0;
    else
      return 1;
  }

  /* if this_player is set, and not this_object, we know it IS forced */
  if ( this_player() && this_player() != this_object() )
    return 1;

  /* if this_player is this_object, or this_player isn't set, use
   * the current forced status; note if it's -1 then of course we are
   * being forced.
   */
  if ( curr_forced == 0 )
    return 0;
  else
    return 1;
}


/*
 * Tries to insert an action at the head of the queue.
 */
nomask private int aq_insert( mixed val )
{
  if ( !stringp( val ) && !functionp( val ) )
    return AQ_ERROR;

  if ( sizeof( actionq ) >= AQ_MAX_ACTIONS )
    return AQ_FULL;

  actionq = ({ val }) + actionq;

  action_forcedq = ({ aq_determine_forced() }) + action_forcedq;

  return AQ_OK;
}

/*
 * Tries to add an action to the end of queue
 */
nomask private int aq_add( mixed val )
{
  string t, verb;

  //tc("wait a goddamn minute. aq_add("+identify(val)+")");
  //tc("called by: "+get_stack());

  if(!this_object()){
      //tc("returning error...no object");
      return AQ_ERROR;
  }

  if ( !stringp( val ) && !functionp( val ) ){
    //tc("returning error");
    return AQ_ERROR;
  }

  if ( sizeof( actionq ) >= AQ_MAX_ACTIONS ){
    //tc("returning full");
    return AQ_FULL;
  }

  if (sizeof(actionq) == 0 && !hb_command_done)
    {
    mixed ret;
    if ( functionp( val ) )
      {
      evaluate( val );
      }
    notify_fail ("");
    notified = 0;

    ret = command( val );
    //tc("ret0: "+identify(ret));
    if (!ret)
    //if (!command( val ))
      {
      sscanf(val, "%s %s", verb, t);
      if(!verb)
        verb = val;
      if (!this_object() || (!environment(this_object()) || 
          (!environment(this_object())->do_move_command(verb, t))))
      if (this_object() && !CMD_HANDLER->cmd(verb, t, this_object()))
        if (this_object() && !this_object()->parse_comm(verb, t ))
          hb_command_done = 2;
      }
    if (hb_command_done == 2 && !notified)
      hb_command_done = 1;
     else
      {
      hb_command_done = 1;
      //tc("returning ok. notified: "+notified);
      return AQ_OK;
      }
    }  

  actionq += ({ val });

  action_forcedq += ({ aq_determine_forced() });

  //tc("returning ok. notified: "+notified);
  //tc("actionq: "+identify(actionq));
  return AQ_OK;
}

/*
 * Removes the head of the queue, of course, and returns it
 * -1 if there are no entries in the queue.
 */
nomask private mixed aq_decapitate()
{
  mixed ret;

  if ( !sizeof(actionq) )
    return AQ_EMPTY;

  ret = actionq[0];

  /* [1..n] means 2nd element (1) to the last element (<0) ;
   * see the man pages under lpc/types/substructures for shortcuts
   * in indexing
   */
  actionq = actionq[1..<0];

  return ret;
}

/*
 * Deletes user actions from the queue.  Any command string is a user
 * action.  (supposedly)
 */
nomask private int aq_delete_user_actions()
{
  int i;
  mixed* newq; 
  int* new_fq;

  newq = ({ });
  new_fq = ({ });
  for( i=0; i<sizeof(actionq); i++ )
    if ( functionp(actionq[i]) )
    {
      newq += ({ actionq[i] });
      new_fq += ({ action_forcedq[i] });
    }

  actionq = newq;
  action_forcedq = new_fq;
      
  return AQ_OK;
}

/* The do_cmd is a part of the external command handling system.
 * Made by Chrisy and gotten from RD. oct '95.
 * Moved here by Baldrick so that the whole living-tree can use the 
 * commands in that system.
 */   
int do_cmd(string tail)
{
  string verb, t;

  sscanf(tail, "%s %s", verb, t);
  if(!verb)
    verb = tail;

  return (int)CMD_HANDLER->cmd(verb, t, this_object());
} /* do_cmd() */

/*
 * This looks for an action to perform and does it if there's one waiting
 * and time left.  Otherwise it returns.  If it does perform an action it'll
 * return 1, otherwise 0.
 */

nomask private int perform_next_action()
{
  mixed curr_act;
  int verb,t;

  show_prompt = 1;
  if ( ia_in_progress && time_left >= 0 )
  {
    /* this means the interruptable action is complete. */
    
    evaluate(ia_complete);
    ia_in_progress = 0;
    ia_complete = 0;
    ia_abort = 0;
    ia_message = "";
    curr_forced = -1;

    /* now we go ahead and try to perform the next action as usual */
  }

  if (time_left < 0 || trivial_actions_performed > MAXIMUM_COMMANDS_PER_HB )
    return 0;

  if ( sizeof(actionq) == 0 ) 
  {
    if ( this_object()->query_in_combat() )
    {
      mixed act = this_object()->determine_action() ;

      if ( !(stringp(act) || functionp(act)) 
           || aq_insert( act ) != AQ_OK )
      {
        write("perform_next_action: determine_action buggered up\n");
        return 0;
      }
    }
    else
      return 0;
  }

  curr_act = aq_decapitate();

  if ( intp(curr_act) )  /* it can't be good */
    return 0;

  curr_forced = action_forcedq[0];
  action_forcedq = action_forcedq[1..<0];

  trivial_action_in_progress = 0;
  if ( functionp( curr_act ) )
  {
    evaluate( curr_act );
  }
  else if ( stringp( curr_act ) )
  {
    mixed ret;
    command_in_progress = curr_act;
    time_adjusted = 0;
    /* testing something.. 
     * the right order of this may have to be tweaked
     * Baldrick */
    notify_fail ("");
    notified = 0;
    //tc("curr_act: "+curr_act);
    ret = command( curr_act );
    //tc("ret: "+identify(ret));
    if (!ret)
    //if (!command( curr_act ))
      {
      sscanf(curr_act, "%s %s", verb, t);
      if(!verb)
        verb = curr_act;
      //tc("verb: "+verb+" t: "+t);
      if (!this_object()->do_gr_command(verb, t))
      if ((!environment(this_object()) || 
          (!environment(this_object())->do_move_command(verb, t))))
        if (!CMD_HANDLER->cmd(verb, t, this_object()))
          if (!this_object()->parse_comm(verb, t ))
            if (!CMD_HANDLER->soul_com ( curr_act, this_object() ))
              if (!notified && strsrch(lower_case(__ARCH__),"windows") == -1)
              //if (!notified)
                write("The attempt to %^RED%^" + curr_act
                      + "%^RESET%^ didn't really work out.\n");

      }
    command_in_progress = "";
  }
  else {
    //tc("hmm.");
    return 0;
  }

  /* if the action didn't flag itself as trivial, and it didn't adjust
   * time left, then adjust time by a default
   *
   * Have to check for this_object(), alas, since 'quit' will destroy it.
   * Particularly stupid, I must say, makes no sense.
   */
  if ( !trivial_action_in_progress && !time_adjusted && this_object() )
    adjust_time_left( -this_object()->query_default_action_time() );

  if ( !ia_in_progress )
    curr_forced = -1;

  return 1;
} /* perform_next_action() */

/****
 * The real routines
 ****/

/*
 * The outside interface for inserting actions to the head of the queue.
 */
nomask int insert_action( mixed val ) { return aq_insert( val ); }
nomask int queue_action( mixed val ) { 
    int ret = aq_add( val );
    //tc("queue_action("+identify(val)+"): "+ret);
    return ret;
}
int action_queue_empty() { return sizeof(actionq) == 0; }

nomask int query_current_action_forced() { return curr_forced; }

/*
 * This should be called each heart beat..
 * This loops on perform_next_action until time is done or the max eval is
 * is hit, probably.  For security we might want to ENSURE this is only
 * called once per heartbeat.
 */
void act() 
{
  trivial_actions_performed = 0;
  if ( time_left < max_time )
  {
    time_left += this_object()->query_bits_per_beat();
    time_left = ( time_left > max_time ) ? max_time : time_left;
  }

  while( perform_next_action() )
  {
    if ( show_prompt && this_object() )
    {
      this_object()->show_prompt();
      /* show busy status; mudos wont in this case */
      this_object()->write_prompt();  
    }
  }
  hb_command_done = 0;
} /* act() */


/*
 * The great command enqueuer.  Fwheee.
 * If this_object has no heartbeat, it won't do anything.  Actions
 * can go right on through, then.
 * Otherwise, it sticks it on the queue and tells everyone its been done.
 * Well it's worse than that.  If we're the one trying to do the
 * action, then we let it through.
 */
nomask int action_check(string str) 
{
  int i;

  /* this is ridiculous.  MudOS will not show these strings as equal. */
  if ( str ==  command_in_progress )
    return 0;

  /* check for some special queue-affecting commands */
  switch( str )
  {
    case "restart":
      if ( query_heart_beat(this_object()) )
        write("You don't need your heartbeat restarted.\n");
      else
      {
        write("Attempting to restart heartbeat..\n");
        actionq = ({ });  /* will get cascading failure without this */
        set_heart_beat(1);
        catch(this_object()->flush_spell_effects());
      }
      return 1;

    case "stop":
      if ( sizeof(actionq) != 0 )
        aq_delete_user_actions();
      write("Removed queue.\n");
      return 1;

    case "abort":
      if ( !ia_in_progress )
      {
        write("You are not in the middle of an action which may be "
          "aborted.\n");
        return 1;
      }
      abort_interruptable_action();
      return 1;
  }
      
  if ( query_heart_beat(this_object()) == 0  )
  {
    write("WARNING: You have no heartbeat; try 'restart' to try to "
      "restart it.  Nothing will get performed without your heartbeat.\n");
  }

  if ( sizeof(actionq) >= AQ_MAX_ACTIONS )
  {
    tell_object(this_object(), "Too many commands queued already; "
      "ignoring '"+str+"'.\n");
    return 1;
  }

  if(this_object()->action_blocked())
  {
    /* Wonderflug, Dec 95, making this more flexible --
     * can specify the string that the block puts out.
     * A year later, adding ability to make it a function pointer too.
     */
    mixed pop = this_object()->action_blocked();

    if ( stringp(pop) )
    {
      write(pop);
      if(!this_object()->query_lord())
        return 1;
    }
    else if ( functionp( pop) )
      return evaluate( pop );
    else
    {
      write("You have passed out, you cant do anything.\n");
      if(!this_object()->query_lord())
        return 1;
    }
  }

  /* not sure why this is necessary.. */
  str=replace_string(str,"@@","");

  this_object()->add_history(str);

  /* The latency is too much, so we've added a check to see
   * if it's ok to execute the command right away.
   */
  //tc("about to try wnqueueing "+str);
  if ( (i=aq_add( str )) != AQ_OK )
    write("Error queuing '"+str+"', "+i+"\n");
  else if ( ia_in_progress )
    write( ia_message );
  else 
  {
    /* added the while below to remove latency in history/alias commands 
     * as well; to get prompting correct, I've also unrolled the first
     * iteration of the loop into an if.
     */
    if ( sizeof(actionq) >= 1 && time_left > 0 
            && trivial_actions_performed < MAXIMUM_COMMANDS_PER_HB )
      perform_next_action();

    while ( sizeof(actionq) >= 1 && time_left > 0 
            && trivial_actions_performed < MAXIMUM_COMMANDS_PER_HB )
    {
      this_object()->show_prompt();
      this_object()->write_prompt();
      perform_next_action();
    }
  }
    
  if ( show_prompt && this_object() )
    this_object()->show_prompt();

  return 1;
} /* action_check() */


/* Always return 0 to get the driver's notify_fail;
 * however getting here, we can be pretty sure that no 'real' action
 * was done, so we know a trivial command was done.  Anything using a
 * notify_fail shouldn't be a real action anyway, or can adjust time itself.
 */
nomask int lower_check(string str) 
{
  if ( command_in_progress )
  {
    trivial_action_in_progress = 1;
    trivial_actions_performed++;
  }

  return 0;
} /* lower_check() */