TinyMAZE/
TinyMAZE/config/
TinyMAZE/doc/
TinyMAZE/run/msgs/
TinyMAZE/src/
TinyMAZE/src/db/
TinyMAZE/src/ident/
TinyMAZE/src/io/
TinyMAZE/src/prog/
TinyMAZE/src/softcode/
TinyMAZE/src/util/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "db.h"
#include "externs.h"

static int can_emit_msg P((OBJ *, OBJ *, char *));

/* This function is a kludge for regenerating messages split by '=' */
char *reconstruct_message(char *arg1, char *arg2)
{
  char buf[4096];
  
  if(!arg2 || !*arg2)
    return(arg1);

  strcpy(buf, (arg1)?arg1:"");
  strcat(buf, "=");
  strcat(buf, arg2);

  return(stack_string_alloc(buf, 0));
}

void do_say(OBJ *player, char *arg1, char *arg2)
{
  OBJ *loc = player->location;
  char *message;

  if(!loc)
    return;

  message = reconstruct_message(arg1, arg2);

  notify(player, tprintf("You say, \"%s|n|\"", message));
  notify_in(loc, player,
    tprintf("%s says, \"%s|n|\"", name(player), message));
}

static void pose_it(OBJ *player, char *arg1, char *arg2, int possessive)
{
  char *message;

  message = reconstruct_message(arg1, arg2);

  if(possessive)
    notify_in(player->location, NULL,
      tprintf("%s %s", poss(player), message));
  else
    notify_in(player->location, NULL,
      tprintf("%s %s", name(player), message));
}

void do_pose(OBJ *player, char *arg1, char *arg2)
{
  pose_it(player, arg1, arg2, 0);
}

void do_poss(OBJ *player, char *arg1, char *arg2)
{
  pose_it(player, arg1, arg2, 1);
}

void do_echo(OBJ *player, char *arg1, char *arg2)
{
  char *message = reconstruct_message(arg1, arg2);

  notify(player, message);
}

void do_necho(OBJ *player, char *msg)
{
  notify(player, msg);
}

static void emit_to(OBJ *player, OBJ *thing, OBJ *exception, char *msg)
{
  if(!can_emit_msg(player, thing, msg))
  {
    notify(player, perm_denied());
    return;
  }

  if(Typeof(thing) == TYPE_ROOM)
    notify_in(thing, exception, msg);
  else
    notify(thing, msg);
}

void do_emit(OBJ *player, char *arg1, char *arg2)
{
  char *msg = reconstruct_message(arg1, arg2);

  emit_to(player, player->location, NULL, msg);
}

void do_oemit(OBJ *player, char *arg1, char *arg2)
{
  OBJ *ex;

  ex = match_object(player, arg1, NOTYPE);
  if(!ex)
  {
    notify(player, no_match(arg1));
    return;
  }

  emit_to(player, player->location, ex, arg2);
}

void do_pemit(OBJ *player, char *arg1, char *arg2)
{
  OBJ *who;

  who = match_object(player, arg1, NOTYPE);
  if(!who)
  {
    notify(player, no_match(arg1));
    return;
  }

  emit_to(player, who, NULL, arg2);
}

void do_remit(OBJ *player, char *arg1, char *arg2)
{
  OBJ *loc;

  loc = match_object(player, arg1, NOTYPE);
  if(!loc)
  {
    notify(player, no_match(arg1));
    return;
  }

  emit_to(player, loc, NULL, arg2);
}

void do_nemit(OBJ *player, char *arg1)
{
  emit_to(player, player->location, NULL, arg1);
}

void do_noemit(OBJ *player, char *arg1, char *arg2)
{
  OBJ *ex;

  ex = match_object(player, arg1, NOTYPE);
  if(!ex)
  {
    notify(player, no_match(arg1));
    return;
  }

  emit_to(player, player->location, ex, arg2);
}

void do_npemit(OBJ *player, char *arg1, char *arg2)
{
  OBJ *who;

  who = match_object(player, arg1, NOTYPE);
  if(!who)
  {
    notify(player, no_match(arg1));
    return;
  }

  emit_to(player, who, NULL, arg2);
}

static int can_emit_msg(OBJ *player, OBJ *loc, char *msg)
{
  char mybuf[4096];
  char *s;
  OBJ *thing;

  for(;*msg == ' ';msg++);
  
  strcpy(mybuf, msg);
  for(s = mybuf;*s && (*s != ' ');s++);
  if(*s)
    *s = '\0';

  if((thing = match_player(NULL, mybuf)) &&
    !string_compare(thing->name, mybuf))
  {
    if(!controls(player, thing, POW_SPOOF))
      return(0);
  }

  if((s-mybuf) > 2 && !strcmp(s-2, "'s"))
  {
    *(s-2) = '\0';
    if((thing = match_player(NULL, mybuf)) &&
      !string_compare(thing->name, mybuf))
    {
      if(!controls(player, thing, POW_SPOOF))
        return(0);
    }
  }

  return(1);
}

void do_announce(OBJ *player, char *arg1, char *arg2)
{
  char *message;
  char buf[4096];

  if(Typeof(player) != TYPE_PLAYER)
  {
    notify(player, perm_denied());
    return;
  }

  message = reconstruct_message(arg1, arg2);

  if(player->flags & PLAYER_NO_ANN)
  {
    notify(player, "You aren't allowed to @announce.");
    log_io(tprintf("%s(#%d) [owner=%s(#%d)] (NO_ANN) attempted to @announce %s",
      name(player), player->dbref,
      name(player->owner), player->owner->dbref, message));
    return;
  }
  
  if(!power(player, POW_ANNOUNCE) && !payfor(player, config.announce_cost))
  {
    notify(player, tprintf("You need %d %s to @announce.",
      config.announce_cost, config.currency_plural));
    return;
  }

  if(*arg1 == ';')
    sprintf(buf, "From across the MAZE, %s %s|n|", poss(player), arg1+1);
  else if(*arg1 == ':')
    sprintf(buf, "From across the MAZE, %s %s|n|", name(player), arg1+1);
  else
  {
    if(power(player, POW_ANNOUNCE))
      sprintf(buf, "%s announces \"%s|n|\"", name(player), message);
    else
      sprintf(buf, "%s announces \"%s|n|\"",
        unparse_object(player, player), message);
  }

  log_io(tprintf("%s(#%d) [owner=%s(#%d)] executes: @announce %s",
    name(player), player->dbref,
    name(player->owner), player->owner->dbref, message));

  notify_except_flag(buf, NULL, PLAYER_NO_WALLS);
}

void do_broadcast(OBJ *player, char *arg1, char *arg2)
{
  char *message;
  char buf[2000];
  
  if(!power(player, POW_BROADCAST))
  {
    notify(player, perm_denied());
    return;
  }
  
  message = reconstruct_message(arg1, arg2);

  if(*message == ':')
    sprintf(buf, "Official broadcast from %s: %s %s",
         name(player), name(player), message+1);
  else if(*message == ';')
    sprintf(buf, "Official broadcast from %s: %s %s",
         name(player), poss(player), message+1);
  else
    sprintf(buf, "Official broadcast from %s: \"%s\"",
	  name(player), message);
  
  log_important(tprintf("%s(#%d) executes: @broadcast %s",
    name(player), player->dbref, message));

  notify_all(buf, NULL);
}

void do_gripe(OBJ *player, char *arg1, char *arg2)
{
  OBJ *loc = player->location;
  char *message;
  
  message = reconstruct_message(arg1, arg2);

  if(!*message)
  {
    notify(player, "Gripe about what?");
    return;
  }

  log_gripe(tprintf("GRIPE from %s(%d) in %s(%d): %s",
    name(player), player->dbref, name(loc), loc->dbref, message));
  
  notify(player, "Your complaint has been duly noted.");
}

void do_cemit(OBJ *player, char *arg1, char *arg2)
{
  char *channel;

  if(!power(player, POW_SPOOF))
  {
    notify(player, perm_denied());
    return;
  }

  channel = unparse_com_alias(player, arg1);

  if(!*channel)
  {
    notify(player, tprintf("Unknown channel: %s", arg1));
    return;
  }

  com_send(channel, NULL, arg2);
  log_important(tprintf("%s executed: @cemit %s=%s",
    unparse_object(player, player), channel, arg2));
}

void do_wemit(OBJ *player, char *arg1, char *arg2)
{
  char *message;

  message = reconstruct_message(arg1, arg2);

  if(!power(player, POW_BROADCAST))
  {
    notify(player, perm_denied());
    return;
  }

  notify_all(message, NULL);

  log_important(tprintf("%s executed: @wemit %s",
    unparse_object(player, player), message));
}

void do_dpage(OBJ *player, char *arg1, char *arg2)
{
  DDATA *d;
  int descriptor = atoi(arg1);

  if(!power(player, POW_BROADCAST))
  {
    notify(player, perm_denied());
    return;
  }

  for(d = descriptor_list;d;d = d->next)
    if(d->descriptor == descriptor)
      break;

  if(!d)
  {
    notify(player, "Invalid descriptor.");
    return;
  } 

  queue_string(d,
    tprintf("Message from %s: %s", player->name, arg2), 1);

  notify(player,
    tprintf("You sent the message '%s' to descriptor %d%s.",
    arg2, descriptor, (check_state(d, STATE_CONNECTED))?tprintf(" (player %s)",
    unparse_object(player, d->player)):""));
}

void do_to(OBJ *player, char *arg1, char *arg2)
{
  OBJ *loc = player->location;
  OBJ *to;
  char buf[4096];
  char *msg;

  if(!(msg = strchr(arg1, ' ')))
    msg = "";
  else
    *msg++ = '\0';

  to = match_object(player, arg1, TYPE_PLAYER);
  if(!to || to->location != loc)
  {
    notify(player, no_match(arg1));
    return;
  }

  if(*msg == ':')
    sprintf(buf, "%s %s", name(player), msg+1);
  else if(*msg == ';')
    sprintf(buf, "%s %s", poss(player), msg+1);
  else
    sprintf(buf, "%s", msg);

  notify_in(loc, NULL,
    tprintf("%s |+W|[|n|to %s|+W|]|n|: %s",
    name(player), name(to), buf));
}

void do_think(OBJ *player, char *arg)
{
  char buf[4096];

  if(*arg == ':')
    sprintf(buf, "%s |+N|. |B|o |+B|O |+C|( |n|%s %s |+C|)",
      name(player), name(player), arg+1);
  else if(*arg == ';')
    sprintf(buf, "%s |+N|. |B|o |+B|O |+C|( |n|%s %s |+C|)",
      name(player), poss(player), arg+1);
  else
    sprintf(buf, "%s |+N|. |B|o |+B|O |+C|( |n|%s |+C|)",
      name(player), arg);

  notify_in(player->location, NULL, buf);
}

/* Bit definitions for type */
/* 0x0 - Parse neither */
/* 0x1 - Parse to      */
/* 0x2 - Parse think   */
/* 0x3 - Parse both    */
int unparse_tothink(OBJ *player, char *msg, char *retbuf, int tolerant,
                    int type)
{
  OBJ *victim;
  char *m = msg;
  char buf[4096], buf2[4096], to_buf[4096];
  char to = 0, think = 0;
  char *begin = "|+N|. |B|o |+B|O |+C|(|n| ";
  char *end = " |+C|)";

  if(type & 0x1 && *msg == TO_TOKEN)
  {
    to = 1;
    m++;
    while(*m && !isspace(*m))
      m++;
    strncpy(buf, msg+1, m-(msg+1));
    *(buf+(m-(msg+1))) = '\0';

    if(!(victim = match_player(NULL, buf)))
    {
      to = 0;

      if(!tolerant)
      {
        notify(player, no_match(buf));
        return(-1);
      }
      else
        m = msg;
    }

    if(m != msg)
    {
      sprintf(to_buf, "|+W|[to %s|+W|]:|n| ", name(victim));
      m++;
    }
  }

  if(type & 0x2 && *m == THINK_TOKEN)
  {
    think = 1;
    m++;
    if(*m == POSE_TOKEN)
      sprintf(buf2, "%s%s %s%s", begin, name(player), m+1, end);
    else if(*m == POSS_TOKEN)
      sprintf(buf2, "%s%s %s%s", begin, poss(player), m+1, end);
    else
    sprintf(buf2, "%s%s%s", begin, m, end);
  }

  if(to && think)
  {
    sprintf(retbuf, "%s%s", to_buf, buf2);
    return(1);
  }
  if(to && !think)
  {
    if(*m == POSE_TOKEN)
      sprintf(retbuf, "%s%s %s", to_buf, name(player), m+1);
    else if(*m == POSS_TOKEN)
      sprintf(retbuf, "%s%s %s", to_buf, poss(player), m+1);
    else
      sprintf(retbuf, "%s%s", to_buf, m);
    return(1);
  }
  if(!to && think)
  {
    strcpy(retbuf, buf2);
    return(1);
  }

  if(*msg == POSE_TOKEN)
  {
    strcpy(retbuf, msg+1);
    return(1);
  }
  if(*msg == POSS_TOKEN)
  {
    strcpy(retbuf, msg+1);
    return(2);
  }

  strcpy(retbuf, msg);
  return(0);
}