talmage@excalibur.UUCP (Talmage) (01/20/87)
Here's a VMS version of good@pixar's ncode toy. I bundled it with Marvin Minow's (minow@decvax) archc program. Cut along the dashed line and use either MM's archx or your fave editor to unbundle it. Enclosed is a bug report, source code, some sample input files (blame me for abuse.ncode), the original man page and news headers. I didn't change the man page to reflect the changes I've made and bugs I've introduced. David Talmage UUCP: seismo!cmbvax \ ihnp4!--< >!vu-vlsi!excalibur!talmage cbosgd!psuvax1/ Bitnet: TALMAGE@VILLVM, TALMAGE@VUVAXCOM Arpa: TALMAGE%villvm.bitnet@wiscvm.wisc.edu -------------------- Cut here ---------------------------------------------- -h- bugs Tue Jan 20 11:02:55 1987 bugs In <401.pixar.UUCP>, good@pixar gives us a nifty toy called "ncode". I've recently hacked at it so it runs on VAXen under VMS 4.2. We have version 2.2 of the VAX/VMS C compiler. I don't know if ncode.c will compile with any earlier versions. There are some differences between the VMS version and the UNIX version. As you may know, VMS is uses a record-oriented file system, rather than a stream-oriented one like UNIX. If you look in init(), you'll see that the UNIX code eats input files in one big gulp, while the VMS code takes smaller bites. Good@pixar sent me a change to allow you to put \'s in your output. Just preceed them with a |. E.g. printf("foo|\n"); in your input should come out as printf("foo\n"); When I was testing this puppy, I wasn't sure it was reading the groups correctly, so I introduced another command-line option to help confirm or deny my suspicions. ncode -d codefile prints the groups and their contents before giving you the usual ncode output. There are some bugs in my version. I don't know if they exist in the original version or not. 1. It doesn't ignore blank lines. They become part of a group. 2. It treats multiple %'s as names of groups. E.g. : : % #include ncode.sample2 % CODE : : % introduces a group called "%" if the file ncode.sample2 ends in a %. 3. The VAX/VMS linker spewls forth the following complaint. I quote: %LINK-W-MULPSC, conflicting attributes for psect DATA in module SHELL$FIX_TIME file SYS$COMMON:[SYSLIB]VAXCRTL.OLB;1 %LINK-W-OVRALI, conflicting alignment on overlayed psect DATA in module SHELL$FIX_TIME file SYS$COMMON:[SYSLIB]VAXCRTL.OLB;1 My system manager says it's DEC's fault, not mine. -h- ncode.txt Tue Jan 20 11:02:55 1987 ncode.txt From good@pixar.UUCP (Pixar -- Out of our minds, into your hands.) Mon Dec 22 21:58:41 1986 Relay-Version: version B 2.10.2 9/5/84; site excalibur.UUCP Path: excalibur!vu-vlsi!cbmvax!bpa!burdvax!sdcrdcf!hplabs!ucbvax!ucsfcgl!pixar!good From: good@pixar.UUCP (Pixar -- Out of our minds, into your hands.) Newsgroups: net.sources Subject: ncode -- source, man page and sample input files Message-ID: <401@pixar.UUCP> Date: 23 Dec 86 02:58:41 GMT Article-I.D.: pixar.401 Posted: Mon Dec 22 21:58:41 1986 Date-Received: 24 Dec 86 23:04:03 GMT Reply-To: good@pixar.UUCP (Pixar -- Out of our minds, into your hands.) Organization: Pixar -- Marin County, California Lines: 900 Distribution: net Xref: excalibur net.sources:16 Here it is: the new, improved ncode.c along with new, improved sample files which help you appreciate all the wonderful features of the program. To unwrap your kit, save it in a file called "ncode.shar". To assemble your kit, delete everything in the file above (and including) this "cut here" line, and delete everything below (and including) the other "cut here" line near the bottom of the file. Then give the command sh ncode.shar and start by reading the README file. Cheers. ------------------------------- cut here -------------------------------- ------------------------------- cut here -------------------------------- (delete from here down) ---- --Craig ...{ucbvax,sun}!pixar!good -h- ncode.c Tue Jan 20 11:02:55 1987 ncode.c /* * ncode.c -- a random text constructor * pixar!good * based on a program by pixar!mark */ #include <stdio.h> #include <sys/file.h> #ifndef VMS /* DWT 9 January, 1987 */ #include <sys/time.h> #define OK_FINE 0 /* DWT */ #define UNWELL 1 /* DWT */ #endif #include <sys/types.h> #include <sys/stat.h> #ifdef VMS #define random rand /* DWT 9 January, 1987. Won't run under VMS */ #define srandom srand /* without these changes. The author says these*/ /* are also needed under SYSV. */ #define rindex strrchr /* Also need this. */ #define OK_FINE 1 /* Termination with bit 1 set is normal for */ #define UNWELL 1 /* VMS. */ #include <timeb.h> #endif #define DATALUMP 8192 /* increment size of data[] by this as needed */ #define BIGBUF 4096 /* nice, roomy buffer for group name checks */ char **data; /* array of pointers to elements in bucket */ int dindex; /* number of elements in data */ int datasize; /* how many elements would fit in data[] is right now */ char *malloc(); char *realloc(); char *rindex(); char *fgets(); long random(); struct gstruct { char *name; /* points to name of a group in data[] */ int count; /* how many elements of data belong to this group */ int index; /* index of element of data where group starts */ }; struct gstruct *groups; /* where the group structs live, or is that obvious? */ int ngroups; /* number of elements in groups */ main (ac,av) int ac; char *av[]; { char *prog; /* name of this program */ char *fname = 0; int loopcnt = 1; /* times through main loop */ char *groupname = "CODE"; int debug = 0; /* DWT- Defaults to */ /* "Don't print the group tables." */ prog = rindex(*av,'/'); prog = ( prog == NULL ) ? *av : ++prog ; ac--;av++; while(ac && **av == '-'){ if (strcmp(*av,"-n") == 0){ ac--;av++; loopcnt = atoi(*av); if (loopcnt <= 0){ fprintf(stderr, "%s: -n: need positive integer\n",prog); exit(UNWELL); } ac--;av++; } else if (strcmp(*av,"-g") == 0){ ac--;av++; groupname = *av; /* use instead of "CODE" */ if (! groupname ){ fprintf(stderr, "%s: -g: need group name\n",prog); exit(UNWELL); } ac--;av++; } else if (strcmp(*av,"-d") == 0){ debug = 1; ac--;av++; } else { printf( "Usage %s [-n n ] [-g groupname] [-d] codefile\n",prog); exit(OK_FINE); } } if (!ac){ fprintf(stderr, "Usage %s [-n n ] [-g groupname] [-d] codefile\n",prog); exit(UNWELL); } fname = *av; /* * Make some room to start, and increment by DATALUMP as needed */ datasize = DATALUMP; if ((data = (char **) malloc(datasize * sizeof(char *))) == NULL ){ perror("main: could not malloc for data[]"); exit(UNWELL); } dindex = 0; if( init(fname) != 0 ){ fprintf(stderr,"%s: init error\n",prog); exit(UNWELL); } /* * This should be more than enough room for worst-case */ groups = (struct gstruct *) malloc(dindex * sizeof(struct gstruct)); if (groups == NULL){ perror("main: could not malloc for groups[]"); exit(UNWELL); } if ( scan() != 0 ){ fprintf(stderr,"%s: scan error\n",prog); exit(UNWELL); } if (debug) /* DWT 9 January, 1987 */ printgroups(); srandom(a_random_number()); /* seed the number generator */ while ( loopcnt ){ expand(groupname,strlen(groupname)); loopcnt--; } exit(OK_FINE); } init(fname) char *fname; { char *bucket; /* big array where data lives */ char *bptr; /* points into bucket */ int fd; struct stat sbuf; char *s, *t; int n_read; /* DWT How many bytes have we read from fname? */ #ifdef VMS int bytecount; /* DWT Number of bytes read so far */ #endif fd = open(fname,O_RDONLY,0); if ( fd < 0 ) { perror(fname); return 1; } if ( fstat(fd,&sbuf) != 0 ){ perror(fname); return 1; } if ((bucket = (char *) malloc( sbuf.st_size + 1)) == NULL ){ perror("init(): malloc() trouble"); return 1; } /* * Read entire file into bucket[] */ #ifndef VMS if ((read(fd,bucket,sbuf.st_size)) != sbuf.st_size){ perror("init: read error"); return 1; } n_read = sbuf.st_size; #else /* DWT- gots to do this for VMS. Most files under VMS aren't stream */ /* as read and its relatives expect, so for each call to read we get */ /* however many characters up to the next end of record marker. This*/ /* little loop lets us read the entire file into the buffer in some */ /* number of passes. */ n_read = 0; bytecount = 0; while ( (n_read = read(fd, bucket+bytecount, sbuf.st_size ) ) != 0 ) bytecount = bytecount + n_read; n_read = bytecount; #endif close(fd); /* * Make first pass through memory, pointing data[] the right way * and recursing as needed on #include files. */ bptr = bucket; /* while ( *bptr && (bptr <= bucket + sbuf.st_size) ){ */ /* DWT */ while ( *bptr && (bptr <= bucket + n_read) ){ s = bptr; while ( *s != '\0' ){ if(*s == '\n' ) *s = '\0'; /* nuke newline */ else s++; } if( strncmp(bptr, "#include", 8) == 0 ){ for(t = bptr + 8; *t!='\0' && (*t==' '||*t=='\t');t++) ; /* skipping white space */ if (init(t) != 0){ /* RECURSES HERE */ return 1; } bptr = t +strlen(t) + 1; /* skip the #include line */ continue; /* back to the top of the while loop */ } /* * Make sure data[] is still big enough */ if ( dindex >= datasize){ datasize += DATALUMP; if((data=(char **) realloc(data, datasize*sizeof(char *)))==NULL){ perror("init: could not realloc for data[]"); return(1); } } data[dindex] = bptr; /* point it at the data */ bptr = s + 1; /* move bptr to the next location to fill */ dindex++; } return 0; } /* * Scan data[] marking and counting groups */ scan() { register i, gcnt, gindex; /* * special case: first line always a group name */ groups[0].name = data[0]; groups[0].index = 0; ngroups = 1; i = 1; gindex = 0; gcnt = 0; while ( i < dindex ){ if ( data[i][0] == '%' ){ groups[gindex].count = gcnt; gcnt = 0; /* close out prev group */ ngroups++; i++; /* start next group */ /* * If a #included file has any blank lines after * the last '%' then the group name would wind * up being '\0'. So the first group name after * the #include won't be marked as a group name * and will thus never be expanded. We could * cluck our tongues at the user and say he has * a bogus file and thus deserves what he gets. * But hopefully this check will just make the * program more robust. */ while ((i < dindex) && (data[i][0] == '\0')){ i++; } gindex++; groups[gindex].name = data[i]; groups[gindex].index = i; }else{ gcnt++; } i++; } ngroups--; /* The last % in the file doesn't start a new group */ return 0; } /* * This is where we finally do the deed. If a string is a group name * then expand() will randomly select a member of that group to * replace it. Through the miracle of recursion, a whole sentence * may be passed to expand() and each word (anything bounded by what * we call "white space" gets expanded. Anything that cannot be * expanded gets printed out. */ expand(s,lim) char s[]; int lim; { register i, j, k, done, n, r; i = j = 0; while ( s[i] != 0 && i < lim ){ done = 0; while ( ! done && j <= lim ){ if ( isawhite(s[j]) ){ /* chase down remaining white space */ for (k=j; k<=lim && s[k] && isawhite(s[k]);k++){ ; } n = isagroup(&s[i], j-i); if ( n >= 0 ){ r = (groups[n].index + 1 + rnd(groups[n].count)); expand( data[r], strlen(data[r])); outstring(&s[j], k-j); } else { outstring(&s[i], k-i); } done++; i = j = k; /* should be on next word, if any */ } j++; } } } /* * Return index into groups[] array if a group name, -1 if just a word. * We have to use gbuf, a seperate place, so that we can null-terminate * the string where we want. Otherwise it wouldn't know santa from * santana. */ isagroup(s,lim) char s[]; int lim; { register i; static char gbuf[BIGBUF]; strncpy(gbuf,s,lim); gbuf[lim] = '\0'; /* strncpy might not do this */ for(i=0; i<ngroups; i++ ){ if (groups[i].name && strcmp(gbuf,groups[i].name) == 0){ return i; /* hit */ } } return -1; /* fail */ } /* * Output string, handling splices */ outstring(s,lim) char s[]; int lim; { register i = 0; while ( s[i] != '\0' && i < lim ){ switch (s[i]){ /* case '|': break; /* splice: no output */ /* DWT- pixar!good told me about this little change. If you preceed a \ with a |, you can make legal C statements part of your output. E.g. printf("foo|\n"); in an input file should translate to printf("foo\n"); in the output. */ case '|': if ( s[i+1] == '\\' ){ putchar('\\'); /* special case: */ i++; /* |\ outputs a \ */ break; } break; /* splice: no output */ case '\\': putchar('\n'); break; default: putchar(s[i]); break; } i++; } } /* * Return random number 0 to limit */ rnd(limit) int limit; { if (limit > 0){ return (random() % limit); } return 0; /* better than a floating exception if lim == 0 */ } a_random_number() { #ifndef VMS struct timeval tp; struct timezone tzp; gettimeofday (&tp, &tzp); return((getpid() ^ tp.tv_usec) % 123456); #else /* DWT- VMS is not quite but almost entirely different... */ struct timeb tp; ftime( &tp ); return((getpid() ^ tp.millitm) % 123456); #endif } /* * Return 1 if one of our "white" characters. A white character is * any character which can bound a group name, so punctuation marks * are included. */ isawhite(c) char c; { if ( c == '\0' || /* traditional white space */ c == ' ' || c == '\t' || c == '|' || /* "splice" character */ c == '\\' || /* becomes a newline */ c == '.' || /* common punctuation */ c == '-' || c == ':' || c == ';' || c == ',' || c == '!' || c == '?' || c == '[' || c == ']' || c == '{' || c == '}' || c == '(' || c == ')' || c == '\'' || c == '\"' || c == '`' ) return 1; return 0; } printgroups() { /* DWT- Use the "-d" command line option to make ncode print out a list of */ /* the groups and their elements */ int gindex, thing; for ( gindex = 0; gindex < ngroups; gindex++ ) { printf( "Group %s has %d elements\n", groups[gindex].name, groups[gindex].count ); for ( thing = groups[gindex].index; thing<= groups[gindex].index + groups[gindex].count; thing++ ) printf( "%d\t%s\n", thing, data[thing] ); printf( "\n\n" ); } } -h- ncode.man Tue Jan 20 11:02:55 1987 ncode.man NCODE(1) UNIX Programmer's Manual NCODE(1) NAME ncode - stochastic text construction SYNOPSIS ncode [-n number] [-g groupname] [-d] codefile DESCRIPTION _N_c_o_d_e reads in a file of a certain format and randomly con- structs text based on the organization of the file. Other files may be recursively included by putting #include pathname on any line of the file. This is useful when you want to use a file of basic definitions, or groups, in different configurations. The -n flag is used to run the program through the main loop multiple times. A "group" name is defined as the word on the first line of the file and, more commonly, the word on each line following a line starting with "%". The members of a group are all lines between the group name and the next "%". When a group name is encountered, surrounded by any of a set of charac- ters called "white space" in this context, it is randomly expanded into one of its members. Group names are not allowed to contain any white space, to prevent terminal con- fusion on the part of the program. The -g flag allows you to start the expanding process on a group name other than the default, which is "CODE". The argument may be a group name, or an entire string including group names, just as if it were a line in the file. It is legal to start on any group in the file, and groups may be referenced before or after the place in the file where they are defined. In the case of duplicate group definitions, the first one occurring is the only one used. For example, here is a sample group definition: NOUN lamp house car % The line "See the NOUN." could be randomly expanded to say "See the lamp." The characters considered "white" for the purpose of bound- ing a group name, besides what is normally considered white Printed 12/29/86 Pixar 1 NCODE(1) UNIX Programmer's Manual NCODE(1) space, are currently: | \ . - : ; , ! ? [ ] { } () ' " ` Two of those characters have special meanings to _n_c_o_d_e. The "|" symbol allows you to "splice" things to a group name. When it is encountered, no character is printed on output. The "\" causes a newline to be printed on output. The simplest application would be for a "fortune" program, but _n_c_o_d_e could also be used for more complex things such as a rumor generating file. The group definitions will be left as an exercise for the reader, but the following example should prove illuminating: CODE It was rumored today that COMPANY will be bought by COMPANY for PRICE\. PERSON, POSITION of COMPANY, said that PRODUCT will be announced DATE\. Note that every string to be expanded must be on only one line of the file. The program now dynamically allocates memory in a very general way, so the total size of your input files and the length of the lines in the files is lim- ited only by how much memory you can get. The only hard limit is that a group name can't be over 4096 characters long. If you can't come up with a unique group name in fewer characters then don't blame me. BUGS No bugs. Only features that you haven't figured out how to use yet. A recent improvement makes it tolerant of blank lines following the last % in a #include file. DIAGNOSTICS Standard perror() stuff. Pretty self explanatory. A bogus input file might benignly yield cryptic results. AUTHOR Craig Good Printed 12/29/86 Pixar 2 -h- ncode.sample1 Tue Jan 20 11:02:55 1987 ncode.sample1 NOUN North South East West Truth grass desk wall window ceiling floor car sign % NUMBER one two two 3.1415927 three eleven a googol % VERB meet knock kiss hug trot miss nod wink hit walk fly zip smash sniff % FLOWERS Roses Violets Chrysanthemums Daisies Gardenias Stinkweeds Petunias % COLOR puce invisible red tan white blue green muave purple chartreuse black yellow % SOMETHING I am Sugar is Radiation is Computing is Nitrous Oxide is ANIMALS are AUTHOR_ANY is You are % PROPERTY fearful liberal conservative sexy schizophrenic sweet bitter stupid ugly hilarious slow miserable % ISYOU are you. is this. am I. is Maple Surple. is it. it is. are they. -...who cares? % HAND mouth hand hand eye eye nose ear tooth foot % AUTHOR_A Craig Good Michael Jackson Wally Beaver Spock Gidget Bambi Dracula Superman Kahn Bullwinkle Bo Derek Koo Stark Lady Diana Steve Jobs Roy Rogers Bugs Bunny James Bond Godzilla Kilroy The Emperor Sweeny Todd Kate Bush % AUTHOR_AN Anonymous Andre Oliver North Ed Catmull % AUTHOR_ANY AUTHOR_AN AUTHOR_A AUTHOR_A FOX FOX FOX % ANIMAL_A Bird Snail Panda Fishy Doggy Puppy Tiger Kitty Worm Kangaroo Wart Hog Penguin Polar Bear Parakeet Cat Mountain Goat Moose Mouse % ANIMAL_AN Egret Aardvark Emu Elephant % ANIMAL_ANY ANIMAL_AN ANIMAL_A ANIMAL_A ANIMAL_A % ANIMALS Birds Snails Pandas Fish Dogs Puppies Tigers Kittens Aardvarks Worms Kangaroos Wart Hogs Penguins Polar Bears Parakeets Cats Mountain Goats Mooses Mice % ROYALTY Prince King Boss Programmer Hacker Salesman Head Hunter % MITS knickers arm bands mittens sunglasses cowboy boots galoshes % HURT hurt hurt kill slap deoderize break zap vaporize irradiate bother % STICKS Sticks Stones Bullets Bombs Croissants Keyboards % FOREST ball park forest swamp land jungle ghetto drug store office % PLACE garage oven bush bush FOREST % TREE a tree FOX's knee FOX's knee FOX's knee FOX's knee % PROVERB NOUN is NOUN, and NOUN is NOUN,\and never the twain shall meet.\ NOUN is NOUN, and NOUN is NOUN,\and never the twain shall VERB.\ NOUN is NOUN, and NOUN is NOUN,\and never the twain shall VERB.\ NOUN is NOUN, and NOUN is NOUN,\and never the ANIMAL_ANY shall VERB.\ NOUN is NOUN, and NOUN is NOUN,\and never the ANIMAL_ANY shall VERB.\ NOUN is NOUN, and NOUN is NOUN,\and never the ANIMAL_ANY shall VERB.\ A ANIMAL_A is as good as a FOREST to AUTHOR_ANY.\ A ANIMAL_A is as good as a FOREST to AUTHOR_ANY.\ An ANIMAL_AN is as good as a FOREST to AUTHOR_ANY.\ A HURT is as good as a VERB to a ANIMAL_A.\ A HURT is as good as a VERB to an ANIMAL_AN.\ A HURT is as good as a VERB to a ANIMAL_A.\ A HURT is as good as a VERB to an ANIMAL_AN.\ A VERB is as good as a HURT to AUTHOR_ANY.\ A VERB is as good as a HURT to AUTHOR_ANY.\ FLOWERS and MITS\May HURT my bones,\But AUTHOR_ANY will never VERB me.\ STICKS and ANIMALS\May HURT my bones,\But FLOWERS will never HURT me.\ FLOWERS and STICKS\May HURT my bones,\But MITS will never HURT me.\ STICKS and STICKS\May HURT my bones,\But ANIMALS will never VERB me.\ Never VERB today what you can HURT tomorrow. Never VERB today what you can HURT tomorrow. Never HURT today what you can VERB tomorrow. A ANIMAL_A in the HAND is worth NUMBER in the PLACE. An ANIMAL_AN in the HAND is worth NUMBER in the PLACE. A ANIMAL_A in the HAND is worth NUMBER in the PLACE. An ANIMAL_AN in the HAND is worth NUMBER in the PLACE. A AUTHOR_A in the HAND is worth NUMBER in the PLACE. An AUTHOR_AN in the HAND is worth NUMBER in the PLACE. Never look a gift ANIMAL_ANY in the mouth. Dead ANIMALS aren't much fun. % VERSE ANIMAL_ANY, ANIMAL_ANY, burning bright\In the FOREST of the night\What immortal HAND or HAND\Dare frame thy PROPERTY symmetry?\ FLOWERS are COLOR,\FLOWERS are COLOR,\SOMETHING PROPERTY,\And so ISYOU\ Hark! Hark!\The ANIMALS do bark!\The ROYALTY is fond of ANIMALS\He likes to take their insides out\And wear them as his MITS.\ I think that I shall never see\A thing as lovely\As TREE.\ % TITLE "Why AUTHOR_ANY tried to HURT the ANIMAL_ANY" "The day AUTHOR_ANY wanted to HURT the ANIMAL_ANY" "ANIMALS" "FLOWERS" "The PROPERTY ANIMAL_ANY" "The PROPERTY FLOWERS" "Ode to AUTHOR_ANY" "I'm so COLOR without my ANIMAL_ANY" "Ode to the ANIMAL_ANY" "I'm dreaming of a COLOR Christmas" "I Love The FLOWERS" "Dead ANIMALS" % CODE \PROVERB\\ --AUTHOR_ANY\ \PROVERB\\ --AUTHOR_ANY\ \VERSE\\ --AUTHOR_ANY\ \VERSE\\ --AUTHOR_ANY\ \TITLE\\VERSE\\ --AUTHOR_ANY\ % #include ncode.sample2 -h- ncode.sample2 Tue Jan 20 11:02:55 1987 ncode.sample2 FOX Appollonia April Wayne Barbara Hershey Bo Derek Brooke Adams Carly Simon Carol Alt Catherine Mary Stewart Cheryl Tiegs Christie Brinkley Coco Mitchell Cybill Shepherd Darryl Hannah Erin Grey Farrah Fawcett Majors Heather Thomas Jaclyn Smith Jamie Lee Curtis Jane Seymour Janet Jones Jennifer Beales Jenny Seagrove Johann Carlo Kate Capshaw Kate Jackson Kathy Ireland Kelly Emberg Kelly LeBrock Kim Basinger Lauren Hutton Lea Thompson Lisa Bonet Lisa Hartman Markie Post Marlee Matlin Melanie Griffith Michelle Pfieffer Nastasia Kinski Ola Ray Olivia Newton John Pamela Sue Martin Paulina Porizkova Rachel Ward Rosanna Arquette Sheila E Shelly Hack Signey Coleman Stevie Nicks Tahnee Welch Tanya Roberts Victoria Principal Vivian Ruiz Whitney Houston % -h- abuse.ncode Tue Jan 20 11:02:55 1987 abuse.ncode NOUN house coat badger piece of lizt wire calliope patch of crab grass desktop copier troglodyte sot puff of lint gasbag cartoon love doll clump of okapi dung trash bag buffoon dingo's kidney ANIMAL_ANY % ADJECTIVE COLOR PROPERTY % PROPERTY infectious soft shelled overbearing festering balloon-eared smug fetid watery fearful inflatable slimy silly liberal conservative thick headed androgynous ambiguous sexy schizophrenic sweet vacuous bitter stupid insufferable ugly hilarious slow intimidated sticky miserable % ADVERB bloody disgustingly lecherously mind-bogglingly incredibly festeringly insufferably % NUMBER one two two 3.1415927 three eleven a googol % VERB meet knock kiss hug trot miss nod wink hit walk fly zip smash sniff % FLOWERS roses violets chrysanthemums daisies gardenias stinkweeds petunias % COLOR puce invisible red tan white blue green muave purple chartreuse black yellow % HAND mouth hand hand eye eye nose ear tooth foot % AUTHOR_A Craig Good Michael Jackson Wally Beaver Spock Gidget Bambi Dracula Superman Kahn Bullwinkle Bo Derek Koo Stark Lady Diana Steve Jobs Roy Rogers Bugs Bunny James Bond Godzilla Kilroy The Emperor Sweeny Todd Kate Bush % ANIMAL_A bird snail panda fishy doggy puppy tiger kitty worm kangaroo wart hog penguin polar bear parakeet cat mountain goat moose mouse % ANIMAL_AN egret aardvark emu elephant % ANIMAL_ANY ANIMAL_AN ANIMAL_A ANIMAL_A ANIMAL_A % ANIMALS birds snails pandas fish dogs puppies tigers kittens aardvarks worms snuggle bunnies kangaroos wart hogs penguins polar bears parakeets cats mountain goats mooses mice % ROYALTY prince king boss programmer hacker salesman head hunter % MITS knickers arm bands mittens sunglasses cowboy boots galoshes % HURT hurt hurt kill slap deoderize break zap vaporize irradiate bother % GERUND hurting hurting killing beating slapping deoderizing breaking zapping vaporizing irradiating bothering % STICKS sticks stones bullets bombs croissants keyboards % FOREST ball park forest swamp land jungle ghetto drug store office % PLACE garage oven bush bush FOREST % WIFE wife ROYALTY daughter aged aunty MITS grandmother mother ANIMAL_ANY father son uncle % BODILY_PARTS ANIMALS MITS arm pits bottoms ear lobes toe nails shoulder blades medulla oblongata % ACTION_DOER biter wiper eater painter butcher baker purloiner purveyer sniffer ogler % TIME_THING lately today all the time whenever you're on the computer in small groups in a crowd when you're alone in the sack in the clutch when we're together % ABUSE How come you're so ADVERB PROPERTY TIME_THING?\\ You ADJECTIVE NOUN\\ You ACTION_DOER of other people's BODILY_PARTS\\ You ADJECTIVE, ADJECTIVE NOUN\\ When did you stop GERUND your WIFE?\\ You NOUN\\ % CODE ABUSE %