home *** CD-ROM | disk | FTP | other *** search
/ Teach Yourself Game Programming in 21 Days / TYGAMES_R.ISO / source / day_10 / antsrus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-23  |  17.9 KB  |  683 lines

  1.  
  2. // I N C L U D E S ///////////////////////////////////////////////////////////
  3.  
  4. #include <io.h>
  5. #include <conio.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <dos.h>
  9. #include <bios.h>
  10. #include <fcntl.h>
  11. #include <memory.h>
  12. #include <malloc.h>
  13. #include <math.h>
  14. #include <string.h>
  15.  
  16. #include "graph3.h"  // include our graphics stuff
  17. #include "graph4.h"
  18. #include "graph6.h"
  19.  
  20. // D E F I N E S /////////////////////////////////////////////////////////////
  21.  
  22. #define CELL_WIDTH       20   // size of bitmaps in world
  23. #define CELL_HEIGHT      20
  24.  
  25. #define NUM_ROWS         10   // number of rows and columns in terrain
  26. #define NUM_COLUMNS      16
  27.  
  28. #define NUM_ANTS         20   // this should be enough (has to be multiple of 2)
  29.  
  30. #define NUM_PATTERNS      3   // there are 3 patterns
  31. #define PATTERN_LENGTH   25   // at most patterns have 25 elements in them
  32.  
  33. // direction of ant
  34.  
  35. #define ANT_UP      0
  36. #define ANT_DOWN    2
  37. #define ANT_RIGHT   4
  38. #define ANT_LEFT    6
  39.  
  40. // state of ants
  41.  
  42. #define ANT_MARCH   0
  43. #define ANT_RANDOM  1
  44. #define ANT_PATTERN 2
  45. #define ANT_SITTING 3
  46.  
  47. // S T R U C T U R E S ///////////////////////////////////////////////////////
  48.  
  49. typedef struct ant_typ
  50.         {
  51.         int dir;      // direction of ant
  52.         int state;    // state of ant
  53.         int count_1;  // counter one
  54.         int count_2;  // counter two
  55.         int max_1;    // maximum count for counter 1
  56.         int max_2;    // maximum count for counter 2
  57.         int index_1;  // general index
  58.         int index_2;  // general index
  59.  
  60.         } ant, *ant_ptr;
  61.  
  62. // G L O B A L S  ////////////////////////////////////////////////////////////
  63.  
  64. pcx_picture imagery_pcx,      // the game imagery
  65.             background_pcx;   // the backdrop
  66.  
  67. // the sprites used in the game
  68.  
  69. sprite ants[NUM_ANTS],        // the ant sprites
  70.        rock;                  // the "rock" sprite
  71.  
  72. ant ant_data[NUM_ANTS];       // the ant data structures
  73.  
  74.  
  75. // this array is a probability density of the different states
  76.  
  77. int ant_personality[10] = {
  78.                           ANT_MARCH,   // 60% of the time march up and down
  79.                           ANT_MARCH,
  80.                           ANT_MARCH,
  81.                           ANT_MARCH,
  82.                           ANT_MARCH,
  83.                           ANT_MARCH,
  84.                           ANT_RANDOM,  // 10% of the time random
  85.                           ANT_PATTERN, // 20% of the time try a pattern
  86.                           ANT_PATTERN,
  87.                           ANT_SITTING  // 10% of the time ant will sit
  88.                           };
  89.  
  90. int terrain[NUM_ROWS][NUM_COLUMNS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  91.                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  92.                                       1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
  93.                                       0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,
  94.                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  95.                                       0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,
  96.                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  97.                                       0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,
  98.                                       0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  99.                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
  100.  
  101. int ant_patterns[NUM_PATTERNS][PATTERN_LENGTH]=
  102.  
  103. { 0,0,0,4,4,4,2,2,2,6,6,6,2,2,2,0,0,4,2,6,0,-1,0,0,0,
  104.   2,2,2,6,6,0,0,4,4,4,4,4,2,6,0,6,2,2,4,0,6,2,4,-1,0,
  105.   4,4,4,4,4,0,6,6,6,6,6,6,6,2,4,0,6,2,2,2,6,0,2,4,-1};
  106.  
  107. // F U N C T I O N S //////////////////////////////////////////////////////////
  108.  
  109. void Draw_Ants(void)
  110. {
  111. // this function draws all the ants
  112.  
  113. int index;
  114.  
  115. for (index=0; index<NUM_ANTS; index++)
  116.     Draw_Sprite_DB((sprite_ptr)&ants[index]);
  117.  
  118. } // end Draw_Ants
  119.  
  120. ///////////////////////////////////////////////////////////////////////////////
  121.  
  122. void Erase_Ants(void)
  123. {
  124. // this function erases all the ants
  125.  
  126. int index;
  127.  
  128. // loop through and process all ants
  129.  
  130. for (index=0; index<NUM_ANTS; index++)
  131.     Erase_Sprite_DB((sprite_ptr)&ants[index]);
  132.  
  133. } // end Erase_Ants
  134.  
  135. ///////////////////////////////////////////////////////////////////////////////
  136.  
  137. void Behind_Ants(void)
  138. {
  139. // this function scans behind all the ants
  140.  
  141. int index;
  142.  
  143. // loop through and process all ants
  144.  
  145. for (index=0; index<NUM_ANTS; index++)
  146.     Behind_Sprite_DB((sprite_ptr)&ants[index]);
  147.  
  148. } // end Behind_Ants
  149.  
  150. ///////////////////////////////////////////////////////////////////////////////
  151.  
  152. void Init_Ants(void)
  153. {
  154. // this function initializes all the ants and places them in two
  155. // columns on the screen and sets them all to march
  156.  
  157. int index;
  158.  
  159. // loop through and process all ants
  160.  
  161. // first the up ants
  162.  
  163. for (index=0; index<(NUM_ANTS/2); index++)
  164.     {
  165.  
  166.     // set up fields in data structure
  167.  
  168.     ant_data[index].dir      = ANT_UP;
  169.     ant_data[index].state    = ANT_MARCH;
  170.     ant_data[index].count_1  = 0;
  171.     ant_data[index].count_2  = 0;
  172.     ant_data[index].max_1    = 100 + rand()%100;
  173.     ant_data[index].max_2    = 0;
  174.     ant_data[index].index_1  = 0;
  175.     ant_data[index].index_2  = 0;
  176.  
  177.     // set up fields in sprite structure
  178.  
  179.     ants[index].curr_frame   = ANT_UP;
  180.     ants[index].x            = 165 + rand()%10;
  181.     ants[index].y            = index*CELL_HEIGHT;
  182.  
  183.     } // end for index
  184.  
  185. // now the down
  186.  
  187. for (index=(NUM_ANTS/2); index<NUM_ANTS; index++)
  188.     {
  189.  
  190.     // set up fields in data structure
  191.  
  192.     ant_data[index].dir      = ANT_DOWN;
  193.     ant_data[index].state    = ANT_MARCH;
  194.     ant_data[index].count_1  = 0;
  195.     ant_data[index].count_2  = 0;
  196.     ant_data[index].max_1    = 100 + rand()%100;
  197.     ant_data[index].max_2    = 0;
  198.     ant_data[index].index_1  = 0;
  199.     ant_data[index].index_2  = 0;
  200.  
  201.     // set up fields in sprite structure
  202.  
  203.     ants[index].curr_frame   = ANT_DOWN;
  204.     ants[index].x            = 180 + rand()%10;
  205.     ants[index].y            = (index-(NUM_ANTS/2))*CELL_HEIGHT;
  206.  
  207.     } // end for index
  208.  
  209.  
  210. } // end Init_Ants
  211.  
  212. /////////////////////////////////////////////////////////////////////////////
  213.  
  214. void Draw_Rocks(void)
  215. {
  216. // based on terrain array place a rock on screen wherever there is a "1"
  217.  
  218. int x,y;
  219.  
  220. // loop through draw and draw rocks
  221.  
  222. for (y=0; y<NUM_ROWS; y++)
  223.     {
  224.  
  225.     for (x=0; x<NUM_COLUMNS; x++)
  226.         {
  227.  
  228.         // is there a rock here
  229.  
  230.         if (terrain[y][x]==1)
  231.            {
  232.            // postion rock sprite
  233.  
  234.            rock.x = x*CELL_WIDTH;
  235.            rock.y = y*CELL_HEIGHT;
  236.  
  237.            Draw_Sprite_DB((sprite_ptr)&rock);
  238.  
  239.            } // end if
  240.  
  241.         } // end for x
  242.  
  243.     } // end for y
  244.  
  245. } // end Draw_Rocks
  246.  
  247. // M A I N ////////////////////////////////////////////////////////////////////
  248.  
  249. void main(void)
  250. {
  251. // this is the main function
  252.  
  253. int done=0,         // exit flag for whole system
  254.     index,          // loop index
  255.     change_state,   // used to flag when a ant should change state
  256.     new_dir,        // local AI variable
  257.     cell_x,cell_y;  // used to compute what cell ant is in for rock collision
  258.  
  259.  
  260. // SECTION 1 /////////////////////////////////////////////////////////////////
  261.  
  262. // set video mode to 320x200 256 color mode
  263.  
  264. Set_Video_Mode(VGA256);
  265.  
  266. // create a double buffer
  267.  
  268. if (!Create_Double_Buffer(SCREEN_HEIGHT))
  269.    {
  270.    printf("\nNot enough memory to create double buffer.");
  271.  
  272.    } // end if
  273.  
  274. // clear the double buffer
  275.  
  276. Fill_Double_Buffer(0);
  277.  
  278. // load in the background image into the double buffer
  279.  
  280. PCX_Init((pcx_picture_ptr)&background_pcx);
  281.  
  282. PCX_Load("antbak.pcx", (pcx_picture_ptr)&background_pcx,1);
  283.  
  284. // copy the background into the double buffer
  285.  
  286. _fmemcpy((char far *)double_buffer,
  287.          (char far *)(background_pcx.buffer),
  288.          SCREEN_WIDTH*SCREEN_HEIGHT);
  289.  
  290. PCX_Delete((pcx_picture_ptr)&background_pcx);
  291.  
  292. Blit_String_DB(2,2,10,"Press any key to exit.",1);
  293.  
  294. // SECTION 2 /////////////////////////////////////////////////////////////////
  295.  
  296. // load in imagery for the ants
  297.  
  298. PCX_Init((pcx_picture_ptr)&imagery_pcx);
  299.  
  300. PCX_Load("antimg.pcx", (pcx_picture_ptr)&imagery_pcx,1);
  301.  
  302. // initialize player and extract bitmaps
  303.  
  304. sprite_width  = 20;
  305. sprite_height = 20;
  306.  
  307. // create all the ants...we have a long way to create the Genesis bomb.
  308. // but I'm on the job!
  309.  
  310. for (index=0; index<NUM_ANTS; index++)
  311.     {
  312.     // initialize the ant sprite
  313.  
  314.     Sprite_Init((sprite_ptr)&ants[index],0,0,0,0,0,0);
  315.  
  316.     // load the bitmaps
  317.  
  318.     PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,
  319.                     (sprite_ptr)&ants[index],0,0,0);
  320.  
  321.     PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,
  322.                     (sprite_ptr)&ants[index],1,1,0);
  323.  
  324.     PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,
  325.                     (sprite_ptr)&ants[index],2,2,0);
  326.  
  327.     PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,
  328.                     (sprite_ptr)&ants[index],3,3,0);
  329.  
  330.     PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,
  331.                     (sprite_ptr)&ants[index],4,4,0);
  332.  
  333.     PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,
  334.                     (sprite_ptr)&ants[index],5,5,0);
  335.  
  336.     PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,
  337.                     (sprite_ptr)&ants[index],6,6,0);
  338.  
  339.     PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,
  340.                     (sprite_ptr)&ants[index],7,7,0);
  341.  
  342.     // initialize the ant vars
  343.  
  344.     ants[index].curr_frame = 0;
  345.     ants[index].state      = 1;
  346.  
  347.     } // end for index
  348.  
  349. // load up the rock
  350.  
  351. Sprite_Init((sprite_ptr)&rock,0,0,0,0,0,0);
  352.  
  353. PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,
  354.                 (sprite_ptr)&rock,0,0,1);
  355.  
  356. rock.curr_frame = 0;
  357. rock.state      = 1;  // alive or dead, it's not doing much!
  358.  
  359.  
  360. // SECTION 3 /////////////////////////////////////////////////////////////////
  361.  
  362. // draw all the rocks
  363.  
  364. Draw_Rocks();
  365.  
  366. // initialize the ants
  367.  
  368. Init_Ants();
  369.  
  370. // scan background once before loop
  371.  
  372. Behind_Ants();
  373.  
  374. // SECTION 4 /////////////////////////////////////////////////////////////////
  375.  
  376. // main event loop
  377.  
  378. while(!kbhit())
  379.      {
  380.  
  381.      // erase all objects
  382.  
  383.      Erase_Ants();
  384.  
  385. // SECTION 5 /////////////////////////////////////////////////////////////////
  386.  
  387.      // BEGIN AI LOGIC  //
  388.  
  389.      // at this point we want to move all the ants, change stats, etc.
  390.  
  391.      for (index=0; index<NUM_ANTS; index++)
  392.          {
  393.  
  394.          // reset state change flag
  395.  
  396.          change_state = 0;
  397.  
  398.          // what state is ant in ?
  399.  
  400.          switch(ant_data[index].state)
  401.                {
  402.  
  403.                case ANT_MARCH:
  404.                   {
  405.  
  406.                   // test if it's time to change state
  407.  
  408.                   if (++ant_data[index].count_1 == ant_data[index].max_1)
  409.                      change_state = 1;
  410.  
  411.                   } break;
  412.  
  413.                case ANT_RANDOM:
  414.                   {
  415.                   // select a new direction for ant
  416.  
  417.                   ant_data[index].dir      = 2*(rand()%4);
  418.                   ant_data[index].state    = ANT_MARCH;
  419.                   ant_data[index].count_1  = 0;
  420.                   ant_data[index].max_1    = 50 + rand()%50;
  421.  
  422.                   // set up fields in sprite structure
  423.  
  424.                   ants[index].curr_frame   = ant_data[index].dir;
  425.  
  426.                   } break;
  427.  
  428.                case ANT_PATTERN:
  429.                   {
  430.                   // test if it's time to use next pattern element
  431.  
  432.                   if (++ant_data[index].count_1 == ant_data[index].max_1)
  433.                      {
  434.                      // reset counter
  435.  
  436.                      ant_data[index].count_1 = 0;
  437.  
  438.                      // move to next element of pattern
  439.  
  440.                      ant_data[index].index_2++;
  441.  
  442.                      new_dir =
  443.                      ant_patterns[ant_data[index].index_1][ant_data[index].index_2];
  444.  
  445.                      if (new_dir!=-1)
  446.                         {
  447.  
  448.                         // change direction of ant
  449.  
  450.                         ant_data[index].dir =  ants[index].curr_frame = new_dir;
  451.  
  452.                         } // end if not done with pattern
  453.                      else
  454.                         {
  455.  
  456.                         change_state = 1;
  457.  
  458.                         } // end else pattern is dead
  459.  
  460.                      } // end if time to change pattern element
  461.  
  462.                   } break;
  463.  
  464.                case ANT_SITTING:
  465.                   {
  466.  
  467.                   // test if it's time to change state
  468.  
  469.                   if (++ant_data[index].count_1 == ant_data[index].max_1)
  470.                      change_state = 1;
  471.  
  472.                   } break;
  473.  
  474.                default:break;
  475.  
  476.                } // end switch
  477.  
  478. // SECTION 6 /////////////////////////////////////////////////////////////////
  479.  
  480.  
  481.          // check if there has been a state change
  482.  
  483.          if (change_state)
  484.             {
  485.  
  486.             // use personality table to select a new state
  487.  
  488.             ant_data[index].state = ant_personality[rand()%10];
  489.  
  490.             // based on new state set up ant appropriately(if needed)
  491.  
  492.             switch(ant_data[index].state)
  493.                   {
  494.  
  495.                   case ANT_MARCH:
  496.                      {
  497.                      // select up or down
  498.  
  499.                      ant_data[index].dir      = 2*(rand()%2);
  500.                      ant_data[index].state    = ANT_MARCH;
  501.                      ant_data[index].count_1  = 0;
  502.                      ant_data[index].max_1    = 100 + rand()%75;
  503.  
  504.                      // set up current frame
  505.  
  506.                      ants[index].curr_frame   = ant_data[index].dir;
  507.  
  508.                      } break;
  509.  
  510.                   case ANT_PATTERN:
  511.                      {
  512.  
  513.                      // select the pattern and set a pointer to first element
  514.  
  515.                      ant_data[index].index_1 = rand()%NUM_PATTERNS;
  516.                      ant_data[index].index_2 = 0;
  517.  
  518.                      // this time, these two variables will be used to count
  519.                      // how long to play each pattern instruction
  520.  
  521.                      ant_data[index].count_1  = 0;
  522.                      ant_data[index].max_1    = 2 + rand()%3;
  523.  
  524.                      // based on the first pattern element set initial direction
  525.  
  526.                      ant_data[index].dir =
  527.                            ant_patterns[ant_data[index].index_1][0];
  528.  
  529.                      ants[index].curr_frame = ant_data[index].dir;
  530.  
  531.                      } break;
  532.  
  533.                   case ANT_RANDOM:
  534.                      {
  535.  
  536.                      ant_data[index].state    = ANT_RANDOM;
  537.  
  538.                      // do nothing, the logic will take care of it above
  539.  
  540.                      } // break;
  541.  
  542.                   case ANT_SITTING:
  543.                      {
  544.  
  545.                      ant_data[index].state    = ANT_SITTING;
  546.                      ant_data[index].count_1  = 0;
  547.                      ant_data[index].max_1    = 10 + rand()%10;
  548.  
  549.                      } // break;
  550.  
  551.                   } // end switch state;
  552.  
  553.             } // end if we need to move to another state
  554.  
  555. // SECTION 7 /////////////////////////////////////////////////////////////////
  556.  
  557.  
  558.          // check if ant has bumped into a rock, if so set state to
  559.          // random
  560.  
  561.          // obtain cell location of ant using center of ant as reference
  562.  
  563.          cell_x = (ants[index].x+10)/CELL_WIDTH;
  564.          cell_y = (ants[index].y+10)/CELL_HEIGHT;
  565.  
  566.          // test if there is a rock there
  567.  
  568.          if (terrain[cell_y][cell_x]==1)
  569.             {
  570.             // set state of ant to random
  571.  
  572.             ant_data[index].dir      = 2*(rand()%4);
  573.             ant_data[index].state    = ANT_MARCH;
  574.             ant_data[index].count_1  = 0;
  575.             ant_data[index].max_1    = 50 + rand()%50;
  576.             ants[index].curr_frame   = ant_data[index].dir;
  577.  
  578.             change_state = 0;
  579.  
  580.             } // end if ant hit a rock
  581.  
  582. // SECTION 8 /////////////////////////////////////////////////////////////////
  583.  
  584.          // now matter what state ant is in we should move it in the direction
  585.          // it is pointing, unless it is sitting
  586.  
  587.          // don't move ant if it is sitting
  588.  
  589.          if (ant_data[index].state!=ANT_SITTING)
  590.          {
  591.          // based on direction move the ant
  592.  
  593.          switch(ant_data[index].dir)
  594.                {
  595.  
  596.                case ANT_RIGHT:
  597.                   {
  598.                   ants[index].x+=4;
  599.                   } break;
  600.  
  601.                case ANT_LEFT:
  602.                   {
  603.                   ants[index].x-=4;
  604.                   } break;
  605.  
  606.                case ANT_UP:
  607.                   {
  608.                   ants[index].y-=4;
  609.                   } break;
  610.  
  611.                case ANT_DOWN:
  612.                   {
  613.                   ants[index].y+=4;
  614.                   } break;
  615.  
  616.                default:break;
  617.  
  618.                } // end switch direction
  619.  
  620. // SECTION 9 /////////////////////////////////////////////////////////////////
  621.  
  622.  
  623.         // change animation frame using a toggle
  624.  
  625.         if ((ants[index].curr_frame % 2)==0)
  626.             ants[index].curr_frame++;
  627.         else
  628.             ants[index].curr_frame--;
  629.  
  630.         // boundary detection
  631.  
  632.         if (ants[index].x > 300)
  633.             ants[index].x = 0;
  634.         else
  635.         if (ants[index].x < 0)
  636.             ants[index].x = 300;
  637.  
  638.         if (ants[index].y > 180)
  639.             ants[index].y = 0;
  640.         else
  641.         if (ants[index].y < 0)
  642.             ants[index].y = 180;
  643.  
  644.         } // end if ant wasn't sitting
  645.  
  646.         } // end for index
  647.  
  648.      // END AI LOGIC    //
  649.  
  650. // SECTION 10 ///////////////////////////////////////////////////////////////
  651.  
  652.      // scan background under objects
  653.  
  654.      Behind_Ants();
  655.  
  656.      // draw all the imagery
  657.  
  658.      Draw_Ants();
  659.  
  660.      // copy the double buffer to the screen
  661.  
  662.      Show_Double_Buffer(double_buffer);
  663.  
  664.      // wait a sec
  665.  
  666.      Delay(1);
  667.  
  668.      } // end while
  669.  
  670. // SECTION 11 ///////////////////////////////////////////////////////////////
  671.  
  672. // reset the video mode back to text
  673.  
  674. Set_Video_Mode(TEXT_MODE);
  675.  
  676. // free the double buffer
  677.  
  678. Delete_Double_Buffer();
  679.  
  680. } // end main
  681.  
  682.  
  683.