/* -*- LPC -*- */
/*
* $Locker: $
* $Id: speech.c,v 1.36 2003/04/15 17:46:43 ceres Exp $
*/
/* command, trial out by Turrican for a commands daemon. */
#include <language.h>
#include <player.h>
#include <drinks.h>
#include <cmds/options.h>
#define TP this_player()
#define BEEP sprintf("%c",7)
#define CTRL sprintf("%c", 13)
#define REPLACEMENTS (["ne1":"anyone",\
"u":"you",\
"r":"are", \
"NE1":"anyone",\
"U":"you",\
"R":"are", \
"ur":"you are",\
"teh":"the", \
"some1":"someone"])
class message {
string text;
string emote;
string language;
string type;
string notify_mess;
int status;
}
varargs string query_word_type(string str, string def) {
int i;
if (!str || strlen(str) < 1)
return "";
for (i = strlen(str) - 1; i >= 0 && str[i] == ' '; i--);
// Make sure the string is not just spaces
if (i < 0) {
return "discombobulate";
}
switch (str[i]) {
case '!':
return "exclaim";
case '?':
return "ask";
default:
if (def)
return def;
else
return "say";
}
}
string mangle_tell(string mess, object dest) {
int i;
string ret;
if (!TP || !environment(TP))
return mess;
if (environment(TP)->query_property("reverse_tell") &&
!dest->query_creator() && !TP->query_creator()) {
for (i = 0; i < strlen(mess); i++)
ret = mess[i..i] + ret;
return ret;
}
return mess;
} /* mangle_tell() */
string drunk_speech(string str) {
/* I think I like replace already */
return replace(str, ({ "S", "sh", "r", "rr", "ing", "in'", "x", "xsh",
"S", "SH", "R", "RR" }));
}
string de_eight(string arg) {
object g;
string replace_num;
g = (object) TP->query_guild_ob();
if (g && ((string) g->query_name() == "wizards") && !TP->query_creator()) {
arg = "@ " + arg + "@";
replace_num = ({ " seven plus one", " nine minus one",
" two to the power of three",
" four times two" })[random(4)];
arg = implode(explode(arg, " eight"), replace_num);
replace_num = ({ "(7+1)", "(9-1)", "(2^3)", "(4*2)" })[random(4)];
arg = implode(explode(arg, "8"), replace_num);
arg = arg[2.. < 2];
}
return arg;
}
/**
* Replace "ne1" with "anyone" and suchlike.
*/
string fix_shorthand(string mess) {
string *bits, name, value;
mixed *tmp;
int index, i;
bits = explode(mess, " ");
foreach(name, value in REPLACEMENTS) {
tmp = regexp(bits, "(^|[^A-Za-z]+)"+name+"($|[^A-Za-z]+)", 1);
if(sizeof(tmp)) {
for(i=0; i<sizeof(tmp); i+=2) {
index = tmp[i+1]-1;
bits[index] = replace(bits[index], name, value);
}
}
}
return implode(bits, " ");
}
/* to properly columnate word_typed things */
void my_mess(string fish, string erk) {
int bing;
if (!interactive(TP)) {
return;
}
bing = strlen(fish);
if (bing > 15) {
bing = 15;
}
efun::tell_object(TP, TP->fix_string(sprintf("%s%s\n", fish, erk),
(int) TP->query_cols(), bing));
}
class message build_message(string arg, mixed target, string word_type) {
string lang;
string s1;
string emotion;
string word;
string *langs;
int i;
class message mess;
int done;
mess = new (class message);
if (!arg || arg == "" || arg == " ") {
mess->status = NO_MESSAGE;
return mess;
}
// Look for words starting #, @ or :. Take up to two in either order.
while (!done && (!lang || !emotion)) {
switch (arg[0]) {
case '#':
if(word_type == "tell") {
done = 1;
continue;
}
if (arg[1] == '\'' && sscanf(arg, "#'%s' %s", lang, arg) == 2)
continue;
if (sscanf(arg, "%s %s", lang, arg) == 2) {
lang = lang[1..];
// Try and do partial matching.
langs = LANGUAGE_HAND->query_languages();
if (member_array(lang, langs) == -1) {
for (i = 0; i < sizeof(langs); i++) {
if (TP->query_skill(LANGUAGE_HAND->
query_language_spoken_skill(langs[i])) > 1 ||
TP->query_skill(LANGUAGE_HAND->
query_language_written_skill(langs[i])) > 1) {
if (langs[i][0..strlen(lang)-1] == lang) {
lang = langs[i];
}
}
}
}
} else {
done = 1;
}
break;
case '@':
//case ':':
if (sscanf(arg, "%s %s", emotion, arg) == 2) {
emotion = emotion[1..] + " ";
} else {
done = 1;
}
break;
default:
done = 1;
}
}
if (!emotion)
emotion = "";
if(lang == "general" && interactive(TP) && !TP->query_creator()) {
mess->status = NOT_KNOWN;
return mess;
}
if(!lang)
lang = (string) TP->query_current_language();
mess->language = lang;
if(!LANGUAGE_HAND->query_language_spoken(lang)) {
mess->status = NOT_SPOKEN;
return mess;
}
if(word_type == "shout" && !LANGUAGE_HAND->query_language_distance(lang)) {
mess->status = NOT_DISTANCE;
return mess;
}
if(word_type != "tell" &&
!TP->query_skill(LANGUAGE_HAND->query_language_spoken_skill(lang)) &&
!LANGUAGE_HAND->query_language_always_spoken(lang)) {
mess->status = NOT_KNOWN;
return mess;
}
if (!interactive(TP)) {
arg = TP->convert_message(arg);
arg = TP->fit_message(arg);
}
// remove any unwanted stuff from the message.
arg = replace(arg, ({ BEEP, "", CTRL, "", "[A", "", "[B", "", "[C", "",
"[D", "", "%^", " " }));
if(TP->query_property(SHORTHAND_PROP))
arg = LANGUAGES->fix_shorthand(arg);
if(word_type != "tell") {
if(TP->query_volume(D_ALCOHOL))
arg = drunk_speech(arg);
// General speech modifications (curses, etc)
s1 = TP->mangle_speech(arg);
if (stringp(s1))
arg = s1;
if(TP && environment(TP) &&
function_exists("mangle_speech", environment(TP)))
arg = (string) environment(TP)->mangle_speech(word_type, arg, target);
arg = de_eight(arg);
}
word = query_word_type(arg, word_type);
mess->text = arg;
mess->type = word;
mess->emote = emotion;
mess->status = MESSAGE_OK;
if (target)
mess->notify_mess = "$one_short:" + file_name(TP) + "$ " + emotion +
"$V$0=" + word + "s," + word + "$V$ $target$: ";
else
mess->notify_mess = "$one_short:" + file_name(TP) + "$ " + emotion +
"$V$0=" + word + "s," + word + "$V$: ";
return mess;
}
int say_it(class message mess) {
string accent;
if (!environment(TP))
write("You are in limbo, noone can hear you.\n");
switch(mess->status) {
case NO_MESSAGE:
return notify_fail("Syntax: " + query_verb() + " <something>\n");
case NOT_SPOKEN:
return notify_fail(capitalize(mess->language) +
" is not a spoken language.\n");
case NOT_KNOWN:
return notify_fail("You cannot speak " + capitalize(mess->language) + ".\n");
}
TP->remove_hide_invis("hiding");
accent = TP->query_nationality_accent_ob();
TP->comm_event(environment(TP), "person_say",
mess->notify_mess, mess->text, mess->language, accent);
if (mess->language != TP->query_default_language() &&
mess->language != "general") {
my_mess("You " + mess->emote + mess->type + " in " +
capitalize(mess->language) + ": ", mess->text);
} else {
my_mess("You " + mess->emote + mess->type + ": ", mess->text);
}
TP->adjust_time_left(-5);
return 1;
}
int say_it_to(class message mess, mixed targets, int priv, string event) {
string lstr;
string extra;
string accent;
if (!environment(TP)) {
write("You are in limbo, noone can hear you.\n");
}
switch(mess->status) {
case NO_MESSAGE:
return notify_fail("Syntax: " + query_verb() + " <something>\n");
case NOT_SPOKEN:
return notify_fail(capitalize(mess->language) +
" is not a spoken language.\n");
case NOT_KNOWN:
return notify_fail("You cannot speak " + capitalize(mess->language) + ".\n");
}
if (!sizeof(targets)) {
return 0;
}
targets -= ({ this_player() });
TP->remove_hide_invis("hiding");
this_player()->adjust_time_left(-5);
accent = TP->query_nationality_accent_ob();
switch (mess->type) {
case "exclaim":
case "whisper":
case "say":
extra = "to ";
break;
default:
extra = "";
}
switch (priv) {
case 2: // Only recipients see anything.
break;
case 1: // Everyone sees it happen but not what's said
TP->comm_event_to(environment(this_player()), event,
(string) this_player()->one_short(1) +
" " + mess->emote + mess->type + "s " +
extra, mess->text, targets, mess->language,
this_player(), accent);
break;
case 0: // Everyone hears it all.
TP->comm_event(environment(TP), event,
"$one_short:" + file_name(TP) + "$ " + mess->emote +
"$V$0=" + mess->type + "s," + mess->type + "$V$ " +
extra + query_multiple_short(targets, "the") + ": ",
mess->text, mess->language, accent);
break;
}
if (mess->language != TP->query_default_language() &&
mess->language != "general") {
lstr = " in " + cap_words(mess->language);
} else {
lstr = "";
}
write("You " + mess->emote + mess->type + " " + extra +
query_multiple_short(targets, "the") + lstr + ": " +
mess->text + "\n");
return 1;
} /* say_it_to() */