home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / microcrn / issue_49.arc / CRITTERS.ARC / CRITTERS.C next >
C/C++ Source or Header  |  1989-06-02  |  12KB  |  423 lines

  1. /*
  2.     Program:    Critters
  3.     Version:    1.00    02-Jun-1989
  4.     Language:   Microsoft QuickC v2.0
  5.     Purpose:    Simulates simple life forms which evolve
  6.  
  7.     Written by Scott Robert Ladd. No rights reserved.
  8. */
  9.  
  10. #include "graph.h"
  11. #include "stddef.h"
  12. #include "stdio.h"
  13. #include "stdlib.h"
  14. #include "string.h"
  15. #include "conio.h"
  16. #include "time.h"
  17.  
  18.  
  19. /* structure which defines a critter */
  20. struct critter
  21.     {
  22.     int move_gene[4];
  23.     int energy_level;
  24.     int posx;
  25.     int posy;
  26.     long int age;
  27.     struct critter * next;
  28.     struct critter * prev;
  29.     };
  30.  
  31. /* constants which define the program environment */
  32. const int start_crit   =   25; /* initial number of critters */
  33. const int start_food   = 2500; /* initial food supply */
  34.  
  35. const int max_x        =  600; /* maximum x dimension of "world" */
  36. const int max_y        =  300; /*    "    y     "      "    "    */
  37.  
  38. const int max_energy   = 1000; /* max energy a critter can have */
  39. const int max_food     = 4000; /* max amount of food in existence */
  40. const int max_age      =  200; /* max age critter can reach w/o reproducing */
  41. const int max_mutant   =    4; /* max magnitude of a mutation */
  42.  
  43. const int food_value   =   25; /* energy value of a piece of food */
  44. const int move_cost    =    1; /* energy cost for critter to move once */
  45. const int repro_energy =  500; /* minimum energy for a critter to reproduce */
  46. const int repro_age    =  100; /* minimum age for a critter to reproduce */
  47. const int start_energy =  500; /* initial energy level for starting critters */
  48. const int food_growth  =    2; /* amount of food created each generation */
  49.  
  50. /* boolean values for program behavior */
  51. const int old_age_kills = 1; /* true */
  52. const int mutate_parent = 1; /* true */
  53. const int dead_are_food = 0; /* false */
  54.  
  55. /* colors of critters and food */
  56. const short food_color =  7; /* grey */
  57. const short crit_color = 15; /* white */
  58.  
  59. /* movement definition table */
  60. const int delta_table[4][2] = { {0, -3}, {+3, 0,}, {0, +3}, {-3, 0} };
  61.  
  62. /* root and tail of critter linked list */
  63. struct critter * first_critter = NULL;
  64. struct critter * last_critter  = NULL;
  65.  
  66. /* informational display counts */
  67. long int critter_count = 0;
  68. long int food_supply   = 0;
  69. long int generation    = 0;
  70.  
  71. /* macro to get a random value between 1 and x */
  72. #define randval(x) ((rand() % x) + 1)
  73.  
  74. /* function prototypes */
  75. void main(void);       /* program control and logic */
  76. void setup(void);      /* initial set-up of program */
  77. void reproduce(void);  /* critter reproduction/death cycle */
  78. void movement(void);   /* critter motion */
  79. void make_food(void);  /* adds new food to world */
  80. void show_stats(void); /* displays current information on the world */
  81. int  cancel(void);     /* checks for a keyboard entry */
  82.  
  83. void main(void)
  84.     {
  85.     setup();
  86.  
  87.     do  {
  88.         reproduce();
  89.         movement();
  90.         make_food();
  91.         show_stats();
  92.         }
  93.     while (!cancel());
  94.  
  95.     _setvideomode(_DEFAULTMODE);
  96.     }
  97.  
  98. void setup(void)
  99.     {
  100.     int i, j, res, x, y, pval, working;
  101.     unsigned seed;
  102.     struct critter * temp_critter;
  103.  
  104.     /* initialize random number generator */
  105.     seed = (unsigned)time(NULL);
  106.     srand(seed);
  107.  
  108.     /* initialize graphics to EGA 16 color mode */
  109.     res = _setvideomode(_ERESCOLOR);
  110.  
  111.     if (!res)
  112.         {
  113.         _setvideomode(_DEFAULTMODE);
  114.         exit(1);
  115.         }
  116.  
  117.     /* initialize linked list of critters */
  118.     for (i = 0; i < start_crit; ++i)
  119.         {
  120.         temp_critter = malloc(sizeof(struct critter));
  121.  
  122.         if (first_critter == NULL)
  123.             {
  124.             temp_critter->prev = NULL;
  125.             first_critter = temp_critter;
  126.             }
  127.         else
  128.             {
  129.             last_critter->next = temp_critter;
  130.             temp_critter->prev = last_critter;
  131.             }
  132.  
  133.         last_critter = temp_critter;
  134.         temp_critter->next = NULL;
  135.  
  136.         temp_critter->energy_level = start_energy;
  137.  
  138.         for (j = 0; j < 4; ++ j)
  139.             temp_critter->move_gene[j] = j + 1;
  140.  
  141.         temp_critter->posx = randval(max_x);
  142.         temp_critter->posy = randval(max_y);
  143.  
  144.         temp_critter->age = 0;
  145.         }
  146.  
  147.     /* place initial food supply */
  148.     _setcolor(food_color);
  149.  
  150.     for (i = 0; i < start_food; ++i)
  151.         {
  152.         working = 1;
  153.  
  154.         do  {
  155.             x = randval(max_x);
  156.             y = randval(max_y);
  157.  
  158.             pval = _getpixel(x,y);
  159.  
  160.             if (pval != food_color)
  161.                 {
  162.                 _setpixel(x,y);
  163.                 working = 0;
  164.                 }
  165.  
  166.             ++food_supply;
  167.             }
  168.         while (working);
  169.         }
  170.  
  171.     /* set information counts */
  172.     critter_count = start_crit;
  173.     food_supply   = start_food;
  174.     }
  175.  
  176. void reproduce(void)
  177.     {
  178.     int i, x, y;
  179.     struct critter * temp_critter;
  180.     struct critter * new_critter;
  181.  
  182.     ++generation;
  183.  
  184.     temp_critter = first_critter;
  185.  
  186.     while (temp_critter != NULL)
  187.         {
  188.         /* the critter gets older */
  189.         ++temp_critter->age;
  190.  
  191.         /* if critter can reproduce, it does */
  192.         if ((temp_critter->energy_level >= repro_energy)
  193.         && (temp_critter->age >= repro_age))
  194.             {
  195.             /* allocate a new critter */
  196.             new_critter = malloc(sizeof(struct critter));
  197.  
  198.             if (new_critter == NULL)
  199.                 {
  200.                 _setvideomode(_DEFAULTMODE);
  201.                 exit(3);
  202.                 }
  203.  
  204.             /* add new critter to end of critter list */
  205.             new_critter->prev  = last_critter;
  206.             new_critter->next  = NULL;
  207.             last_critter->next = new_critter;
  208.             last_critter       = new_critter;
  209.  
  210.             /* set new energy levels for parent and child */
  211.             temp_critter->energy_level = temp_critter->energy_level / 2;
  212.             new_critter->energy_level  = temp_critter->energy_level;
  213.  
  214.             /* inherit the old genes */
  215.             for (i = 0; i <= 3; ++i)
  216.                  new_critter->move_gene[i] = temp_critter->move_gene[i];
  217.  
  218.             /* select gene which is mutatated! */
  219.             for (i = randval(4) - 1; i <= 3; ++i)
  220.                  new_critter->move_gene[i] += randval(max_mutant);
  221.  
  222.             /* if parent mutates... */
  223.             if (mutate_parent)
  224.                 {
  225.                 for (i = randval(4) - 1; i <= 3; ++i)
  226.                      temp_critter->move_gene[i] += randval(max_mutant);
  227.                 }
  228.  
  229.  
  230.             /* put the new critter in the same place as its parent */
  231.             new_critter->posx = temp_critter->posx;
  232.             new_critter->posy = temp_critter->posy;
  233.  
  234.             ++critter_count;
  235.  
  236.             new_critter->age  = 0;
  237.             temp_critter->age = 0;
  238.             }
  239.         /* check to see if the critter dies */
  240.         else if ((temp_critter->energy_level == 0)
  241.              || ((old_age_kills) && (temp_critter->age > max_age)))
  242.             {
  243.             --critter_count;
  244.  
  245.             /* if all critters have died, end the program */
  246.             if (critter_count <= 0)
  247.                 {
  248.                 show_stats();
  249.  
  250.                 while (!cancel())
  251.                     /* empty */ ;
  252.  
  253.                 _setvideomode(_DEFAULTMODE);
  254.  
  255.                 exit(2);
  256.                 }
  257.  
  258.             /* delete character from linked list */
  259.             if (temp_critter->prev == NULL)
  260.                 {
  261.                 first_critter = temp_critter->next;
  262.                 first_critter->prev = NULL;
  263.                 }
  264.             else if (temp_critter->next == NULL)
  265.                 {
  266.                 last_critter = temp_critter->prev;
  267.                 last_critter->next = NULL;
  268.                 }
  269.             else
  270.                 {
  271.                 temp_critter->prev->next = temp_critter->next;
  272.                 temp_critter->next->prev = temp_critter->prev;
  273.                 }
  274.  
  275.             /* remove body of dead critter */
  276.             for (x = temp_critter->posx - 1; x <= temp_critter->posx + 1; ++x)
  277.                 {
  278.                 for (y = temp_critter->posy - 1; y <= temp_critter->posy + 1; ++y)
  279.                     {
  280.                     if (dead_are_food)
  281.                         _setcolor(food_color);
  282.                     else
  283.                         _setcolor(0);
  284.  
  285.                     _setpixel(x,y);
  286.                     }
  287.                 }
  288.  
  289.             if (dead_are_food)
  290.                 food_supply += 9;
  291.  
  292.             free(temp_critter);
  293.             }
  294.  
  295.         temp_critter = temp_critter->next;
  296.         }
  297.     }
  298.  
  299. void movement(void)
  300.     {
  301.     int i, x, y;
  302.     int pval, move;
  303.     struct critter * temp_critter;
  304.  
  305.     temp_critter = first_critter;
  306.  
  307.     while (temp_critter != NULL)
  308.         {
  309.         /* erase critter from old position */
  310.         for (x = temp_critter->posx - 1; x <= temp_critter->posx + 1; ++x)
  311.             {
  312.             for (y = temp_critter->posy - 1; y <= temp_critter->posy + 1; ++y)
  313.                 {
  314.                 _setcolor(0);
  315.                 _setpixel(x,y);
  316.                 }
  317.             }
  318.  
  319.         /* select movement */
  320.         move = randval(temp_critter->move_gene[3]);
  321.  
  322.         for (i = 0; move > temp_critter->move_gene[i]; ++i)
  323.             /*empty*/;
  324.  
  325.         /* adjust critters position */
  326.         temp_critter->posx += delta_table[i][0];
  327.         temp_critter->posy += delta_table[i][1];
  328.  
  329.         /* wrap around the edges of the world if needed */
  330.         if (temp_critter->posx < 1)
  331.             temp_critter->posx = max_x;
  332.  
  333.         if (temp_critter->posy < 1)
  334.             temp_critter->posy = max_y;
  335.  
  336.         if (temp_critter->posx > max_x)
  337.             temp_critter->posx = 1;
  338.  
  339.         if (temp_critter->posy > max_y)
  340.             temp_critter->posy = 1;
  341.  
  342.         /* assess movement cost */
  343.         temp_critter->energy_level -= move_cost;
  344.  
  345.         /* redraw critter at new position */
  346.         for (x = temp_critter->posx - 1; x <= temp_critter->posx + 1; ++x)
  347.             {
  348.             for (y = temp_critter->posy - 1; y <= temp_critter->posy + 1; ++y)
  349.                 {
  350.                 _setcolor(crit_color);
  351.                 pval = _setpixel(x,y);
  352.  
  353.                 /* if pixel covered is a food particle, consume it! */
  354.                 if (pval == food_color)
  355.                     {
  356.                     if (temp_critter->energy_level < max_energy)
  357.                         temp_critter->energy_level += food_value;
  358.  
  359.                     --food_supply;
  360.                     }
  361.                 }
  362.             }
  363.  
  364.         temp_critter = temp_critter->next;
  365.         }
  366.     }
  367.  
  368. void make_food(void)
  369.     {
  370.     int i, x, y, pval, working;
  371.  
  372.     if (food_supply >= max_food)
  373.         return;
  374.  
  375.     _setcolor(food_color);
  376.  
  377.     /* drop pieces of food in blank spots */
  378.     for (i = 0; i < food_growth; ++i)
  379.         {
  380.         working = 1;
  381.  
  382.         do  {
  383.             x = randval(max_x);
  384.             y = randval(max_y);
  385.  
  386.             pval = _getpixel(x,y);
  387.  
  388.             if ((pval != crit_color) && (pval != food_color))
  389.                 {
  390.                 _setpixel(x,y);
  391.                 working = 0;
  392.                 }
  393.  
  394.             ++food_supply;
  395.             }
  396.         while (working);
  397.         }
  398.     }
  399.  
  400. void show_stats(void)
  401.     {
  402.     char buffer[78];
  403.  
  404.     _settextcolor(crit_color);
  405.  
  406.     sprintf(buffer,"generation: %6ld, critters: %5ld, food: %5ld",
  407.         generation, critter_count, food_supply);
  408.  
  409.     _settextposition(24,1);
  410.     _outtext(buffer);
  411.     }
  412.  
  413. int cancel(void)
  414.     {
  415.     if (kbhit())
  416.         {
  417.         if (!getch()) getch();
  418.         return 1;
  419.         }
  420.  
  421.     return 0;
  422.     }
  423.