Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 8/23/84; site ucbcad.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!decvax!ucbvax!ucbcad!faustus From: faustus@ucbcad.UUCP (Wayne A. Christopher) Newsgroups: net.sources.games Subject: Source for insult, flame, babble (Part 2 of 3) Message-ID: <233@ucbcad.UUCP> Date: Sat, 11-May-85 03:24:28 EDT Article-I.D.: ucbcad.233 Posted: Sat May 11 03:24:28 1985 Date-Received: Mon, 13-May-85 02:42:05 EDT References: <399@ho95b.UUCP> Organization: UC Berkeley CAD Group, Berkeley, CA Lines: 921 I am posting the source for a few programs I wrote some time ago to generate random insults, flames, and sentences. They are written using a pre-processor called "kafka", which is also included. To create them collect all the parts of this posting, pipe them to sh, then run "make". Wayne echo x - insult.k cat >insult.k <<'!Funky!Stuff!' %{ /* RCS Info: $Revision: $ on $Date: $ * $Source: $ * Copyright (c) 1985 Wayne A. Christopher * Permission is granted to do anything with this code except sell it * or remove this message. * * Insult -- a program to generate nasty insults. This is a kafka source file. * Compile with etc.c, output.c, and maketext.c */ #include #include #define CH(n, o) return (((rnum() % o) < n) ? 1 : 0) rnum() { return (random()); } char *ones; #define YOUR ones = "your" #define MY ones = "my" #define HIS ones = "his" /* Instead of defining all these words as rules, keep arrays of them. We * can also make the insults more interesting by using alliteration on * the words... */ char *words1[] = { /* Animals. */ "aardvark", "amphibian", "animal", "ant", "apteryx", "bird", "buzzard", "cat", "cockroach", "cow", "dodo", "dog", "duck", "emu", "fish", "flea", "frog", "gazelle", "gerbil", "goat", "goose", "grep", "haddock", "hippotomus", "hog", "horse", "insect", "jackal", "kitten", "kobold", "leech", "louse", "milkweed", "monkey", "moose", "mouse", "octopus", "penguin", "pig", "pigeon", "puppy", "racoon", "rat", "rust monster", "sheep", "skunk", "slime-mold", "slug", "snail", "snake", "squid", "toad", "tuna", "turkey", "turtle", "weed", "whale", "wombat", "worm", "yak", NULL } ; char *words2[] = { /* Derogatory terms. */ "airhead", "axe murderer", "beer", "bug-breath", "bum", "cookie", "creep", "cretin", "crud", "deviate", "dink", "dipstick", "dirt", "dork", "dude", "dumbbell", "fairy", "fleabag", "fruit", "garbage", "geek", "gimp", "glob", "gloop", "goober", "goof", "grunt", "gump", "hag", "idiot", "ignoramus", "inanimate object", "jerk", "lark's vomit", "lump", "lunkhead", "monster", "mudface", "mudpie", "muscle-brain", "nasty", "numskull", "nymphomaniac", "pervert", "pinhead", "plant", "plebe", "quiche-eater", "rat spit", "redneck", "scary dude", "scum that grows on the bottom of the lake", "scum", "septic tank", "slob", "super geek", "toady", "vegetable", "weight-lifter", "welfare mother", "wonderful, sensitive human being", NULL } ; char *words3[] = { /* Body parts. */ "behind", "brain", "crotch", "ear", "eye", "face", "liver", "nose", "pancreas", "private parts", "rectum", "stomach", NULL } ; char *words4[] = { /* Objects. */ "VAX", "baseball bat", "big thing", "boulder", "brick", "car", "heavy object", "knife", "manhole cover", "needle", "object", "rock", "sword", "terminal", "tree", "truck", "two by four", NULL } ; char *words5[] = { /* Adjectives. */ "Lovecraftian", "abnormal", "absurd", "awful", "bad", "bootlicking", "brainless", "cowardly", "crude", "dastardly", "dirty", "diseased", "disgusting", "disobedient", "dopey", "dumb", "elitist", "evil", "fat", "flabby", "foolish", "foul", "frightening", "funny", "furry", "green", "gruesome", "gumpy", "hairy", "hideous", "horrifying", "icky", "ignorant", "imaginary", "intolerable", "lousy", "ludicrous", "lumpy", "mangy", "muddy", "nauseating", "nauseating", "old", "pencil-necked", "perverted", "ratty", "religous", "ridiculous", "rotten", "scab-picking", "scummy", "sick", "silly", "skinny", "slimy", "slippery", "slobbering", "slow", "small", "smelly", "strange", "stupid", "trashy", "ugly", "undesirable", "unhappy", "unpleasant", "unspeakable", "unstructured", "uppity", "vile", "worthless", NULL } ; char *words6[] = { /* Adverbs. */ "disgustingly", "incredibly", "mega", "microscopically", "paradoxically", "phenomenally", "pseudo", "rather", "ridiculously", "semi", "slightly", "stupidly", "surprisingly", "terribly", "typically", "unbeliveably", NULL } ; char *words7[] = { /* Nasty things. */ "abuse", "annihilate", "avoid", "behead", "chop up", "damage", "destroy", "discriminate against", "disembowel", "dismember", "dissect", "eat", "flush", "forget about", "frighten", "hit", "ignore", "insult", "kick", "look at", "molest", "mush", "puree", "scramble", "shred", "spit on", "squish", "stab", "step on", NULL } ; char *words8[] = { /* Diseases. */ "bad breath", "gout", "leprosy", "malaria", "plague", NULL } ; char *lastchoice = NULL; getword(type) { char **wds; int i = 0, j = 0, k; int alliterate = lastchoice ? (random() % 4) : 0; switch (type) { case 1: wds = words1; break; case 2: wds = words2; break; case 3: wds = words3; break; case 4: wds = words4; break; case 5: wds = words5; break; case 6: wds = words6; break; case 7: wds = words7; break; case 8: wds = words8; break; default: fprintf(stderr, "Bad thing %d\n", type); } /* See how many words there are that we can use. */ for (k = 0; wds[k]; k++) { if (alliterate && (*wds[k] == *lastchoice)) j++; } i = k; if (j == 0) { hoho: i = rnum() % i; lastchoice = wds[i]; return ((int) wds[i]); } else { j = rnum() % j; for (k = 0; ; k++) if (*wds[k] == (isupper(*lastchoice) ? tolower(*lastchoice) : *lastchoice)) { if (wds[k] == lastchoice) goto hoho; if (j == 0) { lastchoice = wds[k]; return ((int) wds[k]); } else j--; } } } /* Word types. */ #define ANIMAL 1 #define DER_TERM 2 #define BODYPART 3 #define OBJECT 4 #define ADJ 5 #define ADVERB 6 #define NASTY_THING 7 #define DISEASE 8 %} %% = ; = you { CH(1, 20); } ; = { YOUR; CH(1, 20); } ; = "why you" , { YOUR; CH(1, 20); } ; = "you just make me" { YOUR; CH(1, 20); } ; = "you're a perfect example of a" { YOUR; CH(1, 20); } ; = "you make me want to" { YOUR; CH(1, 25); } ; = { MY; CH(1, 20); } ; = "you make me want to" { MY; CH(1, 30); } ; = "why don't you" { YOUR; CH(1, 25); } ; = "I'd like to" you { CH(1, 30); } ; = "you should" { YOUR; CH(1, 25); } ; = "I wish you'd" { YOUR; CH(1, 25); } ; = "why don't you" { YOUR; CH(1, 25); } ; = "you could make a" { HIS; CH(1, 40); } ; = go { YOUR; CH(1, 20); } ; = "do me a favor," ", and" { YOUR; CH(1, 35); } ; = "you resemble a" { CH(1,25); } ; = "make the world a better place and" { YOUR; CH(1,40); } ; = "why you" , { CH(1,30); } ; = "I used to know a" "just like you" { CH(1,40); } ; = { CH(1,25); } ; = "are you a" ", or just a" { CH(1, 40); } ; = ", you're a" { CH(1, 40); } ; = "you're just such a" { CH(1,20); } ; = "you should" yourself { CH(1,35); } ; = "you're so" { CH(1,20); } ; = "oh, go" { YOUR; CH(1,20) ; } ; = hey, "Yeah, you!" { CH(1,20) ; } ; = get { CH(1, 20); } ; = "you look like you would" { YOUR; CH(1, 20); } ; = "you look like you would" { MY; CH(1, 20); } ; = "what a" "you are" { CH(1, 20); } ; = "you must really be a" { CH(1, 20); } ; = "even a" "would want you to" { HIS; CH(1, 20); } ; = "you're even more" "than a" { CH(1, 20); } ; = "if I were you I'd" { MY; CH(1, 30); } ; = "oh, I get it, you're a" { CH(1, 30); } ; = "why don't you just" "and get it over with" { YOUR; CH(1, 20); } ; = "you look like a" { CH(1, 20); } ; = "I don't know about you" { CH(1, 20); } ; = "hey," "," { YOUR; CH(1, 20); } ; = "whenever I" "it gives me" { YOUR; CH(1, 20); } ; = "I wonder why" { CH(1, 20); } ; = "you make me want to become" ", you know" { CH(1, 20); } ; = "," { CH(1, 20); } ; = "if only you were a" { CH(1, 20); } ; = ; = ; = { CH(1, 3); } ; = ; = { return (getword(ANIMAL)); } ; = { CH(1, 3); } ; = ; = { CH(1, 4) ; } ; = "#'s " { CH(1, 10); } ; = "#ness" { CH(1, 10) ; } ; = squad { CH(1, 25) ; } ; = "son of a" { CH(1, 25) ; } ; = { CH(1, 25) ; } ; = "#y" { CH(1, 25) ; } ; = { CH(1, 25) ; } ; = "#ness" { CH(1, 25) ; } ; = ; = { return (getword(DER_TERM)); } ; = { CH(1, 10) ; } ; = ; = { return (getword(BODYPART)); } ; = { CH(1, 5); } ; = "pile of" "#s" { CH(1, 15); } ; = "bunch of" "#s" { CH(1, 15); } ; = ; = { return (getword(OBJECT)); } ; = { CH(1, 10); } ; = { CH(1, 10) ; } ; = ; = "#-infested" { CH(1, 40) ; } ; = "#ish" { CH(1, 40) ; } ; = "#-loving" { CH(1, 40) ; } ; = "#-eating" { CH(1, 40) ; } ; = "#like" { CH(1, 40) ; } ; = "#-infested" { CH(1, 40) ; } ; = "#ed" { CH(1, 40) ; } ; = ; = { return (getword(ADJ)); } ; = "#ly" { CH(1, 50) ; } ; = ; = { return (getword(ADVERB)); } ; = ; = { return (getword(NASTY_THING)); } ; = { return (getword(DISEASE)); } ; = { CH(2, 3); } ; = ; = eat a { CH(1, 30) ; } ; = lick a { CH(1, 30) ; } ; = lick a "#'s" { CH(1, 30) ; } ; = a "#'s" { CH(1, 30) ; } ; = "have sex with a" { CH(1, 30) ; } ; = die { CH(1, 30) ; } ; = become a { CH(1, 30) ; } ; = { CH(1, 30) ; } ; = "go out and meet a nice" { CH(1, 30) ; } ; = "adopt a" { CH(1, 30) ; } ; = become { CH(1, 30) ; } ; = vomit { CH(1, 30) ; } ; = "gag on a" { CH(1, 30) ; } ; = stick a in { CH(1, 30) ; } ; = stick a up { CH(1, 30) ; } ; = "cut off" { CH(1, 30) ; } ; = "make somebody happy and" { CH(1, 30); } ; = "live with a" { CH(1, 30) ; } ; = put a in { CH(1, 30) ; } ; = die { CH(1, 30) ; } ; = "admit that you're" { CH(1, 30) ; } ; = "blow up" house { CH(1, 30) ; } ; = remove files { CH(1, 30) ; } ; = "sleep on the freeway" { CH(1, 30) ; } ; = take "lessons from a" { CH(1, 30) ; } ; = "realize how" "you are" { CH(1, 30) ; } ; = relocate { CH(1, 30) ; } ; = "crawl under a" { CH(1, 30) ; } ; = pick { CH(1, 30) ; } ; = "go blind" { CH(1, 30) ; } ; = make { CH(1, 30) ; } ; = "go away" { CH(1, 30) ; } ; = "get a" to { CH(1, 30) ; } ; = get { CH(1, 30) ; } ; = "make a" get { CH(1, 30) ; } ; = stick "in a" { CH(1, 30) ; } ; = and { CH(1, 10); } ; = ; = "oh god" { CH(1, 10); } ; = "wow, man" { CH(1, 10); } ; = goodness { CH(1, 10); } ; = "ah say" { CH(1, 10); } ; = "ain't it the truth" { CH(1, 10); } ; = "#s" { CH(1, 10); } ; = gosh { CH(1, 10); } ; = "land 'o goshens" { CH(1, 10); } ; = well, { CH(1, 10); } ; = "lemme tell ya" { CH(1, 10); } ; = "sure as day" { CH(1, 10); } ; = shoot { CH(1, 10); } ; = sheeeit { CH(1, 10); } ; = "hot puppies" { CH(1, 10); } ; = well, { CH(1, 10); } ; = ; = . { lastchoice = NULL; return (1); } ; = ! { lastchoice = NULL; return (1); } ; = ? { lastchoice = NULL; return (1); } ; = { return ((int) ones); } ; !Funky!Stuff! echo x - defs.h cat >defs.h <<'!Funky!Stuff!' /* RCS Info: $Revision: $ on $Date: $ * $Source: $ * Copyright (c) 1985 Wayne A. Christopher * Permission is granted to do anything with this code except sell it * or remove this message. */ #define STACKSIZE 1024 #define HASHSIZE 256 /* Stack elements for the generator machine. */ struct kkelt { struct kknode *ke_node; struct kcarc *ke_arc; }; !Funky!Stuff! echo x - graph.h cat >graph.h <<'!Funky!Stuff!' /* RCS Info: $Revision: $ on $Date: $ * $Source: $ * Copyright (c) 1985 Wayne A. Christopher * Permission is granted to do anything with this code except sell it * or remove this message. * * Definitions for the nodes of directed graphs used by * kafka. A set of rules for a given non-term is represented * as a list of rule definitions. A rule definition is * represented as a list of arcs to other non-terminals or * arcs containing terminal strings, or in the case of * computed terminals, a pointer to a function that returns * a pointer to the computed terminal (note that the function should * cast the pointer to an int before returning it if it doesn't * want complains from the compiler) . * Rules are tried in turn until the kn_func of one suceeds, * in which case either the rule is used or the value of the * kn_func is used as the terminal value, if the node being left * is of type KTCOMP. It is an error for none of the kn_funcs * to succeed. Note that knode is the first form of the graph * nodes, used when the specification is being parsed, and * kknode is the final form used in the actual program generated * (likewise for karc and kcarc) . */ #define SSIZE 100 /* Max size of terminals and nonterms. */ struct knode { int kn_type; /* See below. */ char kn_nodename[SSIZE];/* Terminal or non-term. */ struct karc *kn_arc; /* Pointer to list of arcs. */ struct knode *kn_next; /* Next rule for this non-term. */ struct knode *kn_nnt; /* Next non-term. */ int kn_fnum; /* The id number of the function. 0 if none. */ int kn_nodenumber; /* The (unique) id number of this node. */ }; /* This isn't too hot, but we are lazy... */ struct kknode { int kk_type; /* See below. */ char *kk_nodename; /* Terminal or non-term. */ struct kcarc *kk_arc; /* Pointer to list of arcs. */ struct kknode *kk_next; /* Next rule for this non-term. */ int (*kk_func)(); /* Pointer to associated function. */ struct kknode *kk_link; /* Overall node list. */ }; struct karc { struct karc *ka_narc; /* Link. */ struct knode *ka_to; /* Thing pointed to. */ char ka_toname[SSIZE]; /* Name of node pointed to. */ int ka_type; /* Type of thing pointed to. */ int ka_arcnumber; /* The unique id of this arc. */ }; struct kcarc { char *kc_toname; /* Only terminal names. */ struct kknode *kc_to; /* Node pointed to. */ struct kcarc *kc_narc; /* Link. */ }; #define KTTERM 1 /* kn_arc and kn_next will be NULL. */ #define KTNTERM 2 /* Non-terminal. */ #define KTCOMP 3 /* Computed terminal. kn_arc->ka_func will * be used to decide what the value of the * terminal will be. */ !Funky!Stuff! echo x - kafgraf.h cat >kafgraf.h <<'!Funky!Stuff!' /* RCS Info: $Revision: $ on $Date: $ * $Source: $ * Copyright (c) 1985 Wayne A. Christopher * Permission is granted to do anything with this code except sell it * or remove this message. * * Definitions for the nodes of directed graphs used by * kafka. A set of rules for a given non-term is represented * as a list of rule definitions. A rule definition is * represented as a list of arcs to other non-terminals or * arcs containing terminal strings, or in the case of * computed terminals, a pointer to a function that returns * a pointer to the computed terminal (note that the function should * cast the pointer to an int before returning it if it doesn't * want complains from the compiler) . * Rules are tried in turn until the kn_func of one suceeds, * in which case either the rule is used or the value of the * kn_func is used as the terminal value, if the node being left * is of type KTCOMP. It is an error for none of the kn_funcs * to succeed. Note that knode is the first form of the graph * nodes, used when the specification is being parsed, and * kknode is the final form used in the actual program generated * (likewise for karc and kcarc) . */ #define SSIZE 100 /* Max size of terminals and nonterms. */ struct knode { int kn_type; /* See below. */ char kn_nodename[SSIZE];/* Terminal or non-term. */ struct karc *kn_arc; /* Pointer to list of arcs. */ struct knode *kn_next; /* Next rule for this non-term. */ struct knode *kn_nnt; /* Next non-term. */ int kn_fnum; /* The id number of the function. 0 if none. */ int kn_nodenumber; /* The (unique) id number of this node. */ }; struct kknode { int kk_type; /* See below. */ char *kk_nodename; /* Terminal or non-term. */ struct kcarc *kk_arc; /* Pointer to list of arcs. */ struct kknode *kk_next; /* Next rule for this non-term. */ int (*kk_func)(); /* Pointer to associated function. */ struct kknode *kk_link; /* Overall node list. */ }; struct karc { struct karc *ka_narc; /* Link. */ struct knode *ka_to; /* Thing pointed to. */ char ka_toname[SSIZE]; /* Name of node pointed to. */ int ka_type; /* Type of thing pointed to. */ int ka_arcnumber; /* The unique id of this arc. */ }; struct kcarc { char *kc_toname; /* Only terminal names. */ struct kknode *kc_to; /* Node pointed to. */ struct kcarc *kc_narc; /* Link. */ }; #define KTTERM 1 /* kn_arc and kn_next will be NULL. */ #define KTNTERM 2 /* Non-terminal. */ #define KTCOMP 3 /* Computed terminal. kn_arc->ka_func will * be used to decide what the value of the * terminal will be. */ !Funky!Stuff! echo x - dstrans.c cat >dstrans.c <<'!Funky!Stuff!' /* RCS Info: $Revision: $ on $Date: $ * $Source: $ * Copyright (c) 1985 Wayne A. Christopher * Permission is granted to do anything with this code except sell it * or remove this message. * This routine takes the data structures which have been created by the * parser and creates a file called "kaf.spec.c", with all the appropriate * source in it. Each node in the structure is given a unique name, and * all links between these are made explicit here. Also all nodes are * linked together in a list, for the purpose of searching for names. */ #include "kafgraf.h" #include "defs.h" #include extern struct knode *hashtab[]; extern FILE *specp; /* The file to output to. */ int errp = 0; dstrans() { struct knode *nt, *wk, *lf; struct karc *tarc; int a; char *it; /* Temp char *. */ unsigned char b, phash(); /* For lookup of node names. */ char lastnode[32]; /* dumpdata(); Diagnostic. */ /* First we have to resolve all references to nodes. Match * ka_toname with the apropriate lists of nodes. */ for (a = 0; a < HASHSIZE; a++) { for (nt = hashtab[a]; nt != NULL; nt = nt->kn_nnt) { for (wk = nt; wk != NULL; wk = wk->kn_next) { for (tarc = wk->kn_arc; tarc != NULL; tarc = tarc->ka_narc) { if (tarc->ka_type != KTNTERM) tarc->ka_to = NULL; else { it = tarc->ka_toname; b = phash(it); lf = NULL; for (lf = hashtab[b]; lf != NULL; lf = lf->kn_nnt) if (!strcmp(it, lf->kn_nodename)) { tarc->ka_to = lf; break; } if (lf == NULL) { fprintf(stderr, "Error: no such node: %s\n", it); errp = 1; } } } } } } if (errp) { fprintf(stderr, "kafka aborted due to errors\n"); exit(1); } /* All references are cool now. The working data structure is now * to be built, with the difference that there is no hashing involved * as everything is held together by the arcs. */ strcpy(lastnode, "0"); for (a = 0; a < HASHSIZE; a++) { for (nt = hashtab[a]; nt != NULL; nt = nt->kn_nnt) { for (wk = nt; wk != NULL; wk = wk->kn_next) { /* Write this node out. This is ugly... */ if (wk->kn_arc) fprintf(specp, "extern struct kcarc _kka%d;\n", wk->kn_arc->ka_arcnumber); if (wk->kn_next) fprintf(specp, "extern struct kknode _kkn%d;\n", wk->kn_next->kn_nodenumber); if (wk->kn_fnum) fprintf(specp, "extern int _kkFunc%d();\n", wk->kn_fnum); fprintf(specp, "struct kknode _kkn%d = { ", wk->kn_nodenumber); fprintf(specp, "%d, ", wk->kn_type); if (wk->kn_nodename) fprintf(specp, "\"%s\", ", wk->kn_nodename); else fprintf(specp, "0, "); if (wk->kn_arc) fprintf(specp, "&_kka%d, ", wk->kn_arc->ka_arcnumber); else fprintf(specp, "0, "); if (wk->kn_next) fprintf(specp, "&_kkn%d, ", wk->kn_next->kn_nodenumber); else fprintf(specp, "0, "); if (wk->kn_fnum) fprintf(specp, "_kkFunc%d, ", wk->kn_fnum); else fprintf(specp, "0, "); fprintf(specp, "%s };\n", lastnode); sprintf(lastnode, "&_kkn%d", wk->kn_nodenumber); if (wk->kn_arc) { for (tarc = wk->kn_arc; tarc != NULL; tarc = tarc->ka_narc) { if (tarc->ka_to) fprintf(specp, "extern struct kknode _kkn%d;\n", tarc->ka_to->kn_nodenumber); if (tarc->ka_narc) fprintf(specp, "extern struct kcarc _kka%d;\n", tarc->ka_narc->ka_arcnumber); fprintf(specp, "struct kcarc _kka%d = { ", tarc->ka_arcnumber); fprintf(specp, "\"%s\", ", tarc->ka_toname); if (tarc->ka_type == KTNTERM) fprintf(specp, "&_kkn%d, ", tarc->ka_to->kn_nodenumber); else fprintf(specp, "0, "); if (tarc->ka_narc) fprintf(specp, "&_kka%d };\n", tarc->ka_narc->ka_arcnumber); else /* Oops { */ fprintf(specp, "0 };\n"); } } } } } fprintf(specp, "struct kknode *nodelist = %s;\n\n", lastnode); /* All the necessary information for the structure is now in place. */ } /* Diagnostic routine. */ dumpdata() { int hpos; struct knode *nont, *rule; struct karc *arc; for (hpos = 0; hpos < HASHSIZE; hpos++) { printf("Hashtab entry %d:\n", hpos); if (hashtab[hpos] == NULL) printf("\t(empty)\n"); else for (nont = hashtab[hpos]; nont != NULL; nont = nont->kn_nnt) { printf("\tNonterminal: %s\n", nont->kn_nodename); for (rule = nont; rule != NULL; rule = rule->kn_next) { printf("Rule: "); for (arc = rule->kn_arc; arc != NULL; arc = arc->ka_narc) printf("%s ", arc->ka_toname); putchar('\n'); } } } } !Funky!Stuff!