nakedmudv3.0/
nakedmudv3.0/lib/
nakedmudv3.0/lib/logs/
nakedmudv3.0/lib/misc/
nakedmudv3.0/lib/players/
nakedmudv3.0/lib/pymodules/
nakedmudv3.0/lib/txt/
nakedmudv3.0/lib/world/
nakedmudv3.0/lib/world/examples/
nakedmudv3.0/lib/world/examples/mproto/
nakedmudv3.0/lib/world/examples/oproto/
nakedmudv3.0/lib/world/examples/reset/
nakedmudv3.0/lib/world/examples/rproto/
nakedmudv3.0/lib/world/examples/trigger/
nakedmudv3.0/lib/world/limbo/
nakedmudv3.0/lib/world/limbo/rproto/
nakedmudv3.0/src/alias/
nakedmudv3.0/src/char_vars/
nakedmudv3.0/src/editor/
nakedmudv3.0/src/example_module/
nakedmudv3.0/src/help/
nakedmudv3.0/src/set_val/
nakedmudv3.0/src/socials/
nakedmudv3.0/src/time/
/*
 * This file handles command interpreting
 */
#include <sys/types.h>
#include <stdio.h>

/* include main header file */
#include "mud.h"
#include "utils.h"
#include "character.h"
#include "socket.h"
#include "room.h"
#include "movement.h"    // for try_move_special
#include "commands.h"
#include "action.h"



//*****************************************************************************
// mandatory modules
//*****************************************************************************
#include "scripts/scripts.h"



//*****************************************************************************
// optional modules
//*****************************************************************************
#ifdef MODULE_FACULTY
#include "faculty/faculty.h"
#endif
#ifdef MODULE_ALIAS
#include "alias/alias.h"
#endif



//*****************************************************************************
// local variables and functions
//*****************************************************************************
NEAR_MAP *cmd_table = NULL;


void init_commands() {
  cmd_table = newNearMap();

  //***************************************************************************
  // This is for core functions ONLY! If you have a module that adds new
  // functions to the MUD, they should be added in the init_xxx() function
  // associated with your module.
  //***************************************************************************
  add_cmd("north", "n", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("east",  "e", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("south", "s", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("west",  "w", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("up",    "u", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("down",  "d", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("northeast", "na", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("southeast", "sa",  cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("southwest", "sb", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("northwest", "nb", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("ne",        "ne", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("se",        "se", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("sw",        "sw", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("nw",        "nw", cmd_move, POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );

  // A
  add_cmd("approach",   NULL, cmd_greet,    POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("ask",        NULL, cmd_ask,      POS_SITTING,  POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("at",         NULL, cmd_at,       POS_UNCONCIOUS, POS_FLYING,
	  "builder", TRUE, FALSE);

  // B
  add_cmd("back",       NULL, cmd_back,     POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);

  // C
  add_cmd("chat",       NULL, cmd_chat,     POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("clear",      NULL, cmd_clear,    POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("close",      NULL, cmd_close,    POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("commands",   NULL, cmd_commands, POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("compress",   NULL, cmd_compress, POS_UNCONCIOUS, POS_FLYING,
	  "player", FALSE, FALSE);
  add_cmd("copyover",   NULL, cmd_copyover, POS_UNCONCIOUS, POS_FLYING,
	  "admin",  FALSE, TRUE);

  // D
  add_cmd("delay",      NULL, cmd_delay,    POS_SLEEPING, POS_FLYING,
	  "player", TRUE,  FALSE);
  add_cmd("drop",       NULL, cmd_drop,     POS_SITTING,  POS_FLYING,
	  "player", TRUE, TRUE );

  // E
  add_cmd("emote",      NULL, cmd_emote,    POS_SITTING,  POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd(":",          NULL, cmd_emote,    POS_SITTING,  POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("equipment",  NULL, cmd_equipment,POS_SITTING,  POS_FLYING,
	  "player", TRUE, FALSE);

  // F
  add_cmd("force",      NULL, cmd_force,    POS_STANDING, POS_FLYING,
	  "admin",   FALSE, FALSE);

  // G
  add_cmd("gemote",     NULL, cmd_gemote,   POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("give",       NULL, cmd_give,     POS_SITTING,  POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("gossip",     NULL, cmd_chat,     POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("\"",         NULL, cmd_chat,     POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("greet",      NULL, cmd_greet,    POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("get",        NULL, cmd_get,      POS_SITTING,  POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("goto",       NULL, cmd_goto,     POS_STANDING, POS_FLYING,
	  "builder", FALSE, TRUE );
  add_cmd("groupcmds",  NULL, cmd_groupcmds,POS_UNCONCIOUS, POS_FLYING,
	  "player", FALSE, FALSE);

  // I
  add_cmd("inventory",  NULL, cmd_inventory,POS_SITTING,  POS_FLYING,
	  "player", TRUE, FALSE);

  // L
  add_cmd("look",       "l",  cmd_look,     POS_SITTING,  POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("lock",       NULL,  cmd_lock,    POS_STANDING,  POS_FLYING,
	  "player", TRUE, TRUE);
  add_cmd("land",       NULL, cmd_stand,    POS_FLYING,   POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("load",       NULL, cmd_load,     POS_SITTING,  POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("linkdead",   NULL, cmd_linkdead, POS_UNCONCIOUS, POS_FLYING,
	  "admin", FALSE, FALSE);
  add_cmd("lockdown",   NULL, cmd_lockdown, POS_UNCONCIOUS, POS_FLYING,
	  "admin", FALSE, FALSE);

  // M
  add_cmd("mlist",      NULL, cmd_mlist,    POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("mdelete",    NULL, cmd_mdelete,  POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("mrename",    NULL, cmd_mrename,  POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("more",       NULL, cmd_more,     POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("motd",       NULL, cmd_motd,     POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);

  // O
  add_cmd("olist",      NULL, cmd_olist,    POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("odelete",    NULL, cmd_odelete,  POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("orename",    NULL, cmd_orename,  POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("open",       NULL, cmd_open,     POS_STANDING, POS_FLYING,
	  "player", TRUE, TRUE );

  // P
  add_cmd("put",        "p", cmd_put,       POS_SITTING,  POS_FLYING,
	  "player", TRUE,  TRUE );
  add_cmd("page",       NULL, cmd_page,     POS_SITTING,  POS_FLYING,
	  "builder", TRUE, FALSE);
  add_cmd("purge",      NULL, cmd_purge,    POS_SITTING,  POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("pulserate",  NULL, cmd_pulserate,POS_UNCONCIOUS, POS_FLYING,
	  "admin", FALSE, FALSE);
  
  // Q
  add_cmd("quit",       NULL, cmd_quit,     POS_SLEEPING, POS_FLYING,
	  "player", FALSE, TRUE );

  // R
  add_cmd("rreload",    NULL, cmd_rreload,  POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("remove",     NULL, cmd_remove,   POS_SITTING, POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("repeat",     NULL, cmd_repeat,   POS_UNCONCIOUS, POS_FLYING,
	  "admin", FALSE, FALSE);
  add_cmd("rlist",      NULL, cmd_rlist,    POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("rdelete",    NULL, cmd_rdelete,  POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
  add_cmd("rrename",    NULL, cmd_rrename,  POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);

  // S
  add_cmd("say",        NULL, cmd_say,      POS_SITTING,  POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("'",          NULL, cmd_say,      POS_SITTING,  POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("save",       NULL, cmd_save,     POS_SLEEPING, POS_FLYING,
	  "player", FALSE, FALSE);
  add_cmd("shutdown",   NULL, cmd_shutdown, POS_UNCONCIOUS, POS_FLYING,
	  "admin", FALSE, TRUE );
  add_cmd("sit",        NULL, cmd_sit,      POS_SITTING,  POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("sleep",      NULL, cmd_sleep,    POS_SITTING,  POS_STANDING,
	  "player", TRUE, FALSE);
  add_cmd("stand",      NULL, cmd_stand,    POS_SITTING,  POS_STANDING,
	  "player", TRUE, TRUE );
  add_cmd("stop",       NULL, cmd_stop,     POS_SITTING, POS_FLYING,
	  "player", TRUE, FALSE);

  // T
  add_cmd("take",       NULL, cmd_get,      POS_SITTING,  POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("tell",       NULL, cmd_tell,     POS_SLEEPING, POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("transfer",   NULL, cmd_transfer, POS_STANDING, POS_FLYING,
	  "builder", FALSE, TRUE);

  // U
  add_cmd("unlock",       NULL,  cmd_unlock,    POS_STANDING,  POS_FLYING,
	  "player", TRUE, TRUE);

  // W
  add_cmd("wake",       NULL, cmd_wake,     POS_SLEEPING,  POS_SLEEPING,
	  "player", TRUE, TRUE );
  add_cmd("wear",       NULL, cmd_wear,     POS_SITTING,  POS_FLYING,
	  "player", TRUE, TRUE );
  add_cmd("who",        NULL, cmd_who,      POS_UNCONCIOUS, POS_FLYING,
	  "player", TRUE, FALSE);
  add_cmd("worn",       NULL, cmd_equipment,POS_SITTING,  POS_FLYING,
	  "player", TRUE, FALSE);

  // Z
  add_cmd("zlist",      NULL, cmd_zlist,    POS_SITTING,  POS_FLYING,
	  "builder", FALSE, TRUE);
  add_cmd("zreset",     NULL, cmd_zreset,   POS_UNCONCIOUS, POS_FLYING,
	  "builder", FALSE, FALSE);
}


bool cmd_exists(const char *cmd) {
  return nearMapKeyExists(cmd_table, cmd);
}

void remove_cmd(const char *cmd) {
  CMD_DATA *old_cmd = nearMapRemove(cmd_table, cmd);
  if(old_cmd) deleteCmd(old_cmd);
}

void add_cmd(const char *cmd, const char *sort_by, COMMAND(func),
	     int min_pos, int max_pos, const char *user_group, 
	     bool mob_ok, bool interrupts) {
  // if we've already got a command named this, remove it
  remove_cmd(cmd);

  // add in the new command
  nearMapPut(cmd_table, cmd, sort_by, 
	     newCmd(cmd, func, min_pos, max_pos, 
		    user_group, mob_ok, interrupts));
}


void add_py_cmd(const char *cmd, const char *sort_by, void *pyfunc,
	     int min_pos, int max_pos, const char *user_group, 
	     bool mob_ok, bool interrupts) {
  // if we've already got a command named this, remove it
  remove_cmd(cmd);

  // add in the new command
  nearMapPut(cmd_table, cmd, sort_by, 
	     newPyCmd(cmd, pyfunc, min_pos, max_pos, 
		    user_group, mob_ok, interrupts));
}


// show the character all of the commands in the specified group(s).
void show_commands(CHAR_DATA *ch, const char *user_groups) {
  BUFFER           *buf = newBuffer(MAX_BUFFER);
  NEAR_ITERATOR *near_i = newNearIterator(cmd_table);
  const char    *abbrev = NULL;
  CMD_DATA         *cmd = NULL;
  int               col = 0;

  // go over all of our buckets
  ITERATE_NEARMAP(abbrev, cmd, near_i) {
    if(is_keyword(user_groups, cmdGetUserGroup(cmd), FALSE)) {
      bprintf(buf, "%-13.13s", cmdGetName(cmd));
      if (!(++col % 6))
	bufferCat(buf, "\r\n");
    }
  } deleteNearIterator(near_i);

  // tag on our last newline if neccessary, and show commands
  if (col % 6) bprintf(buf, "\r\n");
  text_to_char(ch, bufferString(buf));
  deleteBuffer(buf);
}


// tries to pull a usable command from the near-table and use it. Returns
// TRUE if a usable command was found (even if it failed) and false otherwise.
bool try_use_cmd_table(CHAR_DATA *ch, NEAR_MAP *table, const char *command, 
		       char *arg, bool abbrev_ok) {
  if(abbrev_ok == FALSE) {
    CMD_DATA *cmd = nearMapGet(table, command, FALSE);
    if(cmd == NULL || !is_keyword(bitvectorGetBits(charGetUserGroups(ch)),
				  cmdGetUserGroup(cmd), FALSE))
      return FALSE;
    else {
      charTryCmd(ch, cmd, arg); 
      return TRUE;
    }
  }
  else {
    // try to look up the possible commands
    LIST *cmd_list = nearMapGetAllMatches(table, command);
    bool cmd_found = FALSE;
    if(cmd_list != NULL) {
      LIST_ITERATOR *cmd_i = newListIterator(cmd_list);
      CMD_DATA        *cmd = NULL;
      ITERATE_LIST(cmd, cmd_i) {
	if(is_keyword(bitvectorGetBits(charGetUserGroups(ch)), 
		      cmdGetUserGroup(cmd), FALSE)) {
	  charTryCmd(ch, cmd, arg); 
	  cmd_found = TRUE;
	  break;
	}
      } deleteListIterator(cmd_i);
      deleteList(cmd_list);
    }
    return cmd_found;
  }
}


void handle_cmd_input(SOCKET_DATA *dsock, char *arg) {
  CHAR_DATA *ch;
  if ((ch = socketGetChar(dsock)) == NULL)
    return;
  do_cmd(ch, arg, TRUE);
}


void do_cmd(CHAR_DATA *ch, char *arg, bool aliases_ok)  {
  char command[MAX_BUFFER];

  // make sure we've got a command to try
  if(!arg || !*arg)
    return;

  // if we are leading with a non-character, we are trying to do a short-form
  // command (e.g. ' for say, " for gossip). Just take the first character
  // and use the rest as the arg
  if(isalpha(*arg) || isdigit(*arg))
    arg = one_arg(arg, command);
  else {
    *command     = *arg;
    *(command+1) = '\0';
    arg++;
    // and skip all spaces
    while(isspace(*arg))
      arg++;
  }

#ifdef MODULE_ALIAS
  if(aliases_ok && try_alias(ch, command, arg))
    return;
#endif

  // check to see if it's a faculty command
#ifdef MODULE_FACULTY
  if(try_use_faculty(ch, command))
    return;
#endif

  // first try room commands then world commands
  if(!try_use_cmd_table(ch,roomGetCmdTable(charGetRoom(ch)),command,arg,FALSE))
    if(!try_use_cmd_table(ch, cmd_table, command, arg, TRUE))
      text_to_char(ch, "No such command.\r\n");
}