Sifi generator
Kevin D. Quitt
kdq at demott.COM
Tue Jul 31 05:37:53 AEST 1990
/**
Please note: This program was converted on the date shown from a
spaghetti-coded BASIC program (that almost worked). I am the original
author of both works, though G*d only knows why someone would claim
otherwise. I make no claims that the code below is optimal, or even
particularly good - most of the translation was done with editor macros.
Note that the original flowchart for this program is *not* my creation -
I believe that Gahan Wilson did it originally, I think about 81,
published in OMNI magazine. I do know that he published such a chart
for horror-films (somewhere, I have that one, too) - I believe this
latter was in National Lampoon. I would appreciate authoritative
information about the original author and chart. I would *really*
appreciate a copy of that chart - which I'll copy and mail to everyone.
Useful Improvements:
Some way of encoding the story produced to prevent duplication
of plot lines (within, oh, say, 50-100 plots).
Perhaps a better random number generator, or better seed.
More phrases, more "au curant" phrases (I just added the Captain Kirk
shtick), maybe some more original paths.
A better way to encode the phrase data perhaps, so that a switch-less
or switch-minimal engine can create all the phrases.
Looking for comments on whether to keep the phrases in a separate file,
something like:
SIZE:
tiny
large
"incredibly phenomenally huge"
BUT:
...
I already have code for parsing such files.
This code is ANSI C, but compiled with MSC 6.0. Let me know if ANSI
gives you problems; obviously it doesn't matter a whole lot. Please let
me know what changes you have to make to get it to run on your system -
I'll incorporate all I can. This is fairly simple; my goal is for it to
compile with warnings on any system.
I will periodically inform you of "improvements" via e-mail.
Mostly it's silly, and for fun. Let's see what we can do with it before
we release it on an unsuspecting net.
/* SIFI.C 24-Jul-90 21:21:51 by Kevin D. Quitt
Science fiction plot generator
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef MSDOS
#include <stdlib.h>
#include <time.h>
#else
typedef unsigned int time_t;
#endif
int col; /* characters on line */
#define TRUE (1==1)
#define FALSE (1!=1)
#define LINE_WIDTH (75)
#define SIZE_COUNT (6)
char *size[ SIZE_COUNT ] =
{
"tiny",
"giant",
"microscopic",
"planet-sized",
"humongous",
"itty-bitty"
};
#define BEING_COUNT (5)
char *being[ BEING_COUNT ] =
{
"bugs, which",
"reptiles, which",
"mechanical devices, which",
"super persons, who",
"icky things, which"
};
#define BEING_TYPE_COUNT (4)
char *being_type[ BEING_TYPE_COUNT ] =
{
"extra-galactic",
"Martian",
"Moon",
"Betelgeusian"
};
#define COMET_RESULTS_COUNT (4)
char *comet_results[ COMET_RESULTS_COUNT ] =
{
"destroyed.",
"saved by Jesus and the J.D.L.",
"not destroyed, but everybody dies.",
"not destroyed, but almost everybody dies."
};
#define KILLED_BY_COUNT (3)
char *killed_by[ KILLED_BY_COUNT ] =
{
"the Atomic Bomb",
"a crowd of peasants with torches",
"the Army, Navy, Air Force, Marine Corps and/or Coast Guard"
};
#define BUT_COUNT (4)
char *but[ BUT_COUNT ] =
{
"they fall in love with this beautiful girl",
"a cute little kid convinces them that people are O.K.",
"a priest talks to them of God",
"Captain Kirk uses logic on them"
};
#define TERMINAL1_COUNT (3)
char *terminal1[ TERMINAL1_COUNT ] =
{
"and they die.",
"and they leave.",
"and they turn into disgusting lumps."
};
#define TERMINAL2_COUNT (4)
char *terminal2[ TERMINAL2_COUNT ] =
{
"but they die from catching chicken pox.",
"so they kill us.",
"so they put us under a benign dictatorship.",
"so they eat us."
};
#define WEAPON_RESULTS_COUNT (3)
char *weapon_results[ WEAPON_RESULTS_COUNT ] =
{
"which fails",
"which kills them.",
"which turns them into disgusting lumps.",
};
char *skip_blanks( char *line )
{
char c;
while ( isspace( *line++ ) );
return --line;
}
/* Output text broken on word boundaries.
Text is automatically preceeded by a blank, unless a period starts
the line. Leading blanks are tossed when we're at the start of a line.
*/
void tell ( char *line )
{
int len = strlen( line );
int c, l;
char myline[ LINE_WIDTH + 1 ];
if ( (col != 0) && !ispunct( *line ) )
{
putchar( ' ' );
col++;
}
/* If the input text won't fit on the current line, we split it
*/
while ( (len + col) > LINE_WIDTH )
{
if ( col >= LINE_WIDTH ) /* Safety play from blank above */
{
puts( "" );
col = 0;
line = skip_blanks( line );
continue;
}
for ( l = LINE_WIDTH - col; l >= 0; l-- )
{
if ( isspace( c = line[ l ] ) || ( c == '-' ) )
{
if ( c == '-' )
l++;
strncpy( myline, line, l );
myline[ l ] = 0;
puts( myline );
col = 0;
len -= l;
line += l + 1;
break;
}
}
/* If we couldn't split it, the are two possibilites. If we're not on
column 0, then it may be that the *first* word is too long to fit. If
we *are* on column zero, then the string can't be split. In the former
case we start a new line and try again. In the latter, we punt.
*/
if ( l < 0 )
{
if ( col == 0 ) /* Can't be split! */
{
puts( line ); /* Joke it */
return;
}
col = LINE_WIDTH; /* First word can't be split */
}
}
printf( "%s", line );
col += len;
}
int describe_being (void)
{
int done = FALSE;
tell( size[ rand() % SIZE_COUNT ] );
tell( being[ rand() % BEING_COUNT ] );
switch( rand() % 6 )
{
case 0:
{
tell( "want our women,");
if ( rand() & 1 )
{
tell( "take a few and leave.");
done = TRUE;
break;
}
break;
}
case 1:
{
tell( "are friendly.");
done = TRUE;
break;
}
case 2:
{
tell( "are friendly, but misunderstood,");
break;
}
case 3:
{
tell( "misunderstand us");
break;
}
case 4:
{
tell( "understand us too well");
break;
}
case 5:
{
tell(
"look upon us only as a source of nourishment");
if ( rand() & 1 )
{
tell( "and eat us.");
done = TRUE;
break;
}
break;
}
}
return done;
}
int do_but (void)
{
int choice;
tell( ", but");
choice = rand() % BUT_COUNT;
tell( but[ choice ] );
if ( (choice == 0) && (rand() & 1) )
tell( "and they get married and live happily ever after.");
else
tell( terminal1[ rand() % TERMINAL1_COUNT ] );
return TRUE;
}
void sifi (void)
{
int done = FALSE;
int choice;
switch ( rand() % 6 )
{
case 0:
{
tell( "Earth is struck by a giant comet and");
tell( comet_results[ rand() % COMET_RESULTS_COUNT ] );
done = TRUE;
break;
}
case 1:
case 2:
{
tell( "Scientists discover or invent");
done = describe_being();
break;
}
case 3:
case 4:
{
tell( "Earth is attacked by");
done = describe_being();
break;
}
case 5:
{
tell( "Earth burns up or freezes or falls into the sun");
if ( rand() & 1 )
tell( "and everybody dies.");
else
tell( "and almost everybody dies.");
done = TRUE;
break;
}
}
if ( !done )
{
if ( rand() & 1 )
tell( "and are radioactive, and");
else
tell( "and are not radioactive, and");
if ( rand() & 1 )
tell( "can be killed by");
else
tell( "cannot be killed by");
tell( killed_by[ rand() % KILLED_BY_COUNT ] );
if ( rand() & 1 )
{
what_to_do:
if ( rand() & 3 )
done = do_but();
else
{
if ( rand() % 3 )
tell( terminal2[ rand() % TERMINAL2_COUNT ] );
else
{
tell( "so scientists invent a weapon");
choice = rand() % WEAPON_RESULTS_COUNT;
if ( choice == 0 )
goto what_to_do;
}
}
}
else
tell( ".");
}
}
int main( int argc, char *argv[] )
{
long how_many = 1;
long chapter = 1;
time_t seed;
if ( argc > 1 )
{
if ( *argv[1] == '-' )
how_many = atol( &argv[1][1] );
else
{
puts( "Science Fiction plot generator");
puts( "sifi -number_of_chapters");
exit( 0 );
}
}
time( &seed );
srand( (unsigned int)(seed & -1) );
while ( how_many-- )
{
col = 0;
sifi();
tell( " The End.\n\n");
}
return 0;
}
--
_
Kevin D. Quitt demott!kdq kdq at demott.com
DeMott Electronics Co. 14707 Keswick St. Van Nuys, CA 91405-1266
VOICE (818) 988-4975 FAX (818) 997-1190 MODEM (818) 997-4496 PEP last
96.37% of all statistics are made up.
More information about the Alt.sources
mailing list