MudOSa4DGD/
MudOSa4DGD/bin/
MudOSa4DGD/data/
MudOSa4DGD/doc/
MudOSa4DGD/doc/driver/
MudOSa4DGD/doc/efun/bitstrings/
MudOSa4DGD/doc/efun/command/
MudOSa4DGD/doc/efun/communication/
MudOSa4DGD/doc/efun/heart_beat/
MudOSa4DGD/doc/efun/interactive/
MudOSa4DGD/doc/efun/inventory/
MudOSa4DGD/doc/efun/living/
MudOSa4DGD/doc/efun/mappings/
MudOSa4DGD/doc/efun/strings/
MudOSa4DGD/doc/efun/uid/
MudOSa4DGD/doc/funs/
MudOSa4DGD/doc/language/
MudOSa4DGD/mudlib/dgd/doc/
MudOSa4DGD/mudlib/dgd/lib/include/dgd/
MudOSa4DGD/mudlib/dgd/lib/std/
MudOSa4DGD/mudlib/dgd/lib/sys/
MudOSa4DGD/mudlib/dgd/log/
MudOSa4DGD/mudlib/log/
MudOSa4DGD/mudlib/std/include/
MudOSa4DGD/mudlib/std/obj/
/*
 * command.c
 *
 * Command a living to do stuff
 *
 * (C) Frank Schmidt, Jesus@NorseMUD
 *
 */


/* current command for this_player1() genuine (typed in) or not? */
static int genuine_command() {
  return GLOBAL->query_genuine_command();
}



#ifndef MUDOS_COMMAND


/* prototype for the mudlib "do_command"-function */
static void __DO_COMMAND_DEF(string str);


/* command a living to do a command */
static varargs int command(string str, object ob) {
  if (!ob) {
    /* command this object */
    int exec, genuine;
    object oldply;
    
    /* store exec-cost left before command takes place */
    exec = status()[ST_TICKS];

    /* store if previous command was a genuine command, and
     * nullify genuine command if this isn't one
     */
    if (genuine=genuine_command()) {
      if (previous_function() != "__command" || previous_program(1) != USER)
	GLOBAL->set_genuine_command(0);
    }
    
    /* set this_object() as this_player() and save old */
    if ((oldply=this_player()) != this_object())
      GLOBAL->set_this_player(this_object());


    if (str) {
      /* command us! */
#if INFORM_DRIVER >= 20
      DRIVER->send("INPUT (DGD): "+str);
#endif
      if (genuine) {
	catch(__DO_COMMAND_DEF(str));
      }
    }

    
    /* reset old this_player() */
    if ((oldply) != this_object())
      GLOBAL->set_this_player(oldply);

    /* reset genuinity */
    if (genuine)
      GLOBAL->set_genuine_command(genuine);
    
    /* return execution cycles used */
    return exec - status()[ST_TICKS];
  }
  else
    /* command another sucker (object) */
    return call_other(ob, "__command", str);

  /* something went VERY wrong */
  return 0;
}


#else /* MUDOS_COMMAND */

/* command a living to do a command */
static varargs int command(string str, object ob) {
  if (!ob) {
    /*if (living(this_object()))*/ {
      int exec, genuine;
      string *words;
      object oldply;

      /* store exec-cost left before command takes place */
      exec = status()[ST_TICKS];

      /* store if previous command was a genuine command, and
       * nullify genuine command if this isn't one
       */
      if (genuine=genuine_command()) {
	if (previous_function() != "__command" || previous_program(1) != USER)
	  GLOBAL->set_genuine_command(0);
      }
    
      /* set this_object() as this_player() and save old */
      if ((oldply=this_player()) != this_object())
	GLOBAL->set_this_player(this_object());


      /* explode into words */
      words = explode(str, " ");

#if 0
      /* get rid of nasty spaces in front of each word */
      words -= ({ "" });
      str = implode(words, " ");
#endif
      
      if (str) {
	/* we got a command to process */
	string oldverb, verb, rest;
#ifdef MUDOS_NOTIFY_FAIL
	string oldnf;
#endif

#ifdef MUDOS_NOTIFY_FAIL
	/* set default notify fail message */
	oldnf=query_notify_fail();
	notify_fail(DEFAULT_NOTIFY_FAIL);
#endif

	/* set current verb as word #1 */
	oldverb = query_verb();
	if (::sizeof(words))
	  GLOBAL->set_verb(verb=words[0]);
	else
	  GLOBAL->set_verb(verb="");

#if INFORM_DRIVER >= 20
	DRIVER->send("INPUT: "+str);
	DRIVER->send("VERB: "+verb);
	DRIVER->send("REST: "+rest);
#endif
	
	{
	  int i;
	  object env;
	  mixed *obs;
	  /* scan through inventory, inventory of environment and environment */
	  obs = ({ });
	  if (env=environment()) {
	    obs += ({ env });
	    obs += all_inventory(env) - ({ this_object() });
	  }
	  obs += all_inventory();
	  obs += ({ this_object() });

	  /* do the actual search for our verb */
	  for (i=::sizeof(obs); --i >= 0; ) {
	    function *triggs;
	    int e;
	    if (arrayp(triggs=obs[i]->query_triggers(verb))) {
	      for (e=::sizeof(triggs); --e >= 0; )
		/* call the functions for the trigger with rest-string */
		mixed ret;
		catch(ret=call_fp(triggs[e], rest));
		if (ret)
		  /* found a matching trigger! */
		  break;
	    }
	  }

#ifdef MUDOS_NOTIFY_FAIL
	  /* We didn't type correctly? */
	  if (i < 0)
	    /* show notify fail message */
	    __CATCH_TELL_DEF(query_notify_fail());
#endif
	}
	
	/* reset old verb */
	GLOBAL->set_verb(oldverb);

#ifdef MUDOS_NOTIFY_FAIL
	/* reset notify fail msg */
	notify_fail(oldnf);
#endif
      }


      /* reset old this_player() */
      if ((oldply) != this_object())
	GLOBAL->set_this_player(oldply);
      
      /* reset genuinity */
      if (genuine)
	GLOBAL->set_genuine_command(genuine);

      /* return execution cycles used */
      return exec - status()[ST_TICKS];
    }
  }
  else
    /* command another sucker */
    return call_other(ob, "__command", str);

  /* return failure */
  return 0;
}


/* return an array of ({ verb, flag, ob, func }) elements */
static mixed **commands() {
  int i;
  object env;
  mixed *obs, **cmds;

  /* scan through inventory, inventory of environment and environment */
  cmds = ({ });
  obs = ({ });
  if (env=environment()) {
    obs += ({ env });
    obs += all_inventory(env) - ({ this_object() });
  }
  obs += all_inventory();
  
  /* scan through all possible triggers */
  for (i=::sizeof(obs); --i >= 0; ) {
    mapping triggs;
    string *verbs;
    int e;
    for (e=::sizeof(verbs=map_indices(triggs=obs[i]->query_triggers())); --e >= 0; ) {
      int k;
      function *funcs;
      for (k=::sizeof(funcs=triggs[verbs[e]]); --k >= 0; ) {
	/* add a command to the list over local ones? */
	if (functionp(funcs[k]))
	  cmds += ({ verbs[e], 0, _OB(funcs[k]), _FUNC(funcs[k]) });
      }
    }
  }
  /* return result */
  return cmds;
}

#endif /* MUDOS_COMMAND */



/* accessible command(str) from DriverLib */
nomask int __command(string str) {
  if (!DRIVER_PRIV()) {
    /* Illegal call! */
    illegal();
    return 0;
  }
  return command(str);
}