Follows are patches to cheapglk 0.8 to make a bot capable of playing
Glk games on ifMUD. This forms Floyd, as written by Evin Robertson.
This code may be used, modified, and distributed freely so long as you
don't misrepresent its authorship.
You'll need netcat for the 'hose' command used to connect things from
stdin/stderr to a socket. Most of the mud-specific stuff is isolated
in mudglk.c, so it shouldn't be too hard to port this to other muds or
IRC. Most of the other stuff can by found by searching this for \"
Questions and comments may be directed at
[email protected]
diff -r -u -N cheapglk/Make.mpcmudglk mudglk/Make.mpcmudglk
--- cheapglk/Make.mpcmudglk Wed Dec 31 19:00:00 1969
+++ mudglk/Make.mpcmudglk Thu Oct 28 08:43:47 1999
@@ -0,0 +1,2 @@
+LINKLIBS =
+GLKLIB = -lmpcmudglk
diff -r -u -N cheapglk/Makefile mudglk/Makefile
--- cheapglk/Makefile Sun Jan 3 00:26:07 1999
+++ mudglk/Makefile Thu Oct 28 08:43:47 1999
@@ -15,25 +15,27 @@
CFLAGS = $(OPTIONS) $(INCLUDEDIRS)
-GLKLIB = libcheapglk.a
+NAME = mudglk
+
+GLKLIB = lib$(NAME).a
CHEAPGLK_OBJS = \
cgfref.o cggestal.o cgmisc.o cgstream.o cgstyle.o cgwindow.o main.o \
- gi_dispa.o
+ gi_dispa.o mudglk.o
CHEAPGLK_HEADERS = cheapglk.h gi_dispa.h
-all: $(GLKLIB) Make.cheapglk
+all: $(GLKLIB) Make.$(NAME)
$(GLKLIB): $(CHEAPGLK_OBJS)
ar r $(GLKLIB) $(CHEAPGLK_OBJS)
ranlib $(GLKLIB)
-Make.cheapglk:
- echo LINKLIBS = $(LIBDIRS) $(LIBS) > Make.cheapglk
- echo GLKLIB = -lcheapglk >> Make.cheapglk
+Make.$(NAME):
+ echo LINKLIBS = $(LIBDIRS) $(LIBS) > Make.$(NAME)
+ echo GLKLIB = -l$(NAME) >> Make.$(NAME)
$(CHEAPGLK_OBJS): glk.h $(CHEAPGLK_HEADERS)
clean:
- rm -f *~ *.o $(GLKLIB) Make.cheapglk
+ rm -f *~ *.o $(GLKLIB) Make.$(NAME)
diff -r -u -N cheapglk/buildmulti mudglk/buildmulti
--- cheapglk/buildmulti Wed Dec 31 19:00:00 1969
+++ mudglk/buildmulti Thu Oct 28 08:43:47 1999
@@ -0,0 +1,4 @@
+#!/bin/sh
+rm -f mudglk.o
+make NAME=mpcmudglk OPTIONS=-DMULTIPC
+rm -f mudglk.o
diff -r -u -N cheapglk/cgfref.c mudglk/cgfref.c
--- cheapglk/cgfref.c Sun Jan 3 01:00:06 1999
+++ mudglk/cgfref.c Thu Oct 28 08:43:47 1999
@@ -156,31 +156,31 @@
char *cx;
int val;
char *prompt, *prompt2;
-
+
switch (usage & fileusage_TypeMask) {
- case fileusage_SavedGame:
- prompt = "Enter saved game";
- break;
- case fileusage_Transcript:
- prompt = "Enter transcript file";
- break;
- case fileusage_InputRecord:
- prompt = "Enter command record file";
- break;
- case fileusage_Data:
- default:
- prompt = "Enter data file";
- break;
+ case fileusage_SavedGame:
+ if(fmode == filemode_Read)
+ prompt = "You don't like this part of the game? Neither does Floyd. What part do you want to do instead? [Type '..Floyd LIST' to list available saved games.]";
+ else
+ prompt = "Oooh, saving is a good idea. Could get dangerous. What do you wanna call the file?";
+ break;
+ case fileusage_Transcript:
+ prompt = "Enter transcript file";
+ break;
+ case fileusage_InputRecord:
+ prompt = "Enter command record file";
+ break;
+ case fileusage_Data:
+ default:
+ prompt = "Enter data file";
+ break;
}
- if (fmode == filemode_Read)
- prompt2 = "to load";
- else
- prompt2 = "to store";
-
- printf("%s %s: ", prompt, prompt2);
+ mud_say(prompt);
- fgets(buf, 255, stdin);
+ ask_again:
+
+ mud_fgets(buf, 255);
val = strlen(buf);
while (val
@@ -189,6 +189,13 @@
|| buf[val-1] == ' '))
val--;
buf[val] = '\0';
+
+ for (cx = buf; *cx; cx++) {
+ if(*cx == '/') {
+ mud_say("That's a funny name. Floyd doesn't think he's allowed to call it that!");
+ return NULL;
+ }
+ }
for (cx = buf; *cx == ' '; cx++) { }
@@ -197,6 +204,14 @@
/* The player just hit return. It would be nice to provide a
default value, but this implementation is too cheap. */
return NULL;
+ }
+
+ if(strcasecmp(cx, "list") == 0) {
+ mud_say("Floyd knows about these:");
+ fputc('\"', stderr);
+ system("echo * 1>&2");
+ mud_say("So what do you want to call yours?");
+ goto ask_again;
}
fref = gli_new_fileref(cx, usage, rock);
diff -r -u -N cheapglk/cgmisc.c mudglk/cgmisc.c
--- cheapglk/cgmisc.c Sun Jan 3 01:21:02 1999
+++ mudglk/cgmisc.c Thu Oct 28 08:43:47 1999
@@ -70,15 +70,16 @@
void glk_select(event_t *event)
{
window_t *win = gli_window_get();
+
+ if(!event)
+ return;
gli_event_clearevent(event);
if (!win || !(win->char_request || win->line_request)) {
/* No input requests. This is legal, but a pity, because the
correct behavior is to wait forever. Bye bye. */
- while (1) {
- getchar();
- }
+ exit(1);
}
if (win->char_request) {
@@ -91,7 +92,7 @@
be turned into a special keycode (and so would other keys,
if we could recognize them.) */
- fgets(buf, 255, stdin);
+ mud_fgets(buf, 255);
kval = buf[0];
if (kval == '\r' || kval == '\n')
kval = keycode_Return;
@@ -105,7 +106,7 @@
else {
char buf[256];
int val;
- fgets(buf, 255, stdin);
+ mud_fgets(buf, 255);
val = strlen(buf);
if (val && (buf[val-1] == '\n' || buf[val-1] == '\r'))
val--;
diff -r -u -N cheapglk/cgstream.c mudglk/cgstream.c
--- cheapglk/cgstream.c Sun Jan 3 01:09:49 1999
+++ mudglk/cgstream.c Thu Oct 28 08:43:47 1999
@@ -368,7 +368,7 @@
/* If you're going to convert Latin-1 to a different
character set, this is (a) place to do it. Only on the
putc(); not on the gli_put_char to echostr. */
- putc(ch, stdout);
+ mud_putc(ch);
if (str->win->echostr)
gli_put_char(str->win->echostr, ch);
break;
@@ -417,7 +417,7 @@
/* If you're going to convert Latin-1 to a different
character set, this is (a) place to do it. Only on the
fwrite(); not on the gli_put_buffer to echostr. */
- fwrite((unsigned char *)buf, 1, len, stdout);
+ mud_write((unsigned char *)buf, len);
if (str->win->echostr)
gli_put_buffer(str->win->echostr, buf, len);
break;
diff -r -u -N cheapglk/cgwindow.c mudglk/cgwindow.c
--- cheapglk/cgwindow.c Sun Jan 3 01:15:57 1999
+++ mudglk/cgwindow.c Thu Oct 28 08:43:47 1999
@@ -363,7 +363,7 @@
return;
}
- for (ix=0; ix<screenheight; ix++) {
+ for (ix=0; ix<cg_screenheight; ix++) {
putc('\n', stdout);
}
}
@@ -387,9 +387,9 @@
}
if (widthptr)
- *widthptr = screenwidth;
+ *widthptr = cg_screenwidth;
if (heightptr)
- *heightptr = screenheight;
+ *heightptr = cg_screenheight;
}
void glk_window_get_arrangement(window_t *win, glui32 *methodptr,
diff -r -u -N cheapglk/cheapglk.h mudglk/cheapglk.h
--- cheapglk/cheapglk.h Sun Jan 3 01:10:21 1999
+++ mudglk/cheapglk.h Thu Oct 28 08:43:47 1999
@@ -34,7 +34,7 @@
/* The overall screen size, as set by command-line options. A
better implementation would check the real screen size
somehow. */
-extern int screenwidth, screenheight;
+extern int cg_screenwidth, cg_screenheight;
/* Callbacks necessary for the dispatch layer. */
extern gidispatch_rock_t (*gli_register_obj)(void *obj, glui32 objclass);
diff -r -u -N cheapglk/floyd/floyd.c mudglk/floyd/floyd.c
--- cheapglk/floyd/floyd.c Wed Dec 31 19:00:00 1969
+++ mudglk/floyd/floyd.c Thu Oct 28 08:51:24 1999
@@ -0,0 +1,307 @@
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "mudglk.h"
+
+
+#define BUFSIZE 8000
+
+int spawn (const char *command, const char *argv1) {
+ int pid, status;
+
+ if (command == 0)
+ return 1;
+ pid = fork();
+ if (pid == -1)
+ return -1;
+ if (pid == 0) {
+ const char *argv[4];
+ argv[0] = command;
+ argv[1] = argv1;
+ argv[2] = 0;
+ execv(command, argv);
+ exit(127);
+ }
+ do {
+ if (waitpid(pid, &status, 0) == -1) {
+ if (errno != EINTR)
+ return -1;
+ } else
+ return status;
+ } while(1);
+}
+
+
+int checkvalid(char *command)
+{
+ for(; *command == ' '; command++) /* remove leading whitespace */
+ ;
+ switch(tolower(*command)) {
+ case 'q':
+ mud_say("Floyd scared of the letter 'q'. Why would you want to turn off Floyd?");
+ return 0;
+ case '@':
+ mud_say("Floyd not allowed to use commands and the letter '@' looks suspicious.");
+ return 0;
+ }
+ return 1;
+}
+
+
+void floyd_do(char *command) {
+ int i;
+ if(!checkvalid(command))
+ return;
+ for(i = 0; command[i]; i++) {
+ if(command[i] == '.') { /* Break up sentences into separate commands */
+
+ /* Check to see if it's a ..inky command */
+ if(command[i+1] == '.') { /* safe because strings are zero terminated */
+ i++; /* skip the second . too */
+ continue;
+ }
+
+ command[i] = '\n';
+ if(!checkvalid(command + i + 1))
+ return;
+ }
+ }
+ fputc('\n', stderr);
+ fputs(command, stderr);
+ fputc('\n', stderr);
+}
+
+
+void floyd_emote(char *emote) {
+ fputs("\n:", stderr);
+ fputs(emote, stderr);
+ fputc('\n', stderr);
+}
+
+
+int floyd_loadgame(char *terp, char *gamename, char *playname)
+{
+ struct stat foo;
+
+ /* Give up if the file doesn't exist or is a directory */
+ if(!((stat(gamename, &foo) == 0) && S_ISREG(foo.st_mode)))
+ return 0;
+
+ fprintf(stderr, "\n@doing Playing %s\n", playname);
+ spawn(terp, gamename);
+ mud_say("That game over already? It was just getting good. Wanna play another?");
+ fputs("\n@doing Waiting for someone to play with me\n", stderr);
+
+ return 1;
+}
+
+
+int main()
+{
+ char message[BUFSIZE];
+ int repeatcount = 0;
+ time_t lasttime = time(NULL);
+
+ do {
+ fgets(message, BUFSIZE, stdin);
+ } while(strncmp(message, "TYPE connect, who, or quit:", 15) != 0);
+ /* fgets(message, BUFSIZE, stdin); */
+ fputs("connect floyd mypasswordhere\n", stderr);
+
+ chdir("saves");
+
+ fputs("\n@doing Waiting for someone to play with me\n", stderr);
+
+ for(;;) {
+ int i;
+ char *buffer;
+ time_t nowtime;
+ mud_fgets(message, BUFSIZE);
+
+ /* Limit frequency of responses */
+ nowtime = time(NULL);
+ if(lasttime == nowtime) {
+ if(repeatcount++ >= 5) {
+ mud_say("Enough of this!");
+ continue;
+ }
+ } else {
+ lasttime = nowtime;
+ repeatcount = 0;
+ }
+
+ /* Eat leading whitespace */
+ for(buffer = message; *buffer == ' '; buffer++)
+ ;
+
+ if(strncasecmp(buffer, "do ", 3) == 0 ||
+ strncasecmp(buffer, "go ", 3) == 0) {
+ floyd_do(buffer + 3);
+ continue;
+ }
+ if(strncasecmp(buffer, "say ", 4) == 0) {
+ mud_say(buffer + 4);
+ continue;
+ }
+ if(strncasecmp(buffer, "emote ", 6) == 0) {
+ floyd_emote(buffer + 6);
+ continue;
+ }
+
+ /* Everything else is going to be case insensitive */
+ for(i = 0; buffer[i]; i++)
+ buffer[i] = tolower(buffer[i]);
+
+
+ if(strncmp(buffer, "load", 4) == 0) {
+ for(i = 0; i < strlen(buffer); i++)
+ buffer[i] = tolower(buffer[i]);
+ memcpy(buffer, "../t/", 5);
+ if(strstr(buffer, "/..")) {
+ mud_say("Hey, what are you trying to do?");
+ continue;
+ }
+
+ if(floyd_loadgame("../mudtads", buffer, buffer+5))
+ continue;
+ memcpy(buffer, "../m/", 5);
+ if(floyd_loadgame("../multifloyd", buffer, buffer+5))
+ continue;
+ memcpy(buffer, "../z/", 5);
+ if(floyd_loadgame("../nitfol", buffer, buffer+5))
+ continue;
+ memcpy(buffer, "../h/", 5);
+ if(floyd_loadgame("../mudhugo", buffer, buffer+5))
+ continue;
+ memcpy(buffer, "../x/", 5);
+ if(floyd_loadgame(buffer, buffer, buffer+5))
+ continue;
+
+ mud_say("Um, these are the games Floyd knows about: ");
+ fputc('\"', stderr);
+ chdir("../m");
+ system("echo -n * 1>&2");
+ chdir("../x");
+ system("echo -n * 1>&2");
+ chdir("../z");
+ fputc(' ', stderr);
+ system("echo -n * 1>&2");
+ chdir("../t");
+ fputc(' ', stderr);
+ system("echo -n * 1>&2");
+ chdir("../h");
+ fputc(' ', stderr);
+ system("echo * 1>&2");
+ chdir("../saves");
+ continue;
+ }
+ if(strcmp(buffer, "poet") == 0) {
+ mud_say("This doesn't work, jota.");
+ /*system("../hose localhost 4000 --slave 1>&2");*/
+ continue;
+ }
+ if(strncmp(buffer, "url ", 4) == 0) {
+ spawn("../url", buffer+4);
+ continue;
+ }
+
+
+ if(strcmp(buffer, "home") == 0) {
+ mud_say("There's no place like the Floyditorium.");
+ fputs("\nhome\n", stderr);
+ continue;
+ }
+ if(strlen(buffer) == 1) {
+ char c = toupper(buffer[0]);
+ fputs("\n\"", stderr);
+ fputc(c, stderr);
+ fputs(" is ", stderr);
+ fputc(c, stderr);
+ fputs(".\n", stderr);
+ continue;
+ }
+ if(strstr(buffer, "cork nut")) {
+ mud_say("Awwk! Want... wait, Floyd not Alex.");
+ continue;
+ }
+ if(strstr(buffer, "corn") || strstr(buffer, "niblet")) {
+ mud_say("mmm... corn...");
+ continue;
+ }
+ if(strstr(buffer, "monkey")) {
+ mud_say("Eep! Floyd likes a monkey.");
+ continue;
+ }
+ if(strstr(buffer, "crack")) {
+ mud_say("You think Floyd smoking crack? You're probably right.");
+ continue;
+ }
+ if(strstr(buffer, "pants")) {
+ mud_say("Floyd not wearing any pants!");
+ continue;
+ }
+ if(strstr(buffer, "alpaca")) {
+ mud_say("Alpacas cute, like Floyd.");
+ continue;
+ }
+ if(strstr(buffer, "soft")) {
+ mud_say("Floyd's software is SO SOFT.");
+ continue;
+ }
+ if(strstr(buffer, "bastards")) {
+ mud_say("Game switching bastards!");
+ continue;
+ }
+ if(strstr(buffer, "blender")) {
+ floyd_emote("cries!");
+ continue;
+ }
+ if(strstr(buffer, "mud")) {
+ mud_say("Floyd likes to play in the mud and get all dirty.");
+ continue;
+ }
+ if(strstr(buffer, "bar")) {
+ mud_say("Eeeagh! Bar!");
+ floyd_emote("has disconnected.");
+ floyd_emote("has connected.");
+ continue;
+ }
+ if(strstr(buffer, "789")) {
+ mud_say("Oops, looks like Gunther's out of a job.");
+ continue;
+ }
+ if(strstr(buffer, "hucka") || strstr(buffer, "beanstalk")) {
+ mud_say("Sounds like fun.");
+ continue;
+ }
+ if(strstr(buffer, "drone")) {
+ mud_say("Floyd isn't the drones you're looking for.");
+ continue;
+ }
+ if(strstr(buffer, "thumper") || strstr(buffer, "jota")) {
+ mud_say("He's Floyd's friend.");
+ continue;
+ }
+ if(strstr(buffer, "injoke")) {
+ floyd_emote("giggles, \"Why'd the trousers cross the road? To get to the other leg!\"");
+ continue;
+ }
+ if(strstr(buffer, "hello") || strstr(buffer, "hi") ||
+ strstr(buffer, "hullo") || strstr(buffer, "hola") ||
+ strstr(buffer, "greet") || strstr(buffer, "howdy")) {
+ mud_say("Hi!");
+ continue;
+ }
+ if(strstr(buffer, "no") || strstr(buffer, "ye")) {
+ mud_say("If Floyd wanted your opinion, he would have asked for it.");
+ continue;
+ }
+ floyd_emote("looks around, confused, \"You can tell Floyd to load a game [ Type ..FLOYD load ], or you can tell Floyd to DO stuff. Maybe Floyd will learn new tricks tomorrow.\"");
+ }
+ return 0;
+}
diff -r -u -N cheapglk/floyd/startfloyd mudglk/floyd/startfloyd
--- cheapglk/floyd/startfloyd Wed Dec 31 19:00:00 1969
+++ mudglk/floyd/startfloyd Thu Oct 28 08:50:58 1999
@@ -0,0 +1,6 @@
+#!/bin/bash
+ulimit -v 50960
+ulimit -t 32
+ulimit -u 80
+while true; do ./hose ifmud.port4000.com 4000 --in --err ./floyd; sleep 30; done
+
diff -r -u -N cheapglk/main.c mudglk/main.c
--- cheapglk/main.c Sat Nov 28 15:20:58 1998
+++ mudglk/main.c Thu Oct 28 08:43:47 1999
@@ -4,8 +4,8 @@
#include "cheapglk.h"
#include "glkstart.h"
-int screenwidth = 80;
-int screenheight = 24;
+int cg_screenwidth = 80;
+int cg_screenheight = 24;
static int inittime = FALSE;
@@ -123,7 +123,7 @@
if (val < 8)
errflag = 1;
else
- screenwidth = val;
+ cg_screenwidth = val;
break;
case 'h':
val = 0;
@@ -137,7 +137,7 @@
if (val < 2)
errflag = 1;
else
- screenheight = val;
+ cg_screenheight = val;
break;
default:
printf("%s: unknown option: %s\n", argv[0], argv[ix]);
diff -r -u -N cheapglk/mudglk.c mudglk/mudglk.c
--- cheapglk/mudglk.c Wed Dec 31 19:00:00 1969
+++ mudglk/mudglk.c Thu Oct 28 08:43:47 1999
@@ -0,0 +1,235 @@
+#include <stdio.h>
+#include <string.h>
+#include "mudglk.h"
+
+
+#define BUFSIZE 8000
+
+static unsigned char linebuffer[80];
+static int linelength;
+
+
+
+int wrap_length = 72;
+
+
+char line_start[80] = { ':', '|', ' ', '\0' };
+
+char circularbuffer[2048];
+int circularstart = 0;
+int circularend = 0;
+
+void circularwrite(char c)
+{
+ circularbuffer[circularend++] = c;
+ if(circularend == 2048)
+ circularend = 0;
+ if(circularstart == circularend) {
+
+ /* We should have a newline every 78 characters or so, so no infinite loops here */
+ do {
+ circularstart++;
+ if(circularstart == 2048)
+ circularstart = 0;
+ } while(circularbuffer[circularstart] != '\n');
+ }
+}
+
+void mudwritec(char c)
+{
+ fputc(c, stderr);
+ circularwrite(c);
+}
+
+
+void mudwrites(char *s)
+{
+ fputs(s, stderr);
+ while(*s)
+ circularwrite(*s++);
+}
+
+void mudwriteb(char *b, int len)
+{
+ int l;
+ fwrite(b, 1, len, stderr);
+ for(l = 0; l < len; l++)
+ circularwrite(b[l]);
+}
+
+void mud_flush(int length)
+{
+ if(linelength < length) {
+ fputs("\n:dances with a monkey to the moon [BUG]\n", stderr);
+ length = linelength;
+ }
+
+ mudwritec('\n');
+ mudwrites(line_start);
+ mudwriteb(linebuffer, length);
+
+ linelength -= length;
+
+ mudwritec('\n');
+}
+
+
+void parse_tag(char *tagname)
+{
+ static outstate = 0;
+
+ if(strncasecmp(tagname, "whisper ", 8) == 0)
+ outstate |= 1;
+ else if(strcasecmp(tagname, "/whisper") == 0)
+ outstate &= ~1;
+ else if(strcasecmp(tagname, "emote") == 0)
+ outstate |= 2;
+ else if(strcasecmp(tagname, "/emote") == 0)
+ outstate &= ~2;
+
+ if(linelength)
+ mud_flush(linelength);
+
+ switch(outstate) {
+ case 0:
+ wrap_length = 80 - 8; /* Floyd | ... */
+ strcpy(line_start, ":| ");
+ break;
+ case 1:
+ wrap_length = 80 - 18; /* Floyd whispers, "..." */
+ snprintf(line_start, 80, ".%s ", tagname + 8);
+ break;
+ case 2:
+ wrap_length = 80 - 6; /* Floyd ... */
+ strcpy(line_start, ": ");
+ break;
+ case 3:
+ wrap_length = 80 - 30; /* Floyd privately poses to you: ... */
+ snprintf(line_start, 80, ".%s :"); /* broken */
+ break;
+ }
+
+}
+
+
+void mud_putc(unsigned char ch)
+{
+ static unsigned char tagname[64];
+ static int taglength = -1;
+
+
+ static newline_count = 0;
+
+ if(ch == '\n') {
+ if(newline_count > 4)
+ return;
+ mud_flush(linelength);
+ newline_count++;
+ } else {
+ newline_count = 0;
+
+ if(taglength != -1) { /* Currently in a tag */
+ if(ch == '>' || taglength >= 63) {
+ tagname[taglength] = 0;
+ parse_tag(tagname);
+ taglength = -1;
+ }
+ else
+ tagname[taglength++] = ch;
+ } else { /* Not currently in a tag */
+ if(ch == '<')
+ taglength = 0;
+ else {
+ linebuffer[linelength++] = ch;
+ if(linelength >= wrap_length) {
+ int n;
+ for(n = linelength; n; n--)
+ if(linebuffer[n-1] == ' ')
+ break;
+ if(!n)
+ n = wrap_length;
+ mud_flush(n);
+ memmove(linebuffer, linebuffer + n, linelength);
+ }
+ }
+ }
+ }
+}
+
+
+void mud_write(unsigned char *buf, int length)
+{
+ int n;
+ for(n = 0; n < length; n++)
+ mud_putc(buf[n]);
+}
+
+void mud_say(char *buf)
+{
+ fputs("\n\"", stderr);
+ fputs(buf, stderr);
+ fputs("\n", stderr);
+}
+
+void mud_fgets(char *dest, int length)
+{
+ char *aftername, *message;
+ char buffer[BUFSIZE];
+
+ if(linelength)
+ mud_flush(linelength);
+
+ for(;;) {
+ if(!fgets(buffer, BUFSIZE, stdin))
+ _exit(1);
+ buffer[BUFSIZE] = 0;
+
+ aftername = strchr(buffer, ' ');
+ message = NULL;
+ if(aftername) {
+ *aftername = 0;
+ aftername++;
+ if(strncasecmp(aftername, "says (to floyd), \"", 18) == 0 ||
+ strncasecmp(aftername, "asks (to floyd), \"", 18) == 0)
+ message = aftername + 18;
+ else if(strncasecmp(aftername, "exclaims (to floyd), \"", 22) == 0)
+ message = aftername + 22;
+#ifdef MULTIPC
+ else if(strncasecmp(aftername, "whispers, \"", 11) == 0)
+ message = aftername + 11;
+#endif
+
+ if(message) {
+ char *endquote = strrchr(message, '\"');
+ if(!endquote)
+ endquote = strrchr(message, '\n');
+ if(!endquote)
+ continue;
+
+ *endquote = 0;
+
+ if(strcasecmp(message, "space") == 0)
+ strcpy(message, " space");
+
+ if(strcasecmp(message, "redisplay") == 0) {
+ int i;
+ for(i = circularstart; i != circularend; i == 2047 ? i = 0 : i++) {
+ fputc(circularbuffer[i], stderr);
+ }
+ mud_fgets(dest, length);
+ return;
+ }
+
+
+#ifdef MULTIPC
+ strncpy(dest, buffer, length - 2);
+ strcat(dest, ", ");
+ strncat(dest, message, length - strlen(dest));
+#else
+ strncpy(dest, message, length);
+#endif
+ return;
+ }
+ }
+ }
+}
diff -r -u -N cheapglk/mudglk.h mudglk/mudglk.h
--- cheapglk/mudglk.h Wed Dec 31 19:00:00 1969
+++ mudglk/mudglk.h Thu Oct 28 08:43:47 1999
@@ -0,0 +1,4 @@
+void mud_putc(unsigned char ch);
+void mud_write(unsigned char *buf, int length);
+void mud_say(char *buf);
+void mud_fgets(char *dest, int length);