/* speech.c */
#include "os.h"
#include "copyright.h"
/* Commands which involve speaking */
#include "config.h"
#include "externs.h"
#include "db.h"
#include "interface.h"
#include "match.h"
static void emit_notify_except (dbref first, dbref exception, const char *msg);
static void oemit_notify_except (dbref first, dbref exc1, dbref exc2, const char *msg);
static char *spname (dbref thing)
{
static char buff[BUFFER_LEN];
#ifdef FULL_INVIS
if (!Dark (thing)) {
strcpy (buff, db[thing].name);
} else {
if (Typeof (thing) != TYPE_PLAYER) {
strcpy (buff, "Something");
} else {
strcpy (buff, "Someone");
}
}
#else
strcpy (buff, db[thing].name);
#endif
return (buff);
}
/* this function is a kludge for regenerating messages split by '=' */
const char *reconstruct_message (const char *arg1, const char *arg2)
{
static char buf[BUFFER_LEN];
if (arg2 && *arg2) {
strcpy (buf, arg1);
strcat (buf, " = ");
strcat (buf, arg2);
return buf;
} else {
return arg1;
}
}
void do_say (dbref player, const char *arg1, const char *arg2)
{
dbref loc;
const char *message;
char tbuf1[BUFFER_LEN];
if ((loc = getloc (player)) == NOTHING)
return;
message = reconstruct_message (arg1, arg2);
strcpy (tbuf1, pronoun_substitute (player, message, player));
/* notify everybody */
notify (player, tprintf ("You say \"%s\"", tbuf1));
notify_except (db[loc].contents, player,
tprintf ("%s says \"%s\"", spname (player), tbuf1));
}
void do_oemit (dbref player, const char *arg1, const char *arg2)
{
dbref who;
dbref loc;
char tbuf1[BUFFER_LEN];
init_match (player, arg1, TYPE_PLAYER);
if ((loc = getloc (player)) == NOTHING)
return;
match_neighbor ();
match_me ();
switch (who = match_result ()) {
case NOTHING:
case AMBIGUOUS:
who = player;
default:
strcpy (tbuf1, pronoun_substitute (player, arg2, player));
notify (player, tprintf ("%s", tbuf1));
oemit_notify_except (db[loc].contents, player, who, tbuf1);
}
}
void do_whisper (dbref player, const char *arg1, const char *arg2)
{
dbref who;
int key;
const char *gap;
init_match (player, arg1, TYPE_PLAYER);
match_neighbor ();
match_possession ();
match_container ();
match_me ();
if (Wizard (player)) {
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:
gap = " ";
switch (*arg2) {
case SEMI_POSE_TOKEN:
gap = "";
case POSE_TOKEN:
key = 1;
arg2 = arg2 + 1;
break;
default:
key = 2;
break;
}
switch (key) {
case 1:
notify (player, tprintf ("%s senses, \"%s%s%s\"", db[who].name,
db[player].name, gap, arg2));
notify (who, tprintf ("You sense: %s%s%s", db[player].name, gap, arg2));
break;
case 2:
notify (player,
tprintf ("You whisper, \"%s\" to %s.", arg2, db[who].name));
notify (who, tprintf ("%s whispers, \"%s\"", db[player].name, arg2));
break;
}
break;
}
}
void do_pemit (dbref player, const char *arg1, const char *arg2)
{
dbref who;
char tbuf1[BUFFER_LEN];
init_match (player, arg1, NOTYPE);
match_neighbor ();
match_possession ();
match_container ();
match_me ();
match_here ();
match_player ();
match_absolute ();
switch (who = match_result ()) {
case NOTHING:
notify (player, "I don't see that player here.");
break;
case AMBIGUOUS:
notify (player, "I don't know who you mean!");
break;
default:
if (Typeof (who) != TYPE_PLAYER && Typeof (who) != TYPE_THING) {
notify (player, "Only players and things can hear @pemits.");
break;
}
if (Haven (who) && (player != who)) {
notify (player,
tprintf ("I'm sorry, but %s wishes to be left alone now.",
db[who].name));
return;
}
strcpy (tbuf1, pronoun_substitute (player, arg2, player));
notify (player, tprintf ("You pemit \"%s\" to %s.", tbuf1, db[who].name));
if (Nospoof (who)) {
notify (who,
tprintf ("[%s->%s] %s", db[player].name, db[who].name, tbuf1));
} else {
notify (who, tprintf ("%s", tbuf1));
}
break;
}
}
void do_pose (dbref player, const char *arg1, const char *arg2, int space)
{
dbref loc;
const char *message;
char tbuf1[BUFFER_LEN];
if ((loc = getloc (player)) == NOTHING)
return;
message = reconstruct_message (arg1, arg2);
strcpy (tbuf1, pronoun_substitute (player, message, player));
/* notify everybody */
if (!space)
notify_except (db[loc].contents, NOTHING,
tprintf ("%s %s", spname (player), tbuf1));
else
notify_except (db[loc].contents, NOTHING,
tprintf ("%s%s", spname (player), tbuf1));
}
void do_wall (dbref player, const char *arg1, const char *arg2, int key)
{
const char *gap;
const char *message;
if (!Wizard (player)) {
notify (player, "Having delusions of grandeur today, are we?");
return;
}
message = reconstruct_message (arg1, arg2);
gap = " ";
switch (*arg1) {
case SAY_TOKEN:
key = 1;
message = message + 1;
break;
case SEMI_POSE_TOKEN:
gap = "";
case POSE_TOKEN:
key = 2;
message = message + 1;
break;
}
switch (key) {
case 2:
fprintf (stderr, "WALL from %d: %s%s%s\n", player, db[player].name,
gap, message);
raw_broadcast (0, "Announcement: %s%s%s", db[player].name, gap, message);
break;
case 3:
fprintf (stderr, "WALL from %s(%d): %s\n", db[player].name, player,
message);
raw_broadcast (0, "Announcement [%s]: %s", db[player].name, message);
break;
default:
fprintf (stderr, "WALL from %s(%d): %s\n", db[player].name, player,
message);
raw_broadcast (0, "Announcement: %s shouts, \"%s\"", db[player].name,
message);
break;
}
}
void
do_wizwall (dbref player, const char *arg1, const char *arg2, int privs,
int key)
{
/* privs is 0 for wizard wizwall, 1 for royalty-wizard wizwall */
const char *gap;
const char *message;
if (!Wizard (player)
#ifdef ROYALTY_FLAG
&& !Royalty (player)
#endif
) {
notify (player, "What makes you think someone wants to listen to you?");
return;
}
if (!privs && !Wizard (player)) {
notify (player, "Posing as a wizard could be hazardous to your health.");
return;
}
message = reconstruct_message (arg1, arg2);
gap = " ";
switch (*arg1) {
case SAY_TOKEN:
key = 1;
message = message + 1;
break;
case SEMI_POSE_TOKEN:
gap = "";
case POSE_TOKEN:
key = 2;
message = message + 1;
break;
}
if (!privs) {
switch (key) {
case 2:
raw_broadcast (WIZARD, "Broadcast: %s%s%s", db[player].name, gap,
message);
break;
case 3:
raw_broadcast (WIZARD, "Broadcast [%s]: %s", db[player].name, message);
break;
default:
raw_broadcast (WIZARD, "Broadcast: %s says, \"%s\"", db[player].name,
message);
}
}
#ifdef ROYALTY_FLAG
else {
switch (key) {
case 2:
raw_broadcast (WIZARD, "Admin: %s%s%s", db[player].name, gap, message);
raw_broadcast (ROYALTY, "Admin: %s%s%s", db[player].name, gap, message);
break;
case 3:
raw_broadcast (WIZARD, "Admin [%s]: %s", db[player].name, message);
raw_broadcast (ROYALTY, "Admin [%s]: %s", db[player].name, message);
break;
default:
raw_broadcast (WIZARD, "Admin: %s says, \"%s\"", db[player].name,
message);
raw_broadcast (ROYALTY, "Admin: %s says, \"%s\"", db[player].name,
message);
}
}
#endif
}
void do_gripe (dbref player, const char *arg1, const char *arg2)
{
dbref loc;
const char *message;
loc = db[player].location;
message = reconstruct_message (arg1, arg2);
fprintf (stderr, "GRIPE from %s(%d) in %s(%d): %s\n",
db[player].name, player, db[loc].name, loc, message);
fflush (stderr);
/* try telling GOD about it */
if (!Haven (GOD)) {
notify (GOD,
tprintf ("%s gripes: \"%s\"", unparse_object (GOD, player), 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)
{
dbref target;
const char *message, *gap;
char spoof[1024];
int key;
if ((!*arg1) && (!*arg2)) {
if (db[player].pageto == NOTHING) {
notify (player, "You haven't paged anyone since connecting.");
} else {
notify (player,
tprintf ("You last paged %s.", db[db[player].pageto].name));
}
return;
}
if (Haven (player))
notify (player, "You are set HAVEN and cannot receive pages.");
if (index (arg1, ' ') != NULL) {
message = reconstruct_message (arg1, arg2);
target = db[player].pageto;
} else {
message = arg2;
if (!*arg1) {
target = db[player].pageto;
} else if ((target = lookup_player (arg1)) == NOTHING) {
if (!*arg2) {
target = db[player].pageto;
message = arg1;
} else {
target = short_page (arg1);
}
}
}
if (target == NOTHING) {
notify (player, "I can't find who you're trying to page.");
return;
} else if (target == AMBIGUOUS) {
notify (player, "I'm not sure who you want to page!");
return;
} else if ((!(db[target].flags & PLAYER_CONNECT)) ||
(Dark (target) && Haven (target))) {
page_return (player, target, "Away", "AWAY",
"That player is not connected.");
return;
} else if (Haven (target)) {
page_return (player, target, "Haven", "HAVEN",
"That player is not accepting any pages.");
return;
} else if (!eval_boolexp (db[player].owner, db[target].usekey,
target, 0, USELOCK)) {
page_return (player, target, "Haven", "HAVEN",
"That player is not accepting your pages.");
return;
}
if (!payfor (player, PAGE_COST)) {
notify (player, tprintf ("You don't have enough %s.", MONIES));
return;
}
db[player].pageto = target;
gap = " ";
switch (*message) {
case SEMI_POSE_TOKEN:
gap = "";
case POSE_TOKEN:
key = 1;
message = message + 1;
break;
case 0:
key = 2;
break;
default:
key = 3;
break;
}
if (Typeof (player) != TYPE_PLAYER && Nospoof (target))
strcpy (spoof, tprintf ("[#%d] ", player));
else
strcpy (spoof, "");
switch (key) {
case 1:
notify (target, tprintf ("%sFrom afar, %s%s%s", spoof,
db[player].name, gap, message));
notify (player, tprintf ("Long distance to %s: %s%s%s", db[target].name,
db[player].name, gap, message));
break;
case 2:
notify (target, tprintf ("%sYou sense that %s is looking for you in %s",
spoof, db[player].name, db[db[player].location].name));
notify (player, tprintf ("You have paged %s.", db[target].name));
break;
case 3:
notify (target, tprintf ("%s%s pages: %s", spoof, db[player].name,
message));
notify (player, tprintf ("You paged %s with '%s'.", db[target].name,
message));
break;
}
page_return (player, target, "Idle", "IDLE", NULL);
return;
}
static void esnotify (dbref player, const char *msg, dbref sender)
{
if (player < 0 || player >= db_top)
return;
if (Nospoof (player)) {
notify (player, tprintf ("[%s:] %s", spname (sender), msg));
} else {
notify (player, tprintf ("%s", msg));
}
}
void notify_except (dbref first, dbref exception, const char *msg)
{
if (first < 0 || first >= db_top)
return;
if (db[first].location != exception)
notify (db[first].location, msg);
DOLIST (first, first) {
if (first != exception) {
notify (first, msg);
}
}
}
static void emit_notify_except (dbref first, dbref exception, const char *msg)
{
if (first < 0 || first >= db_top)
return;
if (db[first].location != exception)
esnotify (db[first].location, msg, exception);
DOLIST (first, first) {
if (first != exception) {
esnotify (first, msg, exception);
}
}
}
void notify_except2 (dbref first, dbref exc1, dbref exc2, const char *msg)
{
if (first < 0 || first >= db_top)
return;
if ((db[first].location != exc1) && (db[first].location != exc2))
notify (db[first].location, msg);
DOLIST (first, first) {
if (first != exc1 && first != exc2) {
notify (first, msg);
}
}
}
static void
oemit_notify_except (dbref first, dbref exc1, dbref exc2, const char *msg)
{
if (first < 0 || first >= db_top)
return;
if ((db[first].location != exc1) && (db[first].location != exc2))
esnotify (db[first].location, msg, exc1);
DOLIST (first, first) {
if (first != exc1 && first != exc2) {
esnotify (first, msg, exc1);
}
}
}
void do_emit (dbref player, const char *arg1, const char *arg2)
{
dbref loc;
const char *message;
char tbuf1[BUFFER_LEN];
if ((loc = getloc (player)) == NOTHING)
return;
message = reconstruct_message (arg1, arg2);
strcpy (tbuf1, pronoun_substitute (player, message, player));
/* notify everybody */
notify (player, tprintf ("%s", tbuf1));
emit_notify_except (db[loc].contents, player, tbuf1);
}
void do_remit (dbref player, const char *arg1, const char *arg2)
{
dbref room;
const char *rmno;
char tbuf1[BUFFER_LEN];
init_match (player, arg1, NOTYPE);
match_here ();
match_absolute ();
match_neighbor ();
match_me ();
match_player ();
match_exit ();
switch (room = match_result ()) {
case NOTHING:
case AMBIGUOUS:
notify (player, "I can't find that.");
break;
default:
if (Typeof (room) == TYPE_EXIT) {
notify (player, "There can't be anything in that!");
break;
}
if ((Typeof (room) == TYPE_PLAYER) && Haven (room)) {
notify (player, "That person is havened. No @remitting allowed.");
break;
}
strcpy (tbuf1, pronoun_substitute (player, arg2, player));
rmno = unparse_object (player, room);
notify (player, tprintf ("You remit, \"%s\" in %s", tbuf1, rmno));
oemit_notify_except (db[room].contents, player, room, tbuf1);
}
}
void do_lemit (dbref player, const char *arg1, const char *arg2)
{
dbref room;
int rec = 0;
const char *message;
char tbuf1[BUFFER_LEN];
message = reconstruct_message (arg1, arg2);
strcpy (tbuf1, pronoun_substitute (player, message, player));
/* only players and things may use this command */
if (Typeof (player) != TYPE_PLAYER && Typeof (player) != TYPE_THING)
return;
/* prevent infinite loop if player is inside himself */
if ((room = db[player].location) == player) {
notify (player, "Invalid container object.");
return;
}
while ((Typeof (room) != TYPE_ROOM) && (rec < 15)) {
room = db[room].location;
rec++;
}
if (rec > 15) {
notify (player, "Too many containers.");
return;
} else {
notify (player, tprintf ("You lemit: \"%s\"", tbuf1));
oemit_notify_except (db[room].contents, player, room, tbuf1);
}
}
void do_zemit (dbref player, const char *arg1, const char *arg2)
{
const char *where;
dbref zone;
dbref room;
char tbuf1[BUFFER_LEN];
init_match (player, arg1, NOTYPE);
match_absolute ();
switch (zone = match_result ()) {
case NOTHING:
case AMBIGUOUS:
notify (player, "Invalid zone.");
return;
default:
if (!controls (player, zone)) {
notify (player, "Permission denied.");
return;
}
if (!payfor (player, FIND_COST)) {
notify (player, "Sorry, you don't have enough money to do that.");
return;
}
strcpy (tbuf1, pronoun_substitute (player, arg2, player));
where = unparse_object (player, zone);
notify (player, tprintf ("You zemit, \"%s\" in zone %s", tbuf1, where));
for (room = 0; room < db_top; room++)
if ((getzone (room) == zone) && (Typeof (room) == TYPE_ROOM))
oemit_notify_except (db[room].contents, player, room, tbuf1);
}
}