Category : Printer + Display Graphics
Archive   : CRITTER4.ZIP
Filename : CRITTERS.C

 
Output of file : CRITTERS.C contained in archive : CRITTER4.ZIP
/*
Program: Critters
Version: 1.00 02-Jun-1989
Language: Microsoft QuickC v2.0
Purpose: Simulates simple life forms which evolve

Written by Scott Robert Ladd. No rights reserved.
*/

#include "graph.h"
#include "stddef.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "conio.h"
#include "time.h"


/* structure which defines a critter */
struct critter
{
int move_gene[4];
int energy_level;
int posx;
int posy;
long int age;
struct critter * next;
struct critter * prev;
};

/* constants which define the program environment */
const int start_crit = 25; /* initial number of critters */
const int start_food = 2500; /* initial food supply */

const int max_x = 600; /* maximum x dimension of "world" */
const int max_y = 300; /* " y " " " */

const int max_energy = 1000; /* max energy a critter can have */
const int max_food = 4000; /* max amount of food in existence */
const int max_age = 200; /* max age critter can reach w/o reproducing */
const int max_mutant = 4; /* max magnitude of a mutation */

const int food_value = 40; /* energy value of a piece of food */
const int move_cost = 1; /* energy cost for critter to move once */
const int repro_energy = 500; /* minimum energy for a critter to reproduce */
const int repro_age = 100; /* minimum age for a critter to reproduce */
const int start_energy = 500; /* initial energy level for starting critters */
const int food_growth = 2; /* amount of food created each generation */

/* boolean values for program behavior */
const int old_age_kills = 1; /* true */
const int mutate_parent = 0; /* false */
const int dead_are_food = 0; /* false */

/* colors of critters and food */
const short food_color = 7; /* grey */
const short crit_color = 15; /* white */

/* movement definition table */
const int delta_table[4][2] = { {0, -3}, {+3, 0,}, {0, +3}, {-3, 0} };

/* root and tail of critter linked list */
struct critter * first_critter = NULL;
struct critter * last_critter = NULL;

/* informational display counts */
long int critter_count = 0;
long int food_supply = 0;
long int generation = 0;

/* macro to get a random value between 1 and x */
#define randval(x) ((rand() % x) + 1)

/* function prototypes */
void main(void); /* program control and logic */
void setup(void); /* initial set-up of program */
void reproduce(void); /* critter reproduction/death cycle */
void movement(void); /* critter motion */
void make_food(void); /* adds new food to world */
void show_stats(void); /* displays current information on the world */
int cancel(void); /* checks for a keyboard entry */

void main(void)
{
setup();

do {
reproduce();
movement();
make_food();
show_stats();
}
while (!cancel());

_setvideomode(_DEFAULTMODE);
}

void setup(void)
{
int i, j, res, x, y, pval, working;
unsigned seed;
struct critter * temp_critter;

/* initialize random number generator */
seed = (unsigned)time(NULL);
srand(seed);

/* initialize graphics to EGA 16 color mode */
res = _setvideomode(_ERESCOLOR);

if (!res)
{
_setvideomode(_DEFAULTMODE);
exit(1);
}

/* initialize linked list of critters */
for (i = 0; i < start_crit; ++i)
{
temp_critter = malloc(sizeof(struct critter));

if (first_critter == NULL)
{
temp_critter->prev = NULL;
first_critter = temp_critter;
}
else
{
last_critter->next = temp_critter;
temp_critter->prev = last_critter;
}

last_critter = temp_critter;
temp_critter->next = NULL;

temp_critter->energy_level = start_energy;

for (j = 0; j < 4; ++ j)
temp_critter->move_gene[j] = j + 1;

temp_critter->posx = randval(max_x);
temp_critter->posy = randval(max_y);

temp_critter->age = 0;
}

/* place initial food supply */
_setcolor(food_color);

for (i = 0; i < start_food; ++i)
{
working = 1;

do {
x = randval(max_x);
y = randval(max_y);

pval = _getpixel(x,y);

if (pval != food_color)
{
_setpixel(x,y);
working = 0;
}

++food_supply;
}
while (working);
}

/* set information counts */
critter_count = start_crit;
food_supply = start_food;
}

void reproduce(void)
{
int i, x, y;
struct critter * temp_critter;
struct critter * new_critter;

++generation;

temp_critter = first_critter;

while (temp_critter != NULL)
{
/* the critter gets older */
++temp_critter->age;

/* if critter can reproduce, it does */
if ((temp_critter->energy_level >= repro_energy)
&& (temp_critter->age >= repro_age))
{
/* allocate a new critter */
new_critter = malloc(sizeof(struct critter));

if (new_critter == NULL)
{
_setvideomode(_DEFAULTMODE);
exit(3);
}

/* add new critter to end of critter list */
new_critter->prev = last_critter;
new_critter->next = NULL;
last_critter->next = new_critter;
last_critter = new_critter;

/* set new energy levels for parent and child */
temp_critter->energy_level = temp_critter->energy_level / 2;
new_critter->energy_level = temp_critter->energy_level;

/* inherit the old genes */
for (i = 0; i <= 3; ++i)
new_critter->move_gene[i] = temp_critter->move_gene[i];

/* select gene which is mutatated! */
for (i = randval(4) - 1; i <= 3; ++i)
new_critter->move_gene[i] += randval(max_mutant);

/* if parent mutates... */
if (mutate_parent)
{
for (i = randval(4) - 1; i <= 3; ++i)
temp_critter->move_gene[i] += randval(max_mutant);
}


/* put the new critter in the same place as its parent */
new_critter->posx = temp_critter->posx;
new_critter->posy = temp_critter->posy;

++critter_count;

new_critter->age = 0;
temp_critter->age = 0;
}
/* check to see if the critter dies */
else if ((temp_critter->energy_level == 0)
|| ((old_age_kills) && (temp_critter->age > max_age)))
{
--critter_count;

/* if all critters have died, end the program */
if (critter_count <= 0)
{
show_stats();

while (!cancel())
/* empty */ ;

_setvideomode(_DEFAULTMODE);

exit(2);
}

/* delete character from linked list */
if (temp_critter->prev == NULL)
{
first_critter = temp_critter->next;
first_critter->prev = NULL;
}
else if (temp_critter->next == NULL)
{
last_critter = temp_critter->prev;
last_critter->next = NULL;
}
else
{
temp_critter->prev->next = temp_critter->next;
temp_critter->next->prev = temp_critter->prev;
}

/* remove body of dead critter */
for (x = temp_critter->posx - 1; x <= temp_critter->posx + 1; ++x)
{
for (y = temp_critter->posy - 1; y <= temp_critter->posy + 1; ++y)
{
if (dead_are_food)
_setcolor(food_color);
else
_setcolor(0);

_setpixel(x,y);
}
}

if (dead_are_food)
food_supply += 9;

free(temp_critter);
}

temp_critter = temp_critter->next;
}
}

void movement(void)
{
int i, x, y;
int pval, move;
struct critter * temp_critter;

temp_critter = first_critter;

while (temp_critter != NULL)
{
/* erase critter from old position */
for (x = temp_critter->posx - 1; x <= temp_critter->posx + 1; ++x)
{
for (y = temp_critter->posy - 1; y <= temp_critter->posy + 1; ++y)
{
_setcolor(0);
_setpixel(x,y);
}
}

/* select movement */
move = randval(temp_critter->move_gene[3]);

for (i = 0; move > temp_critter->move_gene[i]; ++i)
/*empty*/;

/* adjust critters position */
temp_critter->posx += delta_table[i][0];
temp_critter->posy += delta_table[i][1];

/* wrap around the edges of the world if needed */
if (temp_critter->posx < 1)
temp_critter->posx = max_x;

if (temp_critter->posy < 1)
temp_critter->posy = max_y;

if (temp_critter->posx > max_x)
temp_critter->posx = 1;

if (temp_critter->posy > max_y)
temp_critter->posy = 1;

/* assess movement cost */
temp_critter->energy_level -= move_cost;

/* redraw critter at new position */
for (x = temp_critter->posx - 1; x <= temp_critter->posx + 1; ++x)
{
for (y = temp_critter->posy - 1; y <= temp_critter->posy + 1; ++y)
{

_setcolor(crit_color);
pval = _setpixel(x,y);

/* if pixel covered is a food particle, consume it! */
if (pval == food_color)
{
if (temp_critter->energy_level < max_energy)
temp_critter->energy_level += food_value;

--food_supply;
}
}
}

temp_critter = temp_critter->next;
}
}

void make_food(void)
{
int i, x, y, pval, working;

if (food_supply >= max_food)
return;

_setcolor(food_color);

/* drop pieces of food in blank spots */
for (i = 0; i < food_growth; ++i)
{
working = 1;

do {
x = randval(max_x);
y = randval(max_y);

pval = _getpixel(x,y);

if ((pval != crit_color) && (pval != food_color))
{
_setpixel(x,y);
working = 0;
}

++food_supply;
}
while (working);
}
}

void show_stats(void)
{
char buffer[78];

_settextcolor(crit_color);

sprintf(buffer,"generation: %6ld, critters: %5ld, food: %5ld",
generation, critter_count, food_supply);

_settextposition(24,1);
_outtext(buffer);
}

int cancel(void)
{
if (kbhit())
{
if (!getch()) getch();
return 1;
}

return 0;
}


  3 Responses to “Category : Printer + Display Graphics
Archive   : CRITTER4.ZIP
Filename : CRITTERS.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/