/* The obfuscated universe v. 0.0.1 – by evildave */
#include < cstdlib >
#include < iostream >
#include < cstring >
#include < ctime >
#include < list >
using namespace std;
// Gimme kbhit & getch
#include < conio.h >
// Return index of a variation of a found argument if it's there, else 0 (same as command line executable)
// argc, argv from main
// szzarg, a nul terminated list of nul terminated strings
int FindArgs( int argc, const char** argv, const char* szzarg )
{
while( *szzarg )
{
const char** pargv = argv + argc;
int curr = argc;
while( --curr )
{
if( !strcmp( *--pargv, szzarg ) )
return curr;
}
szzarg += strlen(szzarg)+1;
}
return 0;
}
// Something to generate phases from
#define EDEF_GENERATION(edef) \
edef(BORN)\
edef(INFANT)\
edef(CHILDHOOD)\
edef(ADOLESCENCE)\
edef(ADULTHOOD)\
edef(MIDDLEAGE)\
edef(SENIOR)\
edef(ELDERLY)\
edef(OLDAGE)\
#define EDEF_ENUM(e) e,
#define EDEF_STRING(e) #e,
#define EDEF_VNAME(e) mf_ ## e
#define EDEF_VTAB(e) EDEF_VNAME(e),
#define EDEF_DFUNC(e) void EDEF_VNAME(e)();
#define EDEF_IFUNC(e) void Life::EDEF_VNAME(e)()
#define EDEF_CASE(e) case e: EDEF_VNAME(e)(); break;
class Life
{
time_t born;
time_t laststage;
static time_t lifestagetime;
static list<Life*> population;
static list<Life*> killed;
friend void fnatexit(void);
friend int main(int argc, const char** argv );
enum LifeStage
{
EDEF_GENERATION(EDEF_ENUM)
} phase;
static const char* szLifeStage[];
EDEF_GENERATION(EDEF_DFUNC);
public:
char name[16];
Life();
~Life();
void Die();
void Live();
void Stage();
};
list<Life*> Life::population;
list<Life*> Life::killed;
time_t Life::lifestagetime = 1;
const char* Life::szLifeStage[] = { EDEF_GENERATION(EDEF_STRING) };
Life::Life()
{
laststage = born = time(NULL);
phase = BORN;
population.push_back( this );
const char vowel[5] = { 'a','e','i','o','u' };
const char consonant[21] = { 'b','c','d','f','g','h','j','k','l','m','n','p','q','r','s','t','v','w','x','y','z' };
name[0] = toupper(consonant[rand()%sizeof consonant]);
int nsyl = 1 + (rand()%5);
char *p = name+1;
while( nsyl-- )
{
*p++ = vowel[rand() % sizeof vowel];
*p++ = consonant[rand() % sizeof consonant];
}
*p++ = 0;
cout << name << ": " << "Waah!\n";
}
Life::~Life()
{
cout << name << ": " << "Taco! (lived " << laststage - born << " second" << (laststage - born == 1 ? "" : "s" ) << " and died while in stage: " << szLifeStage[phase] << ")\n";
}
void Life::Die()
{
killed.push_back(this);
}
void Life::Live()
{
time_t curr = time(NULL);
if( curr - laststage >= lifestagetime )
{
laststage = time(NULL);
phase = (LifeStage)(1 + phase);
Stage();
}
}
void Life::Stage()
{
switch( phase )
{
EDEF_GENERATION(EDEF_CASE)
}
}
EDEF_IFUNC(BORN)
{
// Might die at birth
cout << name << ": " << "Waah!\n";
if( (rand() & 15) == 1 )
Die();
}
EDEF_IFUNC(INFANT)
{
cout << name << ": " << "Goo...\n";
// Might die
if( (rand() & 15) == 1 )
Die();
}
EDEF_IFUNC(CHILDHOOD)
{
// Might die
cout << name << ": " << "I believe in Santa Claus!\n";
if( (rand() & 15) == 1 )
Die();
}
EDEF_IFUNC(ADOLESCENCE)
{
// Might have a baby
if( (rand() & 15) > 12 )
new Life();
cout << name << ": " << "I believe in God!\n";
// Might die
if( (rand() & 15) == 1 )
Die();
}
EDEF_IFUNC(ADULTHOOD)
{
// Might have a baby
if( (rand() & 15) > 5 )
new Life();
cout << name << ": " << "I believe I'd better get to work.\n";
// Might die
if( (rand() & 15) < 2 )
Die();
}
EDEF_IFUNC(MIDDLEAGE)
{
// Might have a baby
if( rand() & 1 )
new Life();
cout << name << ": " << "I believe I'll have another donut.\n";
// Might die
if( (rand() & 15) < 4 )
Die();
}
EDEF_IFUNC(SENIOR)
{
cout << name << ": " << "I believe I'll sit down.\n";
// Might die
if( (rand() & 15) < 5 )
Die();
}
EDEF_IFUNC(ELDERLY)
{
cout << name << ": " << "I believe I broke my hip.\n";
// Might die
if( (rand() & 15) < 7 )
Die();
}
EDEF_IFUNC(OLDAGE)
{
// Just dies
Die();
}
void fnatexit(void)
{
cout << "That's the end of the universe.\n";
cout.flush();
getch();
}
int main( int argc, const char** argv )
{
if( FindArgs( argc, argv, "-?\0/?\0-h\0-H\0/h\0/H\0" ) )
{
cout << *argv << "\n\t-l span between life phases\n";
return 0;
}
atexit( fnatexit );
int il = FindArgs( argc, argv, "-l\0-L\0" );
Life::lifestagetime = (il && il < argc-1) ? atoi(argv[1+il]) : 1;
srand(time(NULL));
cout << "Building generations that live for " << Life::lifestagetime << " seconds." << "\n";
int seedPop;
for( seedPop = 0; seedPop < 10; ++seedPop )
{
new Life();
}
// Keep the world going as long as there're people in it
while( Life::population.size() )
{
time_t stamp = time(NULL);
// Give everyone a life
list<Life*>::iterator iterate;
for( iterate = Life::population.begin(); iterate != Life::population.end(); iterate++ )
(*iterate)->Live();
// Clear up the dead people
while( Life::killed.size() )
{
Life* curr = Life::killed.front();
Life::population.remove(curr);
Life::killed.remove(curr);
delete curr;
}
if( kbhit() )
{
getch();
cout << "Doomsday for " << Life::population.size() << " people!!!\n";
while( Life::population.size() )
{
delete Life::population.front();
Life::population.pop_front();
}
return 0;
}
}
return 0;
}