From: morpheus@sage.cc.purdue.edu (Morpheus Nosferatu)
Subject: More Words in the Ancient Tongue of R'lyeh (2nd attempt)
Keywords: Cthulhu, R'lyeh, Great Old Ones, Lovecraft
Organization: Netherworld Dreamscape
Date: Thu, 5 Nov 1992 20:43:04 GMT


Following up on whoever posted the r'lyeh word generator, I had the
inspiration to hack out a quick program that takes a text file and
translates it into R'lyeh and back again.  I just hacked it out, so
I make no guarantees that there are no bugs in it (and obviously it
is not commented, sorry (but Real Programmers _never_ comment code)).

compile the program, and invoke it with the name of a file, and it
will output the R'lyeh translation to the screen.  If the output is
redirected into a file, the program can be invoked with the -x flag
and the name of the R'lyeh-text program and will then translate it
back into plain English (or whatever language you started with).

Note that he program uses some of the code from the other fellow's
program (sorry, I seem to have lost the name of who is was) and
generates new words on the fly, only occasionally asking you if a
given word is actually a name (since it does not translate names).
The given english (or whatever) words are saved into a file with
their associated R'lyeh words the program generates.

Granted, this is just a novelty, but it's still interesting (to me
at least), and it was an excuse to avoid doing anything related to
class-work.

Now if only I had some more "authentic" R'lyeh words to add to the
list in this program to make the generated R'lyeh-text more
"authentic" as well.

=====================================================================


#include <ctype.h>
#include <time.h>
#include <stdio.h>

struct wordnode {
    char *norm, *cthul;
    struct wordnode *nleft, *nright, *cleft, *cright;
};

typedef struct wordnode NODE;

NODE *wordtree;
char fname[100];
int  xtract;

#define TOT 6+10+11+6+6+8+5+8

char            symb[TOT][3] = {
    "a", "z", "a", "th", "o", "th",
    "sh", "u", "b", "n", "i", "gg", "u", "r", "a", "th",
    "n", "y", "a", "r", "l", "a", "th", "o", "t", "e", "p",
    "c", "th", "u", "l", "h", "u",
    "h", "a", "s", "t", "u", "r",
    "y", "o", "g", "s", "o", "th", "o", "th",
    "y", "u", "gg", "o", "th",
    "t", "s", "a", "th", "o", "gg", "u", "a"
};


int randint(b)
int b;
{
    return (rand() % b);
}


new_word(word)
char word[];
{
    int  i, ncons, ct;
    char *s;

    word[0] = '\0';
    ct = randint(3) + randint(3) + randint(3) + 3;
    ncons = 0;

    for (i = randint(5) + 6; i >= 1; i--) {
	do {
	    s = symb[randint(TOT)];
	} while ((ncons == 2) &&
		s[0] != 'a' &&
		s[0] != 'e' &&
		s[0] != 'i' &&
		s[0] != 'o' &&
		s[0] != 'u');

	if (s[0] != 'a' &&
		s[0] != 'e' &&
		s[0] != 'i' &&
		s[0] != 'o' &&
		s[0] != 'u')
	    ncons++;
	else
	    ncons = 0;

	strcat(word, s);
    }
}


new_node(ptr, s1, s2)
NODE **ptr;
char *s1, *s2;
{
    NODE *temp;

    temp = (NODE*)malloc(sizeof(NODE));
    string_assign(&(temp->norm), s1);
    string_assign(&(temp->cthul), s2);
    temp->nleft = NULL;
    temp->nright = NULL;
    temp->cleft = NULL;
    temp->cright = NULL;
    *ptr = temp;
}


add_node(new)
NODE *new;
{
    NODE *ptr;

	/* if no words in tree then create a new tree */
    if (wordtree == NULL) {
	wordtree = new;
	return;
    }

	/* insert into binary tree for normal search */
    ptr = wordtree;
    while (ptr != NULL) {
	if (strcmp(ptr->norm,new->norm) < 0) {
	    if (ptr->nleft != NULL)
		ptr = ptr->nleft;
	    else {
		ptr->nleft = new;
		ptr = NULL;
	    }
	}
	else {
	    if (ptr->nright != NULL)
		ptr = ptr->nright;
	    else {
		ptr->nright = new;
		ptr = NULL;
	    }
	}
    }

	/* insert into binary tree for cthulhu search */
    ptr = wordtree;
    while (ptr != NULL) {
	if (strcmp(ptr->cthul,new->cthul) < 0) {
	    if (ptr->cleft != NULL)
		ptr = ptr->cleft;
	    else {
		ptr->cleft = new;
		ptr = NULL;
	    }
	}
	else {
	    if (ptr->cright != NULL)
		ptr = ptr->cright;
	    else {
		ptr->cright = new;
		ptr = NULL;
	    }
	}
    }
}


string_assign(ptr, strg)
char **ptr, strg[];
{
    *ptr = (char*)malloc(strlen(strg) + 1);
    strcpy(*ptr, strg);
}


read_words()
{
    char inline[100], *sp;
    FILE *fopen(), *cthulfile;
    int  i;
    NODE *new;

    cthulfile = fopen("rlyehtxt", "r");
    if (cthulfile == NULL) {
	printf(
	"Error: Unable to open file \"rlyehtxt\"; starting with no words.\n");
	return;
    }

    while (fgets(inline, 100, cthulfile)) {
	for (i = 0; i < 100; ++i)
	    if (inline[i] == '\n')
		inline[i] = '\0';
	i = 0;
	while ((i < 100) && (inline[i] != ' '))
	   ++i;

	inline[i] = '\0';
	sp = inline + i + 1;

	if (wordtree == NULL)
	    new_node(&wordtree, inline, sp);
	else {
	    new_node(&new, inline, sp);
	    add_node(new);
	}
    }

    fclose(cthulfile);
}


writer(ptr, outfile)
NODE *ptr;
FILE *outfile;
{
    if (ptr == NULL)
	return;
    fprintf(outfile, "%s %s\n", ptr->norm, ptr->cthul);
    writer(ptr->nleft, outfile);
    writer(ptr->nright, outfile);
}


write_words()
{
    FILE *fopen(), *outfile;

    outfile = fopen("rlyehtxt", "w");
    if (outfile == NULL) {
	printf("Error: Unable to open file \"rlyehtxt\" for output.\n");
	exit(1);
    }

    writer(wordtree, outfile);
    fclose(outfile);
}


int find_normal(strg, word)
char strg[], word[];
{
    int  i;
    NODE *ptr;

    ptr = wordtree;
    while (ptr != NULL) {
	i = strcmp(ptr->cthul, strg);
	if (!i) {
	    strcpy(word, ptr->norm);
	    return 1;
	}
	else if (i < 0)
	    ptr = ptr->cleft;
	else
	    ptr = ptr->cright;
    }
    return 0;
}


int find_cthulhu(strg, word)
char strg[], word[];
{
    int  i;
    NODE *ptr;

    ptr = wordtree;
    while (ptr != NULL) {
	i = strcmp(ptr->norm, strg);
	if (!i) {
	    strcpy(word, ptr->cthul);
	    return 1;
	}
	else if (i < 0)
	    ptr = ptr->nleft;
	else
	    ptr = ptr->nright;
    }
    return 0;
}


int count_upper(strg)
char strg[];
{
    int i, c = 0;

    for (i = strlen(strg) - 1; i >= 0; --i)
	if (isupper(strg[i]))
	    ++c;

    return c;
}


string_to_lower(strg)
char strg[];
{
    int i;

    for (i = strlen(strg) - 1; i >= 0; --i)
	if (isupper(strg[i]))
	    strg[i] = tolower(strg[i]);
}


main(argc, argv)
int  argc;
char *argv[];
{
    char word[100], strg[100];
    FILE *fopen(), *infile;
    int  c, sc = 0, capflag = 0;
    NODE *ptr;

    wordtree = NULL;
    read_words();
    srand((int)time(0));

    if (argc == 2) {
	if (!strcmp(argv[1], "-x")) {
	    printf("filename required\n");
	    exit(1);
	}
	strcpy(fname, argv[1]);
	xtract = 0;
    }
    else if (argc == 3) {
	if (strcmp(argv[1], "-x")) {
	    printf("Usage: %s [-x] filename\n", argv[0]);
	    exit(1);
	}
	strcpy(fname, argv[2]);
	xtract = 1;
    }
    else {
	printf("Usage: %s [-x] filename\n", argv[0]);
	exit(1);
    }

    infile = fopen(fname, "r");
    if (infile == NULL) {
	printf("Unable to open file \"%s\"\n", fname);
	exit(1);
    }

    while ((c = getc(infile)) != EOF) {
	if (isalpha(c) || (c =='\'')) {
	    strg[sc++] = c;
	    strg[sc] = '\0';
	}
	else {
	    if (strlen(strg)) {
		if ((count_upper(strg) == 1) && (isupper(strg[0]))) {
		    capflag = 1;
		    string_to_lower(strg);
		}

		if (xtract) {
		    if (find_normal(strg, word)) {
			if (capflag)
			    word[0] = toupper(word[0]);
			printf(word);
		    }
		    else
			printf(strg);
		}
		else {
		    if (find_cthulhu(strg, word)) {
			if (capflag)
			    word[0] = toupper(word[0]);
			printf(word);
		    }
		    else {
			if (capflag) {
			    printf("\nIs \"%s\" a name? ", strg);
			    gets(word);
			    if ((word[0] == 'y') || (word[0] == 'Y'))
				new_node(&ptr, strg, strg);
			    else {
				new_word(word);
				new_node(&ptr, strg, word);
			    }
			    add_node(ptr);
			    strcpy(word, ptr->cthul);
			    word[0] = toupper(word[0]);
			    printf(word);
			}
			else {
			    new_word(word);
			    new_node(&ptr, strg, word);
			    add_node(ptr);
			    printf(word);
			}
		    }
		}
	    }
	    capflag = 0;
	    sc = 0;
	    strg[0] = '\0';
	    putchar(c);
	}
    }

    fclose(infile);
    write_words();
}