muse1.7b4/
muse1.7b4/config/
muse1.7b4/doc/
muse1.7b4/run/
muse1.7b4/run/db/
muse1.7b4/src/
muse1.7b4/src/db/
muse1.7b4/src/files/
muse1.7b4/src/io/
muse1.7b4/src/prog/
muse1.7b4/src/util/
/* speech.c */
/* $Id: speech.c,v 1.21 1993/09/18 19:03:46 nils Exp $ */

/* Commands which involve speaking */
#include <ctype.h>
#include <sys/types.h>

#include "db.h"
#include "interface.h"
#include "net.h"
#include "match.h"
#include "config.h"
#include "externs.h"

/* generate name for object to be used when spoken */
/* for spoof protection player names always capitalized, object names */
/* always lower case */
char *spname(thing)
     dbref thing;
{
  
  /* ack! this is evil to do. -shkoo 
     static char buff[1024];
     strcpy(buff,db[thing].name);
     if (Typeof(thing)==TYPE_PLAYER)
     buff[0]=to_upper(buff[0]);
     else
     buff[0]=to_lower(buff[0]);
     return(buff);
     */
  return db[thing].name;
}

/* this function is a kludge for regenerating messages split by '=' */
char *reconstruct_message(arg1,arg2)
     char *arg1;
     char *arg2;
{
  static char buf[BUFFER_LEN];
  
  if ( arg2 )
    if ( *arg2 )  {
      strcpy(buf, arg1?arg1:"");
      strcat(buf, " = ");
      strcat(buf, arg2);
      return buf;
    }
  
  return arg1?arg1:"";
}

int sp_ok(player)
     dbref player;
{
  /*  if ( ! Robot(player) && ! controls(player,db[player].location, TYPE_ADMIN))
      {
      notify(player,"Sorry robots may not speak in public");
      return(0);
      }
      */
  return(1);
}

void do_say(player,arg1,arg2)
     dbref player;
     char *arg1;
     char *arg2;
{
  dbref loc;
  char *message;
  char buf[BUFFER_LEN],*bf;
  
  if((loc = getloc(player)) == NOTHING) return;
  if (!sp_ok(player))
    return;
  if(IS(loc,TYPE_ROOM,ROOM_AUDITORIUM) &&
      !could_doit(player, loc, A_SLOCK)) {
    did_it(player, loc, A_SFAIL, "Shh.", A_OSFAIL, NULL, A_ASFAIL);
    return;
  }
  message = reconstruct_message(arg1, arg2);
  pronoun_substitute(buf,player,message,player);
  bf=buf+strlen(db[player].name)+1;
  /* notify everybody */
  notify(player, tprintf("You say \"%s\"",bf));
  notify_in(loc,player,
		tprintf("%s says \"%s\"", spname(player), bf));
}

void do_whisper(player,arg1,arg2)
     dbref player;
     char *arg1;
     char *arg2;
{
  dbref who;
  char buf[BUFFER_LEN],*bf;
  
  pronoun_substitute(buf, player, arg2, player);
  bf = buf + strlen(db[player].name) + 1;
  init_match(player, arg1, TYPE_PLAYER);
  match_neighbor();
  match_me();
  if(power(player, POW_REMOTE)) {
    match_absolute();
    match_player();
  }
  switch(who = match_result()) {
  case NOTHING:
    notify(player, "Whisper to whom?");
    break;
  case AMBIGUOUS:
    notify(player, "I don't know who you mean!");
    break;
  default:
    if ( *bf == ':' )  {
      notify(player,
	     tprintf("You whisper-posed %s with \"%s %s\".",
		     db[who].name, spname(player), bf+1));
      notify(who,
	     tprintf("%s whisper-poses: %s %s", spname(player), spname(player), bf+1));
      /*    wptr[0]=bf; */ /* Don't pass %0 */
      did_it(player, who, NULL, 0, NULL, 0, A_AWHISPER);
      break;
    }
    notify(player,
	   tprintf( "You whisper \"%s\" to %s.", bf, db[who].name));
    notify(who,
	   tprintf( "%s whispers \"%s\"", spname(player), bf));
    /*    wptr[0]=bf; */ /* Don't pass %0 */
    did_it(player, who, NULL, 0, NULL, 0, A_AWHISPER);
    break;
  }
}

void do_pose(player,arg1,arg2,possessive)
     dbref player;
     char *arg1;
     char *arg2;
     int possessive;
{
  dbref loc;
  char lastchar, *format;
  char *message;
  char buf[BUFFER_LEN], *bf;
  
  if((loc = getloc(player)) == NOTHING) return;
  
  if (!sp_ok(player))
    return;
  
  if(IS(loc,TYPE_ROOM,ROOM_AUDITORIUM) &&
      !could_doit(player, loc, A_SLOCK)) {
    did_it(player, loc, A_SFAIL, "Shhh.", A_OSFAIL, NULL, A_ASFAIL);
    return;
  }
  
  if ( possessive )  {
    /* get last character of player's name */
    lastchar = to_lower(db[player].name[strlen(db[player].name)-1]);
    
    format = (lastchar == 's') ? "%s' %s" : "%s's %s";
  }
  else
    format = "%s %s";
  
  message = reconstruct_message(arg1, arg2);
  pronoun_substitute(buf,player,message,player);
  bf=strlen(db[player].name)+buf+1;
  
  /* notify everybody */
  notify_in(loc,NOTHING,
		tprintf(format, spname(player), bf));
}

void do_echo(player,arg1,arg2,type)
     dbref player;
     char *arg1, *arg2;
     int type;
{
  char *message = reconstruct_message(arg1,arg2);
  char buf[1024];

  if (type == 0) {
    pronoun_substitute(buf, player, message, player);
    message = buf+strlen(db[player].name) +1;
  }
  notify (player, message);
}

void do_emit(player,arg1,arg2,type)
     dbref player;
     char *arg1;
     char *arg2;
     int type;
{
  
  dbref loc;
  char *message;
  char buf[BUFFER_LEN], *bf=buf;
  
  if ((loc = getloc(player)) == NOTHING) return;
  if (IS(loc, TYPE_ROOM, ROOM_AUDITORIUM) &&
      !controls(player,loc,POW_SPOOF) &&
      !could_doit(player, loc, A_SLOCK)) {
    did_it(player, loc,A_SFAIL,"Shh.",A_OSFAIL,NULL,
	   A_ASFAIL);
    return;
  }
  message = reconstruct_message(arg1,arg2);
  if ( type == 0 ) {
    pronoun_substitute(buf, player, message, player);
    bf = buf + strlen(db[player].name) + 1;
  }
  if ( type == 1) {
    strcpy(buf, message);
    bf = buf;
  }
  if (power(player, POW_SPOOF)) {
    notify_in(loc,NOTHING,tprintf("%s",bf));
    return;
  }
  if (can_emit_msg(player, db[player].location, bf))
    notify_in(loc,NOTHING,tprintf("%s", bf));
  else 
    notify(player, "Permission denied.");
}

static void notify_in_zone P((dbref, char *));
void notify_in_zone (zone, msg)
     dbref zone;
     char *msg;
{
  dbref thing;
  static int depth=0;
  if (depth > 10)
    return;

  depth++;
  for (thing = 0; thing < db_top; thing++) {
    if (db[thing].zone == zone) {
      notify_in_zone(thing, msg);
      notify_in(thing, NOTHING, msg);
    }
  }
  depth--;
}

void do_general_emit(player,arg1,arg2, emittype)
     dbref player;
     char *arg1;
     char *arg2;
     int emittype;
{
  dbref who;
  char buf[BUFFER_LEN], *bf=buf;
  
  if ( emittype != 4 ) {
    pronoun_substitute(buf, player, arg2, player);
    bf = buf + strlen(db[player].name) + 1;
  }
  if ( emittype == 4 ) {
    bf = arg2;
    while ( *bf && !(bf[0]=='=') ) bf++;
    if (*bf)
      bf++;
    emittype=0;
  }
  
  init_match(player, arg1, TYPE_PLAYER);
  match_absolute();
  match_player();
  
  match_neighbor();
  match_possession();
  match_me();
  match_here();
  who = noisy_match_result();

  if(get_room(who) != get_room(player) && !controls(player,get_room(who),POW_REMOTE) && !controls_a_zone(player, who, POW_REMOTE)) {
    notify(player,"Permission denied.");
    return;
  }
  
  if (IS(db[who].location,TYPE_ROOM, ROOM_AUDITORIUM) &&
      !controls(player,db[who].location,POW_SPOOF) &&
      !could_doit(player, db[who].location, A_SLOCK)) {
    did_it(player, db[who].location,A_SFAIL,"Shhh.",A_OSFAIL,NULL,
	   A_ASFAIL);
    return;
  }
  
  switch( who ) {
  case NOTHING:
    break;
  default:
    if (emittype == 0)	/* pemit */
      if (can_emit_msg(player, db[who].location, bf) ||
	  controls (player, who, POW_SPOOF)) {
	notify(who, bf);
	/*	wptr[0]=bf; */ /* Do not pass %0 */
	did_it(player, who, NULL, 0, NULL, 0, A_APEMIT);
	if(!(db[player].flags&QUIET))
	  notify(player, tprintf("%s just saw \"%s\".",
				 unparse_object(player, who), bf));
      } else
	notify(player, "Permission denied");
    else if (emittype == 1) {	/* room. */
      if (((controls(player, who, POW_REMOTE) &&
	    controls(player, who, POW_SPOOF)) ||
	   db[player].location == who) &&
	  can_emit_msg(player,who,bf)) {
	notify_in(who, NOTHING, bf);
	if(!(db[player].flags&QUIET))
	  notify(player, tprintf("Everything in %s saw \"%s\".",
				 unparse_object(player, who), bf));
      } else {
	notify(player,"Permission denied.");
	return;
      }
    } else if (emittype == 2) { /* oemit */
      if (can_emit_msg(player, db[who].location, bf)) {
	notify_in(db[who].location,who,bf);
      } else {
	notify(player,"Permission denied.");
	return;
      }
    } else if (emittype == 3) /* zone */
      if (controls(player, who, POW_REMOTE) &&
	  controls(player, who, POW_SPOOF) &&
	  controls(player, who, POW_MODIFY) &&
	  can_emit_msg(player, (dbref) -1, bf)) {
	if (db[who].zone == NOTHING && !(db[player].flags&QUIET))
	  notify(player, tprintf("%s might not be a zone... but i'll do it anyways",
				 unparse_object(player, who)));
	notify_in_zone (who, bf);
	if(!(db[player].flags&QUIET))
	  notify(player, tprintf("Everything in zone %s saw \"%s\".",
				 unparse_object(player, who), bf));
      } else
	notify(player, "Permission denied.");
  }
}

int can_emit_msg(player, loc, msg)
     dbref player;
     dbref loc;
     char *msg;
{
  char mybuf[1000];
  char *s;
  dbref thing, save_loc;
  
  strcpy(mybuf, msg);
  for (s = mybuf; *s && (*s != ' '); s++);
  if (*s)
    *s = '\0';

  if ((thing = lookup_player(mybuf)) != NOTHING && !string_compare(db[thing].name, mybuf))
    if (!controls(player, thing, POW_SPOOF)) return 0;
  if ((s-mybuf)>2 && !strcmp(s-2,"'s")) {
    *(s-2) = '\0';
    if ((thing = lookup_player(mybuf)) != NOTHING && !string_compare(db[thing].name, mybuf))
      if (!controls(player, thing, POW_SPOOF)) return 0;
  }
  /* yes, get ready, another awful kludge */
  save_loc = db[player].location;
  db[player].location = loc;
  init_match (player, mybuf, NOTYPE);
  match_perfect();
  db[player].location = save_loc;
  thing = match_result();
  if (thing != NOTHING && !controls(player, thing, POW_SPOOF))
    return 0;
  return 1;
}

void do_announce(player,arg1,arg2)
     dbref player;
     char *arg1;
     char *arg2;
{
  char *message;
  char buf[2000];
#ifndef SYSV_IO
  struct descriptor_data *d;
#endif
  if ( Guest(player) || (Typeof(player)!=TYPE_PLAYER && !power(player,POW_SPOOF))) {
    notify(player, "You can't do that.");
    return;
  }
  
  message = reconstruct_message(arg1, arg2);
  if ( power(player, POW_ANNOUNCE) || payfor(player,ANNOUNCE_COST))
    sprintf(buf, "%s announces \"%s\"", unparse_object(player,player), message);
  else  {
    notify(player,"sorry, you don't have any credits.");
    return;
  }
  log_io(tprintf("%s(#%d) [owner=%s(#%d)] executes: @announce %s",
		 db[player].name, player,
		 db[db[player].owner].name, db[player].owner, message));
  
  /*
    for(i = 0; i < db_top; i++)
    if ( Typeof(i) == TYPE_PLAYER && ! (db[i].flags & NO_WALLS) )
    notify(i, buf);
    */
#ifdef SYSV_IO
  wall_it(buf);
#else
  strcat(buf,"\n");
  for (d = descriptor_list; d; d = d->next)  {
    if ( d->state != CONNECTED)
      continue;
    if ( db[d->player].flags & PLAYER_NO_WALLS )
      continue;
    queue_string(d, buf);
  }
#endif
}

void do_broadcast(player,arg1,arg2)
     dbref player;
     char *arg1;
     char *arg2;
{
  char *message;
#ifndef SYSV_IO
  struct descriptor_data *d;
#endif
  char buf[2000];
  
  if ( ! power(player, POW_BROADCAST) )  {
    notify(player, "You don't have the authority to do that.");
    return;
  }
  
  message = reconstruct_message(arg1, arg2);
#ifdef SYSV_IO
  sprintf(buf, "Official broadcast from %s: \"%s\"",
	  db[player].name, message);
#else
  sprintf(buf, "Official broadcast from %s: \"%s\"\n",
	  db[player].name, message);
#endif
  
  log_important(tprintf("%s(#%d) executes: @broadcast %s",
			db[player].name, player, message));
#ifdef SYSV_IO
  for(i = 0; i < db_top; i++)
    if ( Typeof(i) == TYPE_PLAYER )
      notify(i, buf);
#else
  for (d = descriptor_list; d; d = d->next)  {
    if ( d->state != CONNECTED )
      continue;
    queue_string(d, buf);
  }
#endif
}

void do_gripe(player,arg1,arg2)
     dbref player;
     char *arg1;
     char *arg2;
{
  dbref loc;
  char *message;
  
  loc = db[player].location;
  message = reconstruct_message(arg1, arg2);
  log_gripe(tprintf("GRIPE from %s(%d) in %s(%d): %s",
		    db[player].name, player,
		    db[loc].name, 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(player,arg1,arg2)
     dbref player;
     char *arg1;
     char *arg2;
{
  dbref *x;
  int k;
  
  x=lookup_players(player,arg1);
  if(x[0]==0) return;
  if(!payfor(player, PAGE_COST*(x[0]))) {
    notify(player,"You don't have enough Credits.");
    return;
  }
  for(k=1;k<=x[0];k++) {
    if((db[x[k]].owner==x[k])
       ?(!(db[x[k]].flags & PLAYER_CONNECT))
       :!(*atr_get(x[k],A_APAGE) || Hearer(x[k]))) {
      notify(player,tprintf("%s isn't connected.",db[x[k]].name));
      if(*Away(x[k])) {
	notify(player,
	       tprintf("Away message from %s: %s", spname(x[k]),
		       atr_get(x[k],A_AWAY)));
      }
    } else if(!could_doit(player,x[k],A_LPAGE)) {
      notify(player,
	     tprintf("%s is not accepting pages.",spname(x[k])));
      if(*atr_get(x[k],A_HAVEN)) {
	notify(player,tprintf("Haven message from %s: %s",
			      spname(x[k]),
			      atr_get(x[k],A_HAVEN)));
      }
    } else {
      if(!*arg2) {
	notify(x[k],
	       tprintf( "You sense that %s is looking for you in %s",
		       spname(player), db[db[player].location].name));
	notify(player,
	       tprintf("You notified %s of your location.",spname(x[k])));
	/*	wptr[0]=arg2; */ /* Do not pass %0 */
	did_it(player, x[k], NULL, 0, NULL, 0, A_APAGE);
      } else if ( *arg2 == ':' )  {
	notify(x[k],tprintf("%s page-poses: %s %s",spname(player),spname(player),arg2+1));
	notify(player, tprintf("You page-posed %s with \"%s %s\".",
			       db[x[k]].name,spname(player),arg2+1));
	if (db[x[k]].owner != x[k])
	  wptr[0]=arg2;
	did_it(player, x[k], NULL, 0, NULL, 0, A_APAGE);
      } else {
	notify(x[k],tprintf("%s pages: %s",spname(player),arg2));
	notify(player, tprintf("You paged %s with \"%s\".",
			       spname(x[k]),arg2));
	if (db[x[k]].owner != x[k])
	  wptr[0]=arg2;
	did_it(player, x[k], NULL, 0, NULL, 0, A_APAGE);
      }
      if (*Idle(x[k])) {
	notify(player, 
	       tprintf("Idle message from %s: %s", spname(x[k]),
		       atr_get(x[k],A_IDLE)));
	notify(x[k],
	       tprintf("Your Idle message has been sent to %s.",
		       spname(player)));
      }
    }
  }  
}


void do_use(player,arg1)
     dbref player;
     char *arg1;
{
  dbref thing;
  thing = match_thing(player,arg1);
  if (thing == NOTHING) return;
  did_it(player, thing, A_USE, "You don't know how to use that.", A_OUSE, NULL, A_AUSE);
}