nakedmudv3.3/
nakedmudv3.3/lib/
nakedmudv3.3/lib/logs/
nakedmudv3.3/lib/misc/
nakedmudv3.3/lib/players/
nakedmudv3.3/lib/txt/
nakedmudv3.3/lib/world/
nakedmudv3.3/lib/world/examples/
nakedmudv3.3/lib/world/examples/mproto/
nakedmudv3.3/lib/world/examples/oproto/
nakedmudv3.3/lib/world/examples/reset/
nakedmudv3.3/lib/world/examples/rproto/
nakedmudv3.3/lib/world/examples/trigger/
nakedmudv3.3/lib/world/limbo/
nakedmudv3.3/lib/world/limbo/room/
nakedmudv3.3/lib/world/limbo/rproto/
nakedmudv3.3/src/alias/
nakedmudv3.3/src/char_vars/
nakedmudv3.3/src/editor/
nakedmudv3.3/src/example_module/
nakedmudv3.3/src/help/
nakedmudv3.3/src/set_val/
nakedmudv3.3/src/socials/
nakedmudv3.3/src/time/
//*****************************************************************************
//
// command.c
//
// A structure that holds all of the data tied to player commands. 
// Specifically, the function that is executed and all of the restrictions on
// its execution.
//
//*****************************************************************************

#include <Python.h>
#include <structmember.h>

#include "mud.h"
#include "utils.h"
#include "action.h"
#include "character.h"



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



//*****************************************************************************
// local structs, defines, and functions
//*****************************************************************************
struct cmd_data {
  char       *name;
  CMD_PTR(func);
  PyObject *pyfunc;
  int      min_pos;
  int      max_pos;
  char *user_group;
  bool      mob_ok;
  bool  interrupts;
};



//*****************************************************************************
// implementation of command.h
//*****************************************************************************
CMD_DATA *newCmd(const char *name, COMMAND(func), int min_pos, int max_pos,
		 const char *user_group, bool mob_ok, bool interrupts) {
  CMD_DATA *cmd   = malloc(sizeof(CMD_DATA));
  cmd->name       = strdupsafe(name);
  cmd->func       = func;
  cmd->min_pos    = min_pos;
  cmd->max_pos    = max_pos;
  cmd->user_group = strdupsafe(user_group);
  cmd->mob_ok     = mob_ok;
  cmd->interrupts = interrupts;
  cmd->pyfunc     = NULL;
  return cmd;
}

CMD_DATA *newPyCmd(const char *name, void *pyfunc, int min_pos, int max_pos,
		 const char *user_group, bool mob_ok, bool interrupts) {
  CMD_DATA *cmd   = malloc(sizeof(CMD_DATA));
  cmd->name       = strdupsafe(name);
  cmd->func       = NULL;
  cmd->min_pos    = min_pos;
  cmd->max_pos    = max_pos;
  cmd->user_group = strdupsafe(user_group);
  cmd->mob_ok     = mob_ok;
  cmd->interrupts = interrupts;
  cmd->pyfunc     = pyfunc;
  Py_INCREF(cmd->pyfunc);
  return cmd;
}

void deleteCmd(CMD_DATA *cmd) {
  if(cmd->name)       free(cmd->name);
  if(cmd->user_group) free(cmd->user_group);
  if(cmd->pyfunc)     { Py_DECREF(cmd->pyfunc); }
  free(cmd);
}

CMD_DATA *cmdCopy(CMD_DATA *cmd) {
  if(cmd->func)
    return newCmd(cmd->name, cmd->func, cmd->min_pos, cmd->max_pos,
		  cmd->user_group, cmd->mob_ok, cmd->interrupts);
  else
    return newPyCmd(cmd->name, cmd->pyfunc, cmd->min_pos, cmd->max_pos,
		    cmd->user_group, cmd->mob_ok, cmd->interrupts);
}

void cmdCopyTo(CMD_DATA *from, CMD_DATA *to) {
  if(to->name)       free(to->name);
  if(to->user_group) free(to->user_group);
  if(to->pyfunc)     { Py_DECREF(to->pyfunc); }
  *to = *from;
  to->name         = strdup(from->name);
  to->user_group   = strdup(from->user_group);
  if(to->pyfunc)     { Py_INCREF(to->pyfunc); }
}

const char *cmdGetName(CMD_DATA *cmd) {
  return cmd->name;
}

const char *cmdGetUserGroup(CMD_DATA *cmd) {
  return cmd->user_group;
}

int cmdGetMinPos(CMD_DATA *cmd) {
  return cmd->min_pos;
}

int cmdGetMaxPos(CMD_DATA *cmd) {
  return cmd->max_pos;
}

bool cmdGetMobOk(CMD_DATA *cmd) {
  return cmd->mob_ok;
}

bool cmdGetInterrupts(CMD_DATA *cmd) {
  return cmd->interrupts;
}


//
// make sure the character is in a position where this can be performed
bool min_pos_ok(CHAR_DATA *ch, int minpos) {
  if(poscmp(charGetPos(ch), minpos) >= 0)
    return TRUE;
  else {
    switch(charGetPos(ch)) {
    case POS_UNCONSCIOUS:
      send_to_char(ch, "You cannot do that while unconscious!\r\n");
      break;
    case POS_SLEEPING:
      send_to_char(ch, "Not while sleeping, you won't!\r\n");
      break;
    case POS_SITTING:
      send_to_char(ch, "You cannot do that while sitting!\r\n");
      break;
    case POS_STANDING:
      // flying is the highest position... we can deduce this message
      send_to_char(ch, "You must be flying to try that.\r\n");
      break;
    case POS_FLYING:
      send_to_char(ch, "That is not possible in any position you can think of.\r\n");
      break;
    default:
      send_to_char(ch, "Your position is all wrong!\r\n");
      log_string("Character, %s, has invalid position, %d.",
		 charGetName(ch), charGetPos(ch));
      break;
    }
    return FALSE;
  }
}


//
// make sure the character is in a position where this can be performed
bool max_pos_ok(CHAR_DATA *ch, int minpos) {
  if(poscmp(charGetPos(ch), minpos) <= 0)
    return TRUE;
  else {
    switch(charGetPos(ch)) {
    case POS_UNCONSCIOUS:
      send_to_char(ch, "You're still too alive to try that!\r\n");
      break;
    case POS_SLEEPING:
      send_to_char(ch, "Not while sleeping, you won't!\r\n");
      break;
    case POS_SITTING:
      send_to_char(ch, "You cannot do that while sitting!\r\n");
      break;
    case POS_STANDING:
      send_to_char(ch, "You cannot do that while standing.\r\n");
      break;
    case POS_FLYING:
      send_to_char(ch, "You must land first.\r\n");
      break;
    default:
      send_to_char(ch, "Your position is all wrong!\r\n");
      log_string("Character, %s, has invalid position, %d.",
		 charGetName(ch), charGetPos(ch));
      break;
    }
    return FALSE;
  }
}


bool charTryCmd(CHAR_DATA *ch, CMD_DATA *cmd, char *arg) {
  if(!min_pos_ok(ch, cmd->min_pos) || !max_pos_ok(ch,cmd->max_pos) ||
     (charIsNPC(ch) && !cmd->mob_ok))
    return FALSE;
  else {
    if(cmd->interrupts) {
#ifdef MODULE_FACULTY
      interrupt_action(ch, FACULTY_ALL);
#else
      interrupt_action(ch, 1);
#endif
    }
    if(cmd->func)
      (cmd->func)(ch, cmd->name, arg);
    else {
      PyObject *arglist = Py_BuildValue("Oss", charGetPyFormBorrowed(ch), 
					cmd->name, arg);
      PyObject *retval  = PyEval_CallObject(cmd->pyfunc, arglist);
      // check for an error:
      if(retval == NULL) {
	char *tb = getPythonTraceback();
	if(tb != NULL) {
	  log_string("Error running python command, %s:\r\n%s\r\n", 
		     cmd->name, tb);
	  free(tb);
	}
      }

      // garbage collection
      Py_XDECREF(retval);
      Py_XDECREF(arglist);
    }
    return TRUE;
  }
}