//\\  ------------------------------------------------------------------
//\\ |		Artificial Life Project                               |
//\\ |		By: William Newell Fields                             |
//\\ |		Started: 9/94                                         |
//\\ |     		Completed:                                            |
//\\  ------------------------------------------------------------------

#include <time.h>
#include <dos.h>
#include <iomanip.h>
#include <iostream.h>
#include <stdlib.h>
#include <conio.h>
#include <signal.h>
#include <string.h>

enum SEX { M, F };
enum TTYPE { GRASS, FOOD, MOUNTAIN };
enum STATUS { OK, PREG };

int G_PERIOD = 100;  //\\ gestation period for pregnancy
const int MAXPOP = 1000;  //\\ maximum population!
int MATURE_AGE = 100;
int MAX_AGE = 1000;
int MAX_STARTING_HEALTH = 1500;  //\\ maximum starting health for creats
int FOOD_GROWTH_RATE = 10;  //\\ (0-100) % of cycles that new food grows
int MAX_N_VALUE = 50;  //\\ maximum nutritional value for food
int FERTILITY_RATE = 90;  //\\ (0-100) % of time that sex is successfull
int M_PUGNACITY = 2;  //\\ (0-100) % of the time that male fights occur
int F_PUGNACITY = 2;  //\\ "	"	"	"	"	 female "		"
int SIGHT = 5;  //\\ range of seeing (odd # please)
int RAND_MOVEMENT = 10;

const char FOOD_LOOKS = '°';
const int FOOD_COLOR = 10;
const char MOUNTAIN_LOOKS = '±';
const int MOUNTAIN_COLOR = 8;
const char GRASS_LOOKS = '°';
const int GRASS_COLOR = 2;

double current_time = 0;  //\\ real time reference from start of run
int d = 0;  //\\ delay time variable
long int cycle = 0;  //\\ cycle number
int pop = 0, m_pop = 0, f_pop = 0, food_pop = 0;  //\\ population variables
int graphics_on = 1;
int tellmex;
int tellmey;

void init_screen();  //\\ function declarations
void genesis(int);
void make_creat(int, int);
void show_stats();
void clear_stats();
void show_info_screen();
int opening_screen();
int billrandom(int);
void signal_handler(int);

//\\ ------------------------ CLASS DECLARATIONS -------------------------

class item  //\\ overall class for all objects to be plotted on screen
{
	protected:
		int x, y;  //\\ x, y coords.
		int color;  //\\ color
		char looks;  //\\ what the character looks like
		void draw_char();  //\\ only to be accessed from within class

	public:
		item(char a, int b, int c, int d)  //\\ constructor
			{ looks = a;  x = b;  y = c;  color = d; };
		void plot(int, int);  //\\ takes x,y coords of new location as args
		void plot();  //\\ plots at current x,y position
		void change_color(int a)  //\\ takes new color as arg
			{
				color = a;
				draw_char();
			};
		void change_looks(char a)
			{ looks = a; };
};

class creat : public item  //\\ creatures class (derived from item)
{
	private:
		SEX gender;  //\\ M = male = 0, F = female = 1  (enum type)
		int health;
		int gestation;
		int strength;
		int id;
		int age;
		STATUS condition;

	public:
		creat(char a, int b, int c, int d, SEX e, int f, int g) : item(a, b, c, d)
			{ gender = e; health = f; strength = g;
			  age = 0; condition = OK; id = pop; };
		void equal_to(creat*);
		void show_info();
		void movement();
		void sex_check();
		void health_check();
		void death();
		void eat_check();
		void preg_check();
		void fight_check();
};

class terrain : public item  //\\ all inanimate objects class (derived from item)
{
	public:
		TTYPE type;  //\\ type must be public
		int n_value;

		terrain(char a, int b, int c, int d, TTYPE e)
		 : item(a, b, c, d)  //\\ calls item const. then does this one
			{
				type = e;
				if (type == FOOD)
					n_value = billrandom(MAX_N_VALUE);
						else
					n_value = 0;
			};
		void make_food();
		void change_type(TTYPE);
};

struct pop_info
{
	int t;
	int value;
};

//\\ ---------------------------------------------------------------------

terrain* t_pntr[50][50];  //\\ global array of pointers to objects of terrain
creat* c_pntr[MAXPOP];  //\\ global array of pointers to object creats
pop_info graph_info[100000];

//\\ -------------------------- FUNCTIONS --------------------------------

int billrandom(int myx)
{
	return random()%myx;
};

void signal_handler(int signalValue)
{
	cout << "signalValue:" << signalValue << endl;
	cout << "tellmex:" << tellmex << endl;
	cout << "tellmey:" << tellmey << endl;
	cout << "pop:" << pop << endl;
	cout << "Cycle:" << cycle << endl;
	int response;
	cin >> response;
};

//\\ ( ITEM FUNCTIONS ) OOOOoooo....

void item::draw_char()  //\\ private to class
{
	if (graphics_on)
		{
			gotoxy(x, y);
			textcolor(color);
			putch(looks);
		};
};

void item::plot(int a, int b)  //\\ 2 arg version
{
	x = a;
	y = b;

	if (x < 0)	//\\ check boudaries of envir. and loop around
		x += 50;
	if (x > 50)
		x -= 50;
	if (y < 0)
		y += 50;
	if (y > 50)
		y -= 50;

	if (graphics_on) draw_char();
};

void item::plot()  //\\ no args version
{
	if (x < 1)	//\\ check boudaries of envir. and loop around
		x += 50;
	if (x > 50)
		x -= 50;
	if (y < 1)
		y += 50;
	if (y > 50)
		y -= 50;

	if (graphics_on) draw_char();
};

//\\ ( CREAT FUNCTIONS ) OOOOoooo....

void creat::movement()
{
	int tempx = x, tempy = y;

	t_pntr[x-1][y-1]->plot(); //\\ draw terrain over top of creat
					  //\\ screen={1,50} array={0,49} so must shift
	TTYPE temp_t;  //\\ temporary terrain type
	int a, b;
	int vert = 0, horiz = 0;  //\\ direction weights
	int sight_x = 0, sight_y = 0;
	int orig_sight_x = 0, orig_sight_y = 0;

	int anotherx, anothery;

	for (a = 0; a < SIGHT; a++)  //\\ survey all the area around
	{
		for (b = 0; b < SIGHT; b++)
		{
			sight_x = x - int((SIGHT-1)/2) + a;
			sight_y = y - int((SIGHT-1)/2) + b;

			orig_sight_x = sight_x;
			orig_sight_y = sight_y;

			if (sight_x < 1)	//\\ check boudaries of envir. and loop around
				sight_x += 50;
			if (sight_x > 50)
				sight_x -= 50;
			if (sight_y < 1)
				sight_y += 50;
			if (sight_y > 50)
				sight_y -= 50;

			temp_t = t_pntr[sight_x-1][sight_y-1]->type;

			if (temp_t == FOOD)
			{
				if (sight_x < x)       horiz -= SIGHT - abs(orig_sight_x - x);
				else if (sight_x > x)  horiz += SIGHT - abs(orig_sight_x - x);
				else if (sight_x == x) vert += vert * 2;

				if (sight_y < y)       vert -= SIGHT - abs(orig_sight_y - y);
				else if (sight_y > y)  vert += SIGHT - abs(orig_sight_y - y);
				else if (sight_y == y) horiz += horiz * 2;
			};
		};
	};

//\\ ----- Change vert + horiz into movement -----

	if ( billrandom(100) < 10 || (vert == 0 && horiz == 0) )
	{
		switch ( billrandom(4) )
		{
			case 0 : x++; break;  //\\ move right
			case 1 : x--; break;  //\\ move left
			case 2 : y++; break;  //\\ move up
			case 3 : y--; break;  //\\ move down
		};
	}
	else if ( abs(horiz) > abs(vert) )  //\\ move horizontal
	{
		if (horiz > 0) x++;       //\\ directly right
		else if (horiz < 0) x--;  //\\ directly left
	}
	else if ( abs(vert) > abs(horiz) )  //\\ move vertical
	{
		if (vert > 0) y++;        //\\ directly down
		else if (vert < 0) y--;   //\\ directly up
	}
	else if ( abs(vert) == abs(horiz) )  //\\ move diagonal if weights equal
	{
		if (horiz > 0) x++;       //\\ directly right
		else if (horiz < 0) x--;  //\\ directly left
		if (vert > 0) y++;        //\\ directly down
		else if (vert < 0) y--;   //\\ directly up
	};

	if (x < 1)	//\\ check boudaries of envir. and loop around
		x += 50;
	if (x > 50)
		x -= 50;
	if (y < 1)
		y += 50;
	if (y > 50)
		y -= 50;
	
	if (t_pntr[x-1][y-1]->type == MOUNTAIN)  //\\ if mountains are in the
		{ x = tempx; y = tempy; };  //\\ way go back to start

	plot();
};

void creat::equal_to(creat* a)  //\\ takes pointer to creat as an argument
{
	strength = a->strength;
	health = a->health;
	x = a->x;
	y = a->y;
	color = a->color;
	looks = a->looks;
	gender = a->gender;
	age = a->age;
	condition = a->condition;
	gestation = a->gestation;
};

void creat::show_info()  //\\ show info about this creat
{
		int yo = 32;
		gotoxy(70, yo); cout << setw(7) << id;
		gotoxy(70, yo+1); cout << setw(7) << x;
		gotoxy(70, yo+2); cout << setw(7) << y;
		gotoxy(70, yo+3);
			if (gender == M) cout << setw(7) << "Male";
				else
			if (gender == F) cout << setw(7) << "Female";
		gotoxy(70,yo+4); cout << setw(7) << health;
		gotoxy(70,yo+5); cout << setw(7) << strength;
		gotoxy(70,yo+6); cout << setw(7) << age;
		gotoxy(70,yo+7);
		if (condition == OK) cout << setw(7) << "OK";
		if (condition == PREG)
			{
				cout << setw(7) << "PREG";
				gotoxy(52,yo+8); textcolor(15); cputs("Birth Countdown: ");
				gotoxy(70,yo+8); cout << setw(7) << gestation;
			}
		else { gotoxy(52,yo+8); cout << "                            "; };

};

void creat::sex_check()
{

if (condition == OK && age > MATURE_AGE)  //\\ if person is not pregnant
{
	for (int u = 0; u < pop; u++)
	{
		if ( x == c_pntr[u]->x && y == c_pntr[u]->y  //\\ if on same spot
			&& u != id  					//\\ not compare to itself
			&& c_pntr[u]->condition == OK  	//\\ if other not preg
			&& c_pntr[u]->age > MATURE_AGE 	//\\ if other mature enough
			&& billrandom(100) < FERTILITY_RATE )  //\\ random factor
			 {
				if ( gender == F && c_pntr[u]->gender == M )
				{
						condition = PREG;  //\\ conception
						gestation = G_PERIOD;
						change_color(4);
				};
				if ( gender == M && c_pntr[u]->gender == F )
				{
						c_pntr[u]->condition = PREG;  //\\ conception
						c_pntr[u]->gestation = G_PERIOD;
						c_pntr[u]->change_color(4);
				};
			};
	};
};

};

void creat::preg_check()
{
	if (condition == PREG && gender == F)  //\\ if preg
	{
		gestation--;

		if (gestation <= 0)  //\\ if count down = 0 then birth
		{
			int temp_x = x + billrandom(6) - 3;  if (temp_x == 0) temp_x++;  //\\ random
			int temp_y = y + billrandom(6) - 3;  if (temp_y == 0) temp_y++;  //\\ coords
			make_creat(temp_x, temp_y);  //\\ if yes, reproduction!

			change_color(13);  //\\ change back to normal color
			condition = OK;  //\\ change back to normal condition
		};
	};
};

void creat::death()
{
	int t = id + 1;

	t_pntr[x-1][y-1]->plot();  //\\ draw terrain over dead creat

	if (gender == M) m_pop--;  //\\ if male, male population - 1
	if (gender == F) f_pop--;  //\\ if female, female population - 1

	if (id == pop-1) pop--;  //\\ if it is the last one then just lower pop
		else
	if (id != pop-1)  //\\ if it is not the last creat on the list
		{
			equal_to( c_pntr[id+1] );  //\\ this object set equal to next

			for (t; t < pop; t++)
			{
				c_pntr[t]->equal_to( c_pntr[t+1] );
			};
			delete c_pntr[pop-1];
			pop--;  //\\ reduce pop by 1
		};
};

void creat::health_check()
{
	health--;  //\\ decrease health by 1
	if (health <= 0) death();
	if (age > MAX_AGE) death();

	age++;  //\\ age increases

	if (age > MATURE_AGE && gender == M && color != 1)  //\\ puberity
		change_looks( char(11) );
	if (age > MATURE_AGE && gender == F && color != 5)  //\\ puberity
		change_looks( char(12) );
};

void creat::eat_check()
{
	if (t_pntr[x-1][y-1]->type == FOOD)  //\\ if the creat is on a foot spot
	{
		health += t_pntr[x-1][y-1]->n_value;  //\\ increased by n_value
		food_pop--;  //\\ amount of food is decreased
		t_pntr[x-1][y-1]->change_type(GRASS);  //\\ change type back to grass
	};
};

void creat::fight_check()
{

if ( (gender == M && billrandom(100) < M_PUGNACITY && age > MATURE_AGE) ||
	(gender == F && billrandom(100) < F_PUGNACITY && age > MATURE_AGE) )
{
	for (int u = 0; u < pop; u++)
	{
		if ( x == c_pntr[u]->x && y == c_pntr[u]->y  //\\ if on same spot
			&& u != id  				 //\\ not compared to itself
			&& c_pntr[u]->gender == gender  //\\ must be same gender
			&& c_pntr[u]->age > MATURE_AGE )  //\\ other old enough
			{
				if (strength > c_pntr[u]->strength)
					{ c_pntr[u]->death(); health += 100; }
					else
					{ death(); c_pntr[u]->health += 100; };
			};
	};
};
};

//\\ ( TERRAIN FUNCTIONS ) OOOOoooo....

void terrain::change_type(TTYPE a)
{
	if (a == GRASS)
	{
		change_color(GRASS_COLOR);
		n_value = 0;
		looks = GRASS_LOOKS;
	};
	if (a == MOUNTAIN)
	{
		change_color(MOUNTAIN_COLOR);
		n_value = 0;
		looks = MOUNTAIN_LOOKS;
	};
	if (a == FOOD)
	{
		change_color(FOOD_COLOR);
		n_value = billrandom(MAX_N_VALUE);
		looks = FOOD_LOOKS;
		food_pop++;
	};

	type = a;  //\\ change type to new type
	plot();  //\\ draw new type
};

void terrain::make_food()  //\\ make this terrain into food
{
	if (type != MOUNTAIN)
		change_type(FOOD);
};

//\\ ( REGULAR FUNCTIONS ) OOOOoooo....

void make_creat(int x, int y)
{
		int c;  //\\ temporary color
		SEX temp;  //\\ temporary sex

		if ( billrandom(2) == 0 ) {	temp = M; c = 9; m_pop++; }
			else
				{ temp = F; c = 13; f_pop++; };

		c_pntr[pop] = new creat( 'o', x, y, c, temp, billrandom(MAX_STARTING_HEALTH),
							billrandom(100) );

		c_pntr[pop]->plot();  //\\ plot new creatures

		pop++;  //\\ increment population by 1
};

void show_stats()  //\\ show current statistics
{
		int yo = 20;
		gotoxy(71, yo); cout << setw(6) << pop;
		gotoxy(70, yo+1); cout << setw(7) << m_pop;
		gotoxy(70, yo+2); cout << setw(7) << f_pop;
		if (d == 0)
			{ gotoxy(70,yo+3); cout << setw(7) << "    OFF   "; }
		else
			{ gotoxy(70,yo+3); cout << setw(7) << d << " ms"; };
		gotoxy(70, yo+4); cout << setw(7) << current_time << " s";
		gotoxy(70, yo+5); cout << setw(7) << cycle;
		if (current_time > 0)
			{ gotoxy(70, yo+6); cout << setw(7) << int(cycle / current_time); };
		gotoxy(70, yo+7); cout << setw(7) << food_pop;
};


void genesis(int initial_pop)
{
	//\\ ---- And god created the earth ----

	TTYPE temp_t;  //\\ temporary type
	int temp_c;  //\\ temporary color
	char temp_l;  //\\ temporary looks

	for (int x = 1; x < 51; x++)  //\\ for every x
		{
			for (int y = 1; y < 51; y++)  //\\ and y coord. we put terrain
				{
					int r = billrandom(100);  //\\ random factor

					if (r < 90) { temp_t = GRASS; temp_c = GRASS_COLOR; temp_l = GRASS_LOOKS; }
						else
					if (r >= 93 && r < 95) { temp_t = FOOD; temp_c = FOOD_COLOR; temp_l = FOOD_LOOKS; }
						else
					if (r >= 95) { temp_t = MOUNTAIN; temp_c = MOUNTAIN_COLOR;  temp_l = MOUNTAIN_LOOKS;};

					t_pntr[x-1][y-1] = new terrain(temp_l, x, y, temp_c, temp_t);
					t_pntr[x-1][y-1]->plot();
					if (t_pntr[x-1][y-1]->type == FOOD) food_pop++;
				};
			};

	//\\ ---- and god created the creats ----

	for (int i = 0; i < initial_pop; i++)
	{
		int a = billrandom(50);
		int b = billrandom(50);
		make_creat(a, b);
	};
};

void init_screen()
{
	clrscr();
	textcolor(8);
	for (int i = 1; i < 51; i++)  //\\ draw lines
		{
			gotoxy(51, i);
			cputs("³");
		};
	gotoxy(51, 2); cputs("ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
	gotoxy(51,42); cputs("ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
	gotoxy(51,44); cputs("ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");

	textcolor(11);
	gotoxy(52, 1);	 cputs("A R T I F I C I A L   L I F E"); //\\ draw titles
	gotoxy(52, 43); cputs("C O M M A N D S");

	int yo = 4;
	textcolor(3);
	gotoxy(52, yo-1); cputs("CONSTANTS_________________");
	textcolor(15);
	gotoxy(52, yo); cputs("Max Population: ");
	gotoxy(70, yo); cout << setw(7) << MAXPOP;  //\\ max pop is constant
	gotoxy(52, yo+1); cputs("Mature Age: ");
	gotoxy(70, yo+1); cout << setw(7) << MATURE_AGE;  //\\ max pop is constant
	gotoxy(52, yo+2); cputs("Max Age: ");
	gotoxy(70, yo+2); cout << setw(7) << MAX_AGE;  //\\ max pop is constant
	gotoxy(52, yo+3); cputs("Max Strtng Hlth: ");
	gotoxy(70, yo+3); cout << setw(7) << MAX_STARTING_HEALTH;  //\\ max pop is constant
	gotoxy(52, yo+4); cputs("Food Growth Rate: ");
	gotoxy(70, yo+4); cout << setw(7) << FOOD_GROWTH_RATE;  //\\ max pop is constant
	gotoxy(52, yo+5); cputs("Max Food Value: ");
	gotoxy(70, yo+5); cout << setw(7) << MAX_N_VALUE;  //\\ max pop is constant
	gotoxy(52, yo+6); cputs("Gestation Period: ");
	gotoxy(70, yo+6); cout << setw(7) << G_PERIOD;  //\\ max pop is constant
	gotoxy(52, yo+7); cputs("Fertility Rate: ");
	gotoxy(70, yo+7); cout << setw(7) << FERTILITY_RATE;  //\\ max pop is constant
	gotoxy(52, yo+8); cputs("Male Pugnacity: ");
	gotoxy(70, yo+8); cout << setw(7) << M_PUGNACITY;  //\\ max pop is constant
	gotoxy(52, yo+9); cputs("Female Pugnacity: ");
	gotoxy(70, yo+9); cout << setw(7) << F_PUGNACITY;  //\\ max pop is constant
	gotoxy(52, yo+10); cputs("Random Movement: ");
	gotoxy(70, yo+10); cout << setw(7) << RAND_MOVEMENT;  //\\ max pop is constant
	gotoxy(52, yo+11); cputs("Sight (diameter): ");
	gotoxy(70, yo+11); cout << setw(7) << SIGHT;  //\\ max pop is constant

	yo = 20;
	textcolor(3);
	gotoxy(52, yo-1); cputs("ENVIRONMENT INFO__________");
	textcolor(15);
	gotoxy(52, yo); cputs("Current Population: ");
	gotoxy(52, yo+1); cputs("Male Population: ");
	gotoxy(52, yo+2); cputs("Female Population: ");
	gotoxy(52, yo+3); cputs("Delay time: ");
	gotoxy(52, yo+4); cputs("Current run time: ");
	gotoxy(52, yo+5); cputs("Cycle #: ");
	gotoxy(52, yo+6); cputs("Average CPS: ");
	gotoxy(52, yo+7); cputs("Amount of Food: ");

	yo = 32;
	textcolor(3);
	gotoxy(52, yo-1); cputs("CREATURE INFO_____________");
	textcolor(15);
	gotoxy(52, yo); cputs("Creat #: ");
	gotoxy(52, yo+1); cputs("X: ");
	gotoxy(52, yo+2); cputs("Y: ");
	gotoxy(52, yo+3); cputs("Gender: ");
	gotoxy(52, yo+4); cputs("Health: ");
	gotoxy(52, yo+5); cputs("Strength: ");
	gotoxy(52, yo+6); cputs("Age: ");
	gotoxy(52, yo+7); cputs("Status: ");

	gotoxy(52, 45); cputs("S - Toggle Creat Info");
	gotoxy(52, 46); cputs("D - Delay Toggle");
	gotoxy(52, 47); cputs("Q - Quit");
	gotoxy(52, 48); cputs("P - Pause");
	gotoxy(52, 49); cputs("I - Cycle through info");
	gotoxy(52, 50); cputs("G - Turn of graphics");
};

void clear_stats()  //\\ redraw screen to clean up garbage
{
	for (int a = 70; a < 80; a++)
	{
		for(int b = 32; b < 41; b++)
		{
			gotoxy(a, b);
			cputs(" ");
		};
	};
};

void show_graph(int pop_count, int max_reached_pop)
{
	clrscr();
	textcolor(15);
	cputs("POPULATION vs. TIME GRAPH");
	textcolor(1);
	float pop_res = 48 / float(max_reached_pop);
	int max_time = cycle;
	float time_res = 79 / float(max_time);

	for (int i = 0; i < pop_count; i++)
	{
		if (graph_info[i].t != 0 && graph_info[i].value != 0)
		{
			int x = 1 + int(graph_info[i].t * time_res);
			int y = 50 - int(graph_info[i].value * pop_res);
			gotoxy(x, y);
			cputs("O");
		};
	};
};

int opening_screen()
{
	int quit_now = 0;

	clrscr();
	textcolor(15);
	gotoxy(25, 15); cputs("Artificial Life Simulation");
	gotoxy(20, 17); cputs("Programmed by William Newell Fields");
	gotoxy(80, 50);  //\\ make cursor wait in the corner
	getch();
	clrscr();
	gotoxy(31, 10); cputs("Main Menu");
	textcolor(7);
	gotoxy(23, 14); cputs("1 + Start the environment");
	gotoxy(23, 16); cputs("2 + See the information screen");
	gotoxy(23, 18); cputs("3 + Quit now");
	gotoxy(80, 50);  //\\ make cursor wait in the corner

switch_start:
	switch( getch() )
	{
		case '1' : break;
		case '2' : show_info_screen(); break;
		case '3' : quit_now = 1; break;
		default  : goto switch_start;
	};

return quit_now;
};

void show_info_screen()
{
	clrscr();
	cout << "This program simulates a controlled environment in which there is \n";
	cout << "living a population of creatures whose behavior is determined by a \n";
	cout << "set of rules and checks which they are continually subjected to.";
	cout << "\n\nTheir current life parameters are as follows:\n";
	cout << "\no Their movement is random unless there is a food unit nearby";
	cout << "\n  in which case it will move towards the food.";
	cout << "\no If they come into contact with any other creatures of the same sex,";
	cout << "\n  there is a chance that a fight will take place.  In case of a fight,";
	cout << "\n  the creature will the highest strength rating will win and the";
	cout << "\n  other will die.";
	cout << "\no Food grows at a set rate.";
	cout << "\no If they come in contact with a food unit, they will eat it,";
	cout << "\n  at the same time increasing their health by a random amount.";
	cout << "\no Their health is depleated by 1 every cycle that takes place.";
	cout << "\n  If their health reaches 0, then they die.";
	cout << "\no Their is a set maximum limit to how old a creature can live,";
	cout << "\n  our equivlant of dying from old age.";
	cout << "\no If a male and a female come into contact then there is a chance that";
	cout << "\n  the female will become pregnant.  If so, the icon for that creature";
	cout << "\n  changes color to red, there is a gestation period, birth takes place,";
	cout << "\n  and the icon changes back to the normal color.";
	cout << "\no There is a set age when the creature become mature (able to fight,";
	cout << "\n  reproduce, etc), when this takes place the creature changes appearance";
	cout << "\n  from the 'o' shape into the popular male and female symbols.";
	cout << "\no Time goes in 'cycles'.  For every cycle, each creature goes through the";
	cout << "\n  entire series life processes and checks.";
	cout << "\no There is an option to turn off the delay, the graphics, and the";
	cout << "\n  creatures current info display.";
	cout << "\no You are able to cycle through each of the creatures information while";
	cout << "\n  it is running.";
	cout << "\no Every creature is born with a random initial health, strength, and";
	cout << "\n  gender.";
	cout << "\no After the completion of the run, you will see the population graph";
	cout << "\n  of the creatures vs. time.";
	getch();
};

//\\ ----------------------------- MAIN PROGRAM ----------------------------

main()
{
	time_t first, second;  		//\\ variables of time
	int info_on = 1;  		//\\ toggle: display info about each creat
	int delay_on = 1;  		//\\ toggle: delay on or off
	int q = 0;  			//\\ toggle: to quit or not to quit
	int o = 0; 				//\\ counter: for info on each creat
	int i = 0;  			//\\ counter: all purpose
	int initial_pop;  		//\\ initial population variable
	char a;  				//\\ input from keyboard
	int start_pop;                //\\ needed for graph info
	int pop_count = 1;            //\\ how many times graph info was entered
	int max_reached_pop = pop;    //\\ maximum population reached

	for (i = 0; i < 100000; i++)  	//\\ clean out graph array
	{
		graph_info[i].t = 0;
		graph_info[i].value = 0;
	};

	signal(SIGSEGV,signal_handler);

	textmode(C4350);  //\\ set graphics mode
	if ( opening_screen() ) goto end_here;
	clrscr();
	textcolor(15);

	char s[256];


	gotoxy(10,8); cputs("Hit ENTER for default value (in square brackets).");

	gotoxy(10, 10); cputs("Starting population (1-1000) [200]: ");
	gets(s);
	if (strlen(s) == 0) initial_pop = 200;
	else initial_pop = atoi(s);

	gotoxy(10, 11); cputs("Maximum Age (will die at this age) [1000]: ");
	gets(s);
	if (strlen(s) == 0) MAX_AGE = 1000;
	else MAX_AGE = atoi(s);

	gotoxy(10, 12); cputs("Mature Age (can have babies at this age) [50]: ");
	gets(s);
	if (strlen(s) == 0) MATURE_AGE = 50;
	else MATURE_AGE = atoi(s);

	gotoxy(10, 13); cputs("Fertility Rate (% of time sex is successful) [75]: ");
	gets(s);
	if (strlen(s) == 0) FERTILITY_RATE = 75;
	else FERTILITY_RATE = atoi(s);

	gotoxy(10, 14); cputs("Gestation period (how long pregnancy lasts) [50]: ");
	gets(s);
	if (strlen(s) == 0) G_PERIOD = 50;
	else G_PERIOD = atoi(s);

	gotoxy(10, 15); cputs("Max Starting Health [1000]: ");
	gets(s);
	if (strlen(s) == 0) MAX_STARTING_HEALTH = 1000;
	else MAX_STARTING_HEALTH = atoi(s);

	gotoxy(10, 16); cputs("Food growth rate (0-100) [75]: ");
	gets(s);
	if (strlen(s) == 0) FOOD_GROWTH_RATE = 75;
	else FOOD_GROWTH_RATE = atoi(s);

	gotoxy(10, 17); cputs("Maximum Nutritional Value of Food [100]: ");
	gets(s);
	if (strlen(s) == 0) MAX_N_VALUE = 100;
	else MAX_N_VALUE = atoi(s);

	gotoxy(10, 18); cputs("Male Pugnacity (% of time fight will occur upon encounter) [10]: ");
	gets(s);
	if (strlen(s) == 0) M_PUGNACITY = 10;
	else M_PUGNACITY = atoi(s);

	gotoxy(10, 19); cputs("Female Pugnacity (% of time fight will occur upon encounter) [10]: ");
	gets(s);
	if (strlen(s) == 0) F_PUGNACITY = 10;
	else F_PUGNACITY = atoi(s);

	gotoxy(10, 20); cputs("Sight (how far away can spot food) [5]: ");
	gets(s);
	if (strlen(s) == 0) SIGHT = 5;
	else SIGHT = atoi(s);

	gotoxy(10, 21); cputs("Percentage random movement (0-100%) [10]: ");
	gets(s);
	if (strlen(s) == 0) RAND_MOVEMENT = 10;
	else RAND_MOVEMENT = atoi(s);

	gotoxy(10, 23); cputs("HIT A KEY TO START!"); getch();

	init_screen();  		//\\ setup screen
	genesis(initial_pop);  	//\\ create the environment and the creats

	first = time(NULL);  	//\\ get first time
	srand(first);

	graph_info[0].t = 0;    //\\ enter first entry into graph
	graph_info[0].value = pop;

	do
	{
		start_pop = pop;
		cycle++;  //\\ increment refrence time
		second = time(NULL);
		current_time = difftime(second, first);

		if (delay_on) 
		{
			d = int (200/pop);  //\\ delay is inversely proportional to pop
			if (d == 0) d = 1;  //\\ but don't let it go below 1
		}
		else d = 0;

		if (info_on) {  c_pntr[o]->show_info(); show_stats();  }  //\\ show all info if info_on
			else { show_stats(); };  //\\ only show system stats
		if (billrandom(100) < FOOD_GROWTH_RATE)  //\\ make food
			t_pntr[billrandom(50)][billrandom(50)]->make_food();

		for (i = 0; i < pop; i++) //\\ cycle through each creat
			{
				c_pntr[i]->movement();  //\\ moves creats randomly about
				c_pntr[i]->fight_check();
				c_pntr[i]->eat_check();  //\\ check for food on same spot
				c_pntr[i]->health_check();  //\\ update/check health info
				if (pop < MAXPOP)
					{
						c_pntr[i]->sex_check();  //\\ sex check
						c_pntr[i]->preg_check();  //\\ see if baby is ready
					};
				if (billrandom(1000) == 0) c_pntr[i]->death();  //\\ rock fall on head
				if (delay_on) delay(d);
			};

		//\\ keyboard check stuff---------------------------------------------------

		while ( kbhit() )  //\\ do this if a key has been hit
			{
				a = getch();
				switch (a)
					{
						case 's' : if (info_on) { info_on = 0; clear_stats(); }
								 else
								 if (!info_on) info_on = 1;
								 break;
						case 'i' : o++; if (o > pop-1) o = 0; break;
						case 'q' : q = 1; break;
						case 'p' : getch(); break;
						case 'g' : if (graphics_on)
											{
												graphics_on = 0;
												init_screen();
												gotoxy(20, 23); cout << "GRAPHICS OFF";
											}
									  else if (!graphics_on)
											{
												graphics_on = 1;
												for (int x = 1; x < 51; x++)
												{
													for (int y = 1; y < 51; y++)
													{
														t_pntr[x-1][y-1]->plot();
													};
												};
											};
											break;
						case 'd' : if (delay_on) delay_on = 0;
									  else if (!delay_on) delay_on = 1;
									  break;
					};
			};
//\\ -----------------------------------------------------------------------

		if (pop == 0)  q = 1; //\\ if population = 0 then quit

		if (max_reached_pop < pop) max_reached_pop = pop;

		if (start_pop != pop && pop_count < 100000)  //\\ if the population has changed and not overflow graph array
		{
			graph_info[pop_count].t = cycle;  //\\ store the change in the graph info
			graph_info[pop_count].value = pop;
			pop_count++;			
		};

	} while (!q);

	second = time(NULL);  //\\ get second time
	show_graph(pop_count, max_reached_pop);
	getch();

end_here:  //\\ label for end
clrscr();
textmode(C80);  //\\ set graphics mode back to normal

return 0;
};

