/* $Header: /belch_a/users/rearl/tinymuck/src/RCS/speech.c,v 1.12 90/09/16 04:43:00 rearl Exp $ */

/*
 * $Log:	speech.c,v $
 * Revision 1.12  90/09/16  04:43:00  rearl
 * 
 * Preparation code added for disk-based MUCK.
 * 
 * Revision 1.11  90/09/15  22:28:08  rearl
 * Fixed bug in @wall.
 * 
 * Revision 1.10  90/09/10  02:21:23  rearl
 * Put quotes around the page format.
 * 
 * Revision 1.9  90/08/27  03:34:21  rearl
 * Changed page format (yet again)
 * 
 * Revision 1.8  90/08/11  04:10:47  rearl
 * *** empty log message ***
 * 
 * Revision 1.7  90/08/09  21:07:44  rearl
 * Removed notify_except2().
 * 
 * Revision 1.6  90/08/05  03:21:36  rearl
 * Redid matching routines.
 * 
 * Revision 1.5  90/08/02  18:54:29  rearl
 * Fixed some calls to logging functions.
 * 
 * Revision 1.4  90/07/29  17:44:45  rearl
 * Took out reconstruct_message() braindamage.
 * 
 * Revision 1.3  90/07/21  16:30:04  casie
 * removed fflush(stderr); call
 * 
 * Revision 1.2  90/07/21  13:04:18  casie
 * modified for logging handling
 * 
 * Revision 1.1  90/07/19  23:04:11  casie
 * Initial revision
 *
 */

#include "copyright.h"
#include "config.h"

#include "db.h"
#include "interface.h"
#include "match.h"
#include "params.h"
#include "externs.h"
#include <ctype.h>

/* Commands which involve speaking */

int blank(const char *s);


void do_say(dbref player, const char *message)
{
  dbref loc;
  char buf[BUFFER_LEN];
  
  if((loc = getloc(player)) == NOTHING) return;
  /* notify everybody */
  sprintf(buf, "You say, \"%s\"", message);
  notify(player, buf);
  sprintf(buf, "%s says, \"%s\"", NAME(player), message);
  notify_except(DBFETCH(loc)->contents, player,	buf);
}

void do_whisper(dbref player, const char *arg1, const char *arg2)
{
  dbref who;
  char buf[BUFFER_LEN];
  struct match_data md;
  
  init_match(player, arg1, TYPE_PLAYER, &md);
  match_neighbor(&md);
  match_me(&md);
  if(Arch(player)) {
    match_absolute(&md);
    match_player(&md);
  }
  switch(who = match_result(&md)) {
  case NOTHING:
    notify(player, "Whisper to whom?");
    break;
  case AMBIGUOUS:
    notify(player, "I don't know who you mean!");
    break;
  default:
    sprintf(buf, "%s whispers, \"%s\"", NAME(player), arg2);
    if (!notify(who, buf)) {
      sprintf(buf, "%s is not connected.", NAME(who));
      notify(player, buf);
      break;
    }
    sprintf(buf, "You whisper, \"%s\" to %s.", arg2, NAME(who));
    notify(player, buf);
    break;
  }
}

void do_pose(dbref player, const char *message)
{
  dbref loc;
  char buf[BUFFER_LEN];
  
  if((loc = getloc(player)) == NOTHING) return;
  
  /* notify everybody */
  sprintf(buf, "%s %s", NAME(player), message);
  notify_except(DBFETCH(loc)->contents, NOTHING, buf);
}

void do_wall(dbref player, const char *message)
{
  dbref i;
  char buf[BUFFER_LEN];
  
  if(Wizard(player)) {
    log_status("WALL from %s(%d): %s\n", NAME(player), player, message);
    sprintf(buf, "%s shouts, \"%s\"", NAME(player), message);
    for(i = 0; i < db_top; i++) {
      if(Typeof(i) == TYPE_PLAYER) {
	notify(i, buf);
      }
    }
  } else {
    notify(player, "But what do you want to do with the wall?");
  }
}

void do_gripe(dbref player, const char *message)
{
  dbref loc;
  
  loc = DBFETCH(player)->location;
  log_gripe("GRIPE from %s(%d) in %s(%d): %s\n",
	    NAME(player), player, NAME(loc), loc, message);
  
  notify(player, "Your complaint has been duly noted.");
}

/* doesn't really belong here, but I couldn't figure out where else */
void do_page(dbref player, const char *arg1, const char *arg2)
{
  char buf[BUFFER_LEN];
  dbref target;
  
  if(!payfor(player, LOOKUP_COST)) {
    notify(player, "You don't have enough pennies.");
    return;
  }
  if((target = lookup_player(arg1)) == NOTHING) {
    notify(player, "I don't recognize that name.");
    return;
  }

  if (blank(arg2))
    sprintf(buf, "You sense that %s is looking for you in %s.",
	    NAME(player), NAME(DBFETCH(player)->location));
  else
    sprintf(buf, "%s pages from %s: \"%s\"", NAME(player),
	    NAME(DBFETCH(player)->location), arg2);
  if (notify(target, buf))
    notify(player, "Your message has been sent.");
  else {
    sprintf(buf, "%s is not connected.", NAME(target));
    notify(player, buf);
  }
}

int notify(dbref who, const char *msg)
{
  register int res;
  static char buff[BUFFER_LEN+80];
  static char buf2[BUFFER_LEN+80];
  if(!msg)
    return notify_internal(who, msg);
  strcpy(buf2, msg);
  msg = buf2;
  if(Paranoid(who) && (who != global_trigger)) { /* paranoid! */
    sprintf(buff, "[%s(#%d)] %s", NAME(global_trigger), (int) global_trigger,
	    msg);
    res = notify_internal(who, buff);
  } else
    res = notify_internal(who, msg);
  if(FLAGS(who)&PUPPET && Typeof(who)!=TYPE_PLAYER) {
    sprintf(buff, "%s> %s", NAME(who), msg);
    res += notify_internal(DBFETCH(who)->owner, buff);
  }
  if(Typeof(who) == TYPE_THING)	/* only objects can do listen/ahear */
    if(get_attr(who, "Listen")) /* do the listen junk */ {
      res++;
      strcpy(buff, msg);
      if(wild_match(get_attr(who, "Listen"), buff)) {
	/* okie, it's a match */
	trigobj(who,get_attr(who, "Aahear"), global_trigger);
	if(global_trigger==who)
	  trigobj(who,get_attr(who, "Amhear"), global_trigger);
	else
	  trigobj(who, get_attr(who, "Ahear"), global_trigger);
      }
   }    
  return res;
}
void notify_except(dbref first, dbref exception, const char *msg)
{
  if(first == NOTHING)
    return;
  if(DBFETCH(first)->location != NOTHING
     && DBFETCH(first)->location != exception) {
    notify(DBFETCH(first)->location, msg);
  }
  DOLIST (first, first) {
    if (first != exception) {
      notify(first, msg);
    }
  }
}

int
  blank(const char *s)
{
  while (*s && isspace(*s))
    s++;
  
  return !(*s);
}

void lose_ears(dbref x)
{
  notify_except(DBFETCH(DBFETCH(x)->location)->contents,
		NOTHING,
		pronoun_substitute(x, "%n loses %p ears and becomes deaf.",
				   GOD));
}
void grow_ears(dbref x)
{
  notify_except(DBFETCH(DBFETCH(x)->location)->contents,
		NOTHING,
		pronoun_substitute(x, "%n grows ears and can now hear!",
				   GOD));
}