home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / Source / GPCHAP18 / UNDERWLD.CPP < prev    next >
C/C++ Source or Header  |  2002-05-01  |  234KB  |  7,467 lines

  1. // UNDERWLD.CPP -  The final game
  2. // remember to compile you need GPDUMB1.CPP, GPDUMB2.CPP and
  3. // DirectX libraries DDRAW.LIB, DSOUND.LIB, DINPUT.LIB, DINPUT8.LIB and
  4. // WINMM.LIB
  5.  
  6. // INCLUDES ///////////////////////////////////////////////
  7.  
  8. #define WIN32_LEAN_AND_MEAN  
  9. #define INITGUID
  10.  
  11. #include <windows.h>   // include important windows stuff
  12. #include <windowsx.h> 
  13. #include <mmsystem.h>
  14. #include <iostream.h> // include important C/C++ stuff
  15. #include <conio.h>
  16. #include <stdlib.h>
  17. #include <malloc.h>
  18. #include <memory.h>
  19. #include <string.h>
  20. #include <stdarg.h>
  21. #include <stdio.h> 
  22. #include <math.h>
  23. #include <io.h>
  24. #include <fcntl.h>
  25.  
  26. #include <ddraw.h>  // directX includes
  27. #include <dsound.h>
  28. #include <dinput.h>
  29. #include "gpdumb1.h" // game library includes
  30. #include "gpdumb2.h"
  31.  
  32. //#include "mono.h"
  33.  
  34. // DEFINES ////////////////////////////////////////////////
  35.  
  36. // defines for windows 
  37. #define WINDOW_CLASS_NAME "WINXCLASS"  // class name
  38.  
  39. #define WINDOW_WIDTH    64   // size of window
  40. #define WINDOW_HEIGHT   48
  41.  
  42. // defines for font
  43. #define FONT_NUM_CHARS  96  // entire character set
  44. #define FONT_WIDTH      16
  45. #define FONT_HEIGHT     16
  46. #define FONT_WIDTH_NEXT_NUM    12
  47. #define FONT_WIDTH_NEXT_LOWER  12 
  48. #define FONT_WIDTH_NEXT_UPPER  12
  49.  
  50. // demo object position
  51. #define DUG_DEMO_X    188
  52. #define DUG_DEMO_Y    352
  53.  
  54. #define POO_DEMO_X    188
  55. #define POO_DEMO_Y    234
  56.  
  57. #define PUFF_DEMO_X   188
  58. #define PUFF_DEMO_Y   190
  59.  
  60. // defines for high score bitmaps
  61. #define NUM_SCORES                   16
  62. #define SCORE_DISPLAY_COUNT          50
  63. #define SCORE_OFF                    0
  64. #define SCORE_ON                     1
  65.  
  66. // defines for grappling pumps
  67. #define NUM_GPUMPS                   8
  68.  
  69. #define GPUMP_INJECTION              50 // pressure of a single gpump
  70.  
  71. #define GPUMP_STATE_DEAD             0
  72. #define GPUMP_STATE_MOVING           1
  73. #define GPUMP_STATE_ATTACHED         2 
  74. #define GPUMP_SPEED                  6
  75.  
  76. // defines for fireballs
  77. #define NUM_FBALLS                   8
  78. #define NUM_FBLASTS                  3
  79.  
  80. #define FBALL_STATE_DEAD             0
  81. #define FBALL_STATE_EXPLODING        1
  82. #define FBALL_STATE_MOVING           2 
  83.  
  84. #define FBALL_SPEED                  4
  85.  
  86. #define FBALL_TYPE_RED               0
  87. #define FBALL_TYPE_GREEN             1
  88.  
  89. #define FBALL_ANIM_RED_FLY           0
  90. #define FBALL_ANIM_RED_EXPLODE       1
  91. #define FBALL_ANIM_GREEN_FLY         2
  92. #define FBALL_ANIM_GREEN_EXPLODE     3
  93.  
  94. // defines for rocks
  95. #define ROCK_STATE_DEAD              0
  96. #define ROCK_STATE_STABLE            1
  97. #define ROCK_STATE_SHAKING           2 
  98. #define ROCK_STATE_FALLING           3
  99. #define ROCK_STATE_CRUMBLING         4
  100. #define ROCK_COUNT_SHAKE             30
  101. #define NUM_ROCKS                    16   // maximum number of rocks in simulation
  102. #define ROCK_INIT_VELOCITY           4    // initial velocity
  103. #define ROCK_GRAVITY                 0.25 // gravity field
  104. #define ROCKS_DROP_FOR_PRIZE         2    // rocks that need to be dropped per level for prize
  105.  
  106. // defines for prizes
  107. #define NUM_PRIZES         9
  108. #define PRIZE_X_POS        320
  109. #define PRIZE_Y_POS        200
  110. #define PRIZE_DISPLAY_TIME 375
  111. #define PRIZE_STATE_OFF    0
  112. #define PRIZE_STATE_ON     1
  113.  
  114. #define POINTS_NEW_MAN   35000
  115.  
  116. // defines for level loading
  117. #define MAX_LEVELS            64
  118. #define LEVEL_COLUMNS         16
  119. #define LEVEL_ROWS            10
  120. #define STARTING_LEVEL_NUMBER 0 // starting level of game
  121.  
  122. // possible data id values in level data
  123. #define OBJECT_ID_ROCK      'r'
  124. #define OBJECT_ID_PUFF      'd'
  125. #define OBJECT_ID_POO       'p'
  126. #define OBJECT_ID_VHOLE     'v'
  127. #define OBJECT_ID_HHOLE     'h'
  128.  
  129. // defines for score rendering
  130. #define SCORE_X                  32
  131. #define SCORE_Y                  2
  132. #define SCORE_COLOR_BOLD         10
  133. #define SCORE_COLOR_TEXT         15
  134.  
  135. // defines for mushrooms
  136. #define MUSH_START_X             (SCREEN_WIDTH - 32)
  137. #define MUSH_START_Y             34
  138.  
  139. // defines for small dugs
  140. #define DUG_LIVES_X              8
  141. #define DUG_LIVES_Y              (SCREEN_HEIGHT - 16)
  142.  
  143. // defines for prizes
  144. #define NUM_PRIZES               9
  145.  
  146. // defines for important colors
  147. #define COLOR_INDEX_HOLE           224  // color index for hole
  148.  
  149. // defines for holes
  150. #define NUM_HOLE_BITMAPS           10
  151. #define HOLE_INDEX_H               8    
  152. #define HOLE_INDEX_V               9
  153.  
  154. // defines for poo's
  155. #define NUM_POOS                   16  // max num of poos available
  156. #define POO_SPEED                  2   // starting speed of all poos
  157. #define POO_EXPLORE_TIME           500 // amount of time to explore
  158. #define POO_BOUNCES_PREMPT         3   // number of bounces before a preempt from 
  159.                                        // explore to chase
  160.  
  161. #define POO_STATE_DEAD             0  // the poo is dead
  162. #define POO_STATE_ALIVE            1  // the poo is alive
  163. #define POO_STATE_INFLATING        2  // the poo is inflating (immobile)
  164. #define POO_STATE_DYING            3  // dying in some manner
  165.  
  166. // anim states
  167. #define POO_ANIM_STATE_BOUNCE      0 // the poo is bouncing like normal
  168. #define POO_ANIM_STATE_CRUSHED     1 // the poo is being crushed by a rock
  169. #define POO_ANIM_STATE_BURROW      2 // the poo is burrowing
  170. #define POO_ANIM_STATE_INFLATING   3 // the poo is being inflated
  171.  
  172. // poo animations
  173. #define POO_ANIM_BOUNCE_LEFT       0 // bouncing left animation index
  174. #define POO_ANIM_BOUNCE_RIGHT      1 // bouncing right animation index
  175. #define POO_ANIM_CRUSH_LEFT        2 // getting crushed facing left
  176. #define POO_ANIM_CRUSH_RIGHT       3 // getting grushed facing right
  177. #define POO_ANIM_BURROW            4 // poo is burrowing
  178.  
  179. // ai states
  180. #define POO_AI_STATE_STOP          0  // the poo is stopped and thinking
  181. #define POO_AI_STATE_EXPLORE       1  // the pos is just exploring
  182. #define POO_AI_STATE_CHASE         2  // the poo chasing the player    
  183. #define POO_AI_STATE_EVADE         3  // the poo is evading the player
  184. #define POO_AI_STATE_BURROW        4  // the poo is burrowing
  185. #define POO_AI_STATE_CRUSHED       5  // the poo is being crushed
  186. #define POO_AI_STATE_INFLATING     6  // the poo is being inflated
  187. #define POO_AI_STATE_POPPED        7  // the poo has finally popped
  188.  
  189. // variable indices
  190. #define POO_INDEX_AI_STATE         0  // the mode of the ai
  191. #define POO_INDEX_ANIM_STATE       1  // the state of the animation
  192. #define POO_INDEX_ANIM_DIR         2  // the direction of animation left or right
  193. #define POO_INDEX_CURR_DIR         3  // the actual nautical direction
  194. #define POO_INDEX_LAST_DIR         4  // the last actual nautical direction
  195. #define POO_INDEX_DESIRED_DIR      5  // the desired nautical direction
  196. #define POO_INDEX_2ND_DESIRED_DIR  6  // the secondary desired nautical direction
  197. #define POO_INDEX_PSI_COUNT        7  // used in inflation algorithm
  198. #define POO_INDEX_EXPLORE_COUNTER  8  // used to track how long poo in explore mode
  199.  
  200. // tracking for bouncing              
  201. #define POO_INDEX_SUM_X             9 // number of x direction bounces 
  202. #define POO_INDEX_SUM_Y            10 // number of y direction bounces
  203. #define POO_INDEX_BOUNCE_MAX       11 // general counter
  204. #define POO_INDEX_OBJECT_PTR       12 // general reference ptr                 
  205.                      
  206. // used to reset level
  207. #define POO_INDEX_SAVED_X          13
  208. #define POO_INDEX_SAVED_Y          14 
  209. #define POO_INDEX_SAVED_DIR        15
  210.  
  211. // defines for PUFF's
  212. #define NUM_PUFFS                   16  // max num of PUFFs available
  213. #define PUFF_SPEED                  2   // starting speed of all PUFFs
  214. #define PUFF_EXPLORE_TIME           400 // amount of time to explore
  215.  
  216. #define PUFF_STATE_DEAD             0  // the PUFF is dead
  217. #define PUFF_STATE_ALIVE            1  // the PUFF is alive
  218. #define PUFF_STATE_INFLATING        2  // the PUFF is inflating (immobile)
  219. #define PUFF_STATE_DYING            3  // dying in some manner
  220.  
  221. // anim states
  222. #define PUFF_ANIM_STATE_BOUNCE      0 // the PUFF is bouncing like normal
  223. #define PUFF_ANIM_STATE_CRUSHED     1 // the PUFF is being crushed by a rock
  224. #define PUFF_ANIM_STATE_BURROW      2 // the PUFF is burrowing
  225. #define PUFF_ANIM_STATE_INFLATING   3 // the PUFF is being inflated
  226.  
  227. // PUFF animations
  228. #define PUFF_ANIM_BOUNCE_LEFT       0 // bouncing left animation index
  229. #define PUFF_ANIM_BOUNCE_RIGHT      1 // bouncing right animation index
  230. #define PUFF_ANIM_CRUSH_LEFT        2 // getting crushed facing left
  231. #define PUFF_ANIM_CRUSH_RIGHT       3 // getting grushed facing right
  232. #define PUFF_ANIM_BURROW            4 // burrowing animation
  233.  
  234. // ai states
  235. #define PUFF_AI_STATE_FIRE          0  // the PUFF is stopped and preparing to fire
  236. #define PUFF_AI_STATE_EXPLORE       1  // the PUFF is just exploring
  237. #define PUFF_AI_STATE_CHASE         2  // the PUFF chasing the player    
  238. #define PUFF_AI_STATE_EVADE         3  // the PUFF is evading the player
  239. #define PUFF_AI_STATE_BURROW        4  // the PUFF is burrowing
  240. #define PUFF_AI_STATE_CRUSHED       5  // the puff is being crushed
  241. #define PUFF_AI_STATE_INFLATING     6  // the puff is being inflated
  242. #define PUFF_AI_STATE_POPPED        7  // the puff has finally popped
  243.  
  244. // variable indices
  245. #define PUFF_INDEX_AI_STATE         0  // the mode of the ai
  246. #define PUFF_INDEX_ANIM_STATE       1  // the state of the animation
  247. #define PUFF_INDEX_ANIM_DIR         2  // the direction of animation left or right
  248. #define PUFF_INDEX_CURR_DIR         3  // the actual nautical direction
  249. #define PUFF_INDEX_LAST_DIR         4  // the last actual nautical direction
  250. #define PUFF_INDEX_DESIRED_DIR      5  // the desired nautical direction
  251. #define PUFF_INDEX_2ND_DESIRED_DIR  6  // the secondary desired nautical direction
  252. #define PUFF_INDEX_PSI_COUNT        7  // used in inflation algorithm
  253. #define PUFF_INDEX_EXPLORE_COUNTER  8  // used to track how long PUFF in explore mode
  254.  
  255. // tracking for bouncing              
  256. #define PUFF_INDEX_SUM_X             9 // number of x direction bounces 
  257. #define PUFF_INDEX_SUM_Y            10 // number of y direction bounces
  258. #define PUFF_INDEX_BOUNCE_MAX       11 // general counter
  259. #define PUFF_INDEX_OBJECT_PTR       12 // general reference ptr                       
  260.                  
  261. // used to reset level
  262. #define PUFF_INDEX_SAVED_X          13
  263. #define PUFF_INDEX_SAVED_Y          14 
  264. #define PUFF_INDEX_SAVED_DIR        15
  265.  
  266. // motion defines for dug
  267. #define DUG_SPEED                2
  268.  
  269. // defines for dug states
  270. #define DUG_STATE_DEAD           0
  271. #define DUG_STATE_DYING          1
  272. #define DUG_STATE_INVINCIBLE     2
  273. #define DUG_STATE_ALIVE          3
  274. #define DUG_STATE_REBIRTH        4
  275. #define DUG_STATE_CRUSHED        5
  276.  
  277. // defines for position
  278. #define DUG_MIN_Y_WALK           32
  279. #define DUG_X_INTERVAL           40
  280. #define DUG_Y_INTERVAL           40
  281. #define DUG_MIN_ROCK_LINE        64
  282.  
  283. // animation sequences
  284. #define DUG_ANIM_WALK            0
  285. #define DUG_ANIM_DIG             1 
  286. #define DUG_ANIM_FIRE            2
  287.  
  288. #define DUG_ANIM_WALK_LEFT       0
  289. #define DUG_ANIM_DIG_LEFT        1
  290. #define DUG_ANIM_FIRE_LEFT       2
  291.  
  292. #define DUG_ANIM_WALK_RIGHT      3
  293. #define DUG_ANIM_DIG_RIGHT       4
  294. #define DUG_ANIM_FIRE_RIGHT      5
  295.  
  296. #define DUG_ANIM_WALK_UP         6
  297. #define DUG_ANIM_DIG_UP          7
  298. #define DUG_ANIM_FIRE_UP         8
  299.  
  300. #define DUG_ANIM_WALK_DOWN       9
  301. #define DUG_ANIM_DIG_DOWN        10
  302. #define DUG_ANIM_FIRE_DOWN       11
  303. #define DUG_ANIM_DEATH           12
  304. #define DUG_ANIM_REBIRTH         13
  305. #define DUG_ANIM_CRUSHED         14 
  306.  
  307. // general directional defines
  308. #define DIR_NULL                 -1
  309. #define DIR_LEFT                 0
  310. #define DIR_RIGHT                1  
  311. #define DIR_UP                   2
  312. #define DIR_DOWN                 3 
  313.  
  314. // indexed state variables
  315. #define DUG_INDEX_SCORE          0        // score of dig
  316. #define DUG_INDEX_LIVES          1        // number of lives left    
  317. #define DUG_INDEX_LEVEL          2        // current level of play
  318. #define DUG_INDEX_DAMAGE         3        // current damage level
  319. #define DUG_INDEX_ANIM_MODE      4        // animation mode: walk, dig, fire
  320. #define DUG_INDEX_PUMP_PSI       5        // the psi of dugs pump
  321. #define DUG_INDEX_KILLS          6        // number of kills on this level
  322. #define DUG_INDEX_DIR            8        // direction of dig
  323. #define DUG_INDEX_OBJECT_PTR     12       // general reference ptr    
  324.  
  325. // defines for dug pump
  326. #define DUG_MIN_PSI              40 
  327. #define DUG_MAX_PSI              100
  328.  
  329. #define DUG_MAX_RADIATION        600 // that's about enough
  330. #define DUG_CRITICAL_RADIATION   400 // getting a sun burn
  331.  
  332. // general game states
  333. #define GAME_STATE_INIT                 0
  334. #define GAME_STATE_NEXT_LEVEL           1
  335. #define GAME_STATE_RUNNING              2
  336. #define GAME_STATE_PAUSED               3
  337. #define GAME_STATE_OVER                 4
  338. #define GAME_STATE_WIN                  5
  339. #define GAME_STATE_EXIT                 6
  340. #define GAME_STATE_MENU                 7
  341. #define GAME_STATE_WAIT_FOR_TERMINATION 8
  342.  
  343. #define END_LEVEL_DELAY        100
  344.  
  345. // TYPES //////////////////////////////////////////////////
  346.  
  347. // this contains the data of a single level
  348. typedef struct LEVEL_REC_TYP
  349.         {
  350.         char level_name[80]; // name if level
  351.         char image_file[80]; // file name of .BMP file containing image
  352.         char author[80];     // name of author
  353.         int  bonus;          // special bonus for level
  354.         int  diff;           // difficulty of level from 1 to 100
  355.  
  356.         CHAR data[LEVEL_ROWS][LEVEL_COLUMNS]; // level data
  357.  
  358.         } LEVEL_REC, *LEVEL_REC_PTR;
  359.  
  360. // GLOBALS ////////////////////////////////////////////////
  361.  
  362. HWND main_window_handle = NULL;  // save the window handle
  363. HINSTANCE main_instance = NULL;  // save the instance
  364. char buffer[80];                 // used to print text
  365.  
  366. int high_score      = 10000;     // the current high score
  367. int new_man_tracker = POINTS_NEW_MAN;     // tracks if the player gets a new man
  368. int radiation_message_played = 0; // has the radiation message been played
  369.  
  370.  
  371. BITMAP_IMAGE background_bmp,       // used to hold backgrounds
  372.              menu_bmp;             // holds the menu
  373.  
  374. int game_state = GAME_STATE_INIT;  // state of game
  375.  
  376. int end_level_counter = 0;         // end level counter
  377.  
  378. BOB    torch,                      // the burning torches
  379.        dug,                        // the digdumb bob 
  380.        dug_demo,                   // demo clone 
  381.        small_dug,                  // the miniture dug
  382.        puffy,                      // the bob holding all the inflated versions of the poos and puffs
  383.        poos[NUM_POOS],             // the poo poos
  384.        poo_demo,                   // demo clone
  385.        puffs[NUM_PUFFS],           // the puff dragons
  386.        puff_demo,                  // demo clone
  387.        mushroom,                   // the level counting mushrooms
  388.        prizes[NUM_PRIZES],         // the level prizes
  389.        rocks[NUM_ROCKS],           // the falling rocks
  390.        gpumps[NUM_GPUMPS],         // the grappling pumps      
  391.        fballs[NUM_FBALLS],         // the fire balls
  392.        scores[NUM_SCORES];         // holds the score bitmaps
  393.  
  394. BITMAP_IMAGE dug_holes[NUM_HOLE_BITMAPS],   // the holes dug digs
  395.              fblasts[NUM_FBLASTS],          // holes fire balls make
  396.              font[FONT_NUM_CHARS],          // holds the bitmap font
  397.              andre;                         // little picture of me
  398.  
  399. // sound id's
  400. int intro_music_id    = -1,                 // intro music
  401.     win_snd_id        = -1,                 // win sound/music
  402.     credits_snd_id    = -1,                 // the credits
  403.     over_snd_id       = -1,                 // loose sound/music
  404.     level_snd_id      = -1,                 // next level
  405.  
  406.     main_music_ids[3] = {-1,-1,-1}, // main music tracks
  407.  
  408.     fball_snd_ids[4]  = {-1,-1,-1,-1},      // fire ball sounds
  409.     expl_snd_ids[4]  = {-1,-1,-1,-1},       // explosion sounds
  410.     fall_snd_ids[4]   = {-1,-1,-1,-1},      // falling rocks sounds
  411.     gpump_snd_ids[4]  = {-1,-1,-1,-1},      // gpumps fire sound
  412.     air_snd_ids[4]  = {-1,-1,-1,-1},        // air inflation
  413.     pop_snd_ids[4]  = {-1,-1,-1,-1},        // creature poping
  414.     crunch_snd_ids[4] = {-1,-1,-1,-1},      // crunching sounds
  415.     crumble_snd_ids[4] = {-1,-1,-1,-1},     // crumble sounds
  416.  
  417.     dyclops_talk_snd_ids[4] = {-1,-1,-1,-1},  // dyclops talking
  418.     puff_talk_snd_ids[4]    = {-1,-1,-1,-1},  // growling
  419.  
  420.     dug_walk_snd_id   = -1,         // dug walking sound
  421.     dug_push_snd_id   = -1,         // dug pushing the rock
  422.     dug_die_snd_id    = -1,         // dug dying sound
  423.     dug_trans_snd_id  = -1,         // dug transport sound
  424.     dug_life_snd_id   = -1,         // dug gets a new life
  425.     fire_snd_id       = -1,         // ambient fire sound
  426.     radiation_snd_id  = -1,         // radiation level critical
  427.     game_over_snd_id  = -1,         // sound for game over
  428.     prize_out_snd_id  = -1,         // sound when prize comes out
  429.     prize_win_snd_id  = -1;         // sound when dug gets prize
  430.  
  431. // animations for dug motion
  432. int dug_anims[15][12]={ 
  433.                       {0,1,0,2,-1,-1,-1,-1,-1,-1,-1,-1},              // left
  434.                       {3,4,3,5,-1,-1,-1,-1,-1,-1,-1,-1},
  435.                       {6,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
  436.                      
  437.                       {0+8,1+8,0+8,2+8,-1,-1,-1,-1,-1,-1,-1,-1},      // right
  438.                       {3+8,4+8,3+8,5+8,-1,-1,-1,-1,-1,-1,-1,-1},
  439.                       {6+8,7+8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
  440.                      
  441.                       {0+16,1+16,0+16,2+16,-1,-1,-1,-1,-1,-1,-1,-1},  // up
  442.                       {3+16,4+16,3+16,5+16,-1,-1,-1,-1,-1,-1,-1,-1},
  443.                       {6+16,7+16,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
  444.                      
  445.                       {0+24,1+24,0+24,2+24,-1,-1,-1,-1,-1,-1,-1,-1},  // down
  446.                       {3+24,4+24,3+24,5+24,-1,-1,-1,-1,-1,-1,-1,-1},
  447.                       {6+24,7+24,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
  448.              
  449.                       {32,33,34,35,36,37,38,39,40,40,-1,-1},          // death
  450.                       {39,38,37,36,35,34,33,32,-1,-1,-1,-1},          // rebirth
  451.                       {41,42,43,-1,-1,-1,-1,-1,-1,-1,-1,-1,} };       // crush sequence
  452.  
  453.  
  454. // animations for dug grappling pump weapon
  455. int gpump_anims[4][4] = {{0,1,2,1}, {3,4,5,4}, {6,7,8,7}, {9,10,11,10}};
  456.  
  457. // animations for fireballs
  458. int fball_anims[4][5] = {{0,1,2,3,4}, {5,6,7,-1,-1}, {8,9,10,11,12}, {13,14,15,-1,-1}};
  459.  
  460. // animations for poos: bounce, crush, burrow
  461. int poo_anims[5][4] = { {0,1,-1,-1}, {2,3,-1,-1}, {4,5,-1,-1}, {6,7,-1,-1}, {8,9,10,9} };
  462.  
  463. // animations for puffs
  464. int puff_anims[5][4] = { {0,1,0,2}, {3,4,3,5}, {6,7,-1,-1}, {8,9,-1,-1}, {10,11,12,11} };
  465.        
  466. // level stuff
  467. LEVEL_REC game_levels[MAX_LEVELS];   // holds all level data
  468.  
  469. int num_levels = 0,                 // number of levels currently loaded
  470.     curr_level = 0,                 // level being played
  471.     level_name_counter = 0,         // global counter used to display level name              
  472.     num_creatures_on_level = 0;     // number of creatures on this level
  473.  
  474. //MONOPRINT mono;                   // debugger
  475.  
  476. int draw_on = 1;                    // info display flag
  477.  
  478. // PROTOTYPES //////////////////////////////////////////////
  479.  
  480. // game console
  481. int Game_Init(void *parms=NULL);
  482. int Game_Shutdown(void *parms=NULL);
  483. int Game_Main(void *parms=NULL);
  484. int Game_Reset(void);
  485.  
  486. int Init_Prize(int prize_index, int count);
  487. int Start_Level(int level);
  488. int Start_Score(int x, int y, int score);
  489. int Start_Rock(int x, int y);
  490. int Start_Poo(int x, int y, int dir);
  491. int Start_Puff(int x, int y, int dir);
  492. int Start_Fball(int x, int y, int dir, int fball_type);
  493. int Start_Gpump(int x, int y, int dir);
  494. void Start_Dug_Death(void);
  495. int Process_Poos(void);
  496. int Process_Puffs(void);
  497. int Draw_Poos(void);
  498. int Draw_Puffs(void);
  499. int Fast_Distance(int x, int y);
  500. int Copy_Screen(UCHAR *source_bitmap,UCHAR *dest_buffer, int lpitch, int transparent);
  501. int Draw_String(BITMAP_IMAGE_PTR font_ptr,char *string,int x, int y, UCHAR *buffer, int lpitch,int trans);
  502. int Draw_Bitmap2(BITMAP_IMAGE_PTR source_bitmap,UCHAR *dest_buffer, int lpitch, int transparent);
  503. int Play_Sound_From_Pool(int *ids, int num_ids);
  504. int Pause_Sound(int id);
  505. int Resume_Sound(int id);
  506.  
  507.  
  508. // FUNCTIONS //////////////////////////////////////////////
  509.  
  510. LRESULT CALLBACK WindowProc(HWND hwnd, 
  511.                             UINT msg, 
  512.                             WPARAM wparam, 
  513.                             LPARAM lparam)
  514. {
  515. // this is the main message handler of the system
  516. PAINTSTRUCT    ps;           // used in WM_PAINT
  517. HDC            hdc;       // handle to a device context
  518.  
  519. // what is the message 
  520. switch(msg)
  521.     {    
  522.     case WM_CREATE: 
  523.         {
  524.         // do initialization stuff here
  525.         return(0);
  526.         } break;
  527.  
  528.     case WM_PAINT:
  529.          {
  530.          // start painting
  531.          hdc = BeginPaint(hwnd,&ps);
  532.  
  533.          // end painting
  534.          EndPaint(hwnd,&ps);
  535.          return(0);
  536.         } break;
  537.  
  538.     case WM_KILLFOCUS:
  539.          {
  540.          return(0);
  541.          } break;
  542.  
  543.     case WM_DESTROY: 
  544.         {
  545.         // kill the application            
  546.         PostQuitMessage(0);
  547.         CloseWindow(hwnd);
  548.  
  549.         return(0);
  550.         } break;
  551.  
  552.     default:break;
  553.  
  554.     } // end switch
  555.  
  556. // process any messages that we didn't take care of 
  557. return (DefWindowProc(hwnd, msg, wparam, lparam));
  558.  
  559. } // end WinProc
  560.  
  561. // WINMAIN ////////////////////////////////////////////////
  562.  
  563. int WINAPI WinMain(    HINSTANCE hinstance,
  564.                     HINSTANCE hprevinstance,
  565.                     LPSTR lpcmdline,
  566.                     int ncmdshow)
  567. {
  568. // this is the winmain function
  569.  
  570. WNDCLASS winclass;    // this will hold the class we create
  571. HWND     hwnd;        // generic window handle
  572. MSG         msg;        // generic message
  573. HDC      hdc;       // generic dc
  574. PAINTSTRUCT ps;     // generic paintstruct
  575.  
  576. // first fill in the window class stucture
  577. winclass.style            = CS_DBLCLKS | CS_OWNDC | 
  578.                           CS_HREDRAW | CS_VREDRAW;
  579. winclass.lpfnWndProc    = WindowProc;
  580. winclass.cbClsExtra        = 0;
  581. winclass.cbWndExtra        = 0;
  582. winclass.hInstance        = hinstance;
  583. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  584. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  585. winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
  586. winclass.lpszMenuName    = NULL; 
  587. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  588.  
  589. // register the window class
  590. if (!RegisterClass(&winclass))
  591.     return(0);
  592.  
  593. // create the window, note the use of WS_POPUP
  594. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  595.                           "WinX Game Console",     // title
  596.                           WS_POPUP | WS_VISIBLE,
  597.                            0,0,       // x,y
  598.                           WINDOW_WIDTH,  // width
  599.                           WINDOW_HEIGHT, // height
  600.                           NULL,       // handle to parent 
  601.                           NULL,       // handle to menu
  602.                           hinstance,// instance
  603.                           NULL)))    // creation parms
  604. return(0);
  605.  
  606. // save the window handle and instance in a global
  607. main_window_handle = hwnd;
  608. main_instance      = hinstance;
  609.  
  610. // perform all game console specific initialization
  611. Game_Init();
  612. Game_Reset();
  613.  
  614. // enter main event loop
  615. while(1)
  616.     {
  617.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  618.         { 
  619.         // test if this is a quit
  620.         if (msg.message == WM_QUIT)
  621.            break;
  622.     
  623.         // translate any accelerator keys
  624.         TranslateMessage(&msg);
  625.  
  626.         // send the message to the window proc
  627.         DispatchMessage(&msg);
  628.         } // end if
  629.     
  630.     // main game processing goes here
  631.     Game_Main();
  632.  
  633.     } // end while
  634.  
  635. // shutdown game and release all resources
  636. Game_Shutdown();
  637.  
  638. #if 1
  639.  
  640. char *wimps[]={"Not Bad For A Human.",
  641.                "See You Later Carbon Unit",
  642.                "Had Enough Huh?",
  643.                "Send In Some Real Competition!",
  644.                "Maybe Next Time You'll Win!",
  645.                "I Am Invincible!",
  646.                "I Eat Players Like You For Lunch!"};
  647.  
  648. // one last message
  649. MessageBox(NULL, 
  650.           wimps[rand()%7], 
  651.           "UnderWorld Message...",
  652.            MB_ICONEXCLAMATION);
  653.  
  654. #endif
  655.  
  656. // return to Windows like this
  657. return(msg.wParam);
  658.  
  659. } // end WinMain
  660.  
  661. // GAME FUNCTIONS /////////////////////////////////////////////
  662.  
  663. int Load_WAV2(char *filename)
  664. {
  665. // this function loads a .wav file, sets up the directsound 
  666. // buffer and loads the data into memory, the function returns 
  667. // the id number of the sound, this version was needed since
  668.  
  669. HMMIO             hwav;    // handle to wave file
  670. MMCKINFO        parent,  // parent chunk
  671.                 child;   // child chunk
  672. WAVEFORMATEX    wfmtx;   // wave format structure
  673.  
  674. int    sound_id = -1,       // id of sound to be loaded
  675.     index;               // looping variable
  676.  
  677. UCHAR *snd_buffer,       // temporary sound buffer to hold voc data
  678.       *audio_ptr_1=NULL, // data ptr to first write buffer 
  679.       *audio_ptr_2=NULL; // data ptr to second write buffer
  680.  
  681. DWORD audio_length_1=0,  // length of first write buffer
  682.       audio_length_2=0;  // length of second write buffer
  683.             
  684. // step one: are there any open id's ?
  685. for (index=0; index < MAX_SOUNDS; index++)
  686.     {    
  687.     // make sure this sound is unused
  688.     if (sound_fx[index].state==SOUND_NULL)
  689.        {
  690.        sound_id = index;
  691.        break;
  692.        } // end if
  693.  
  694.     } // end for index
  695.  
  696. // did we get a free id?
  697. if (sound_id==-1)
  698.     return(-1);
  699.  
  700. // set up chunk info structure
  701. parent.ckid         = (FOURCC)0;
  702. parent.cksize         = 0;
  703. parent.fccType        = (FOURCC)0;
  704. parent.dwDataOffset = 0;
  705. parent.dwFlags        = 0;
  706.  
  707. // copy data
  708. child = parent;
  709.  
  710. // open the WAV file
  711. if ((hwav = mmioOpen(filename, NULL, MMIO_READ | MMIO_ALLOCBUF))==NULL)
  712.     return(-1);
  713.  
  714. // descend into the RIFF 
  715. parent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  716.  
  717. if (mmioDescend(hwav, &parent, NULL, MMIO_FINDRIFF))
  718.     {
  719.     // close the file
  720.     mmioClose(hwav, 0);
  721.  
  722.     // return error, no wave section
  723.     return(-1);     
  724.     } // end if
  725.  
  726. // descend to the WAVEfmt 
  727. child.ckid = mmioFOURCC('f', 'm', 't', ' ');
  728.  
  729. if (mmioDescend(hwav, &child, &parent, 0))
  730.     {
  731.     // close the file
  732.     mmioClose(hwav, 0);
  733.  
  734.     // return error, no format section
  735.     return(-1);     
  736.     } // end if
  737.  
  738. // now read the wave format information from file
  739. if (mmioRead(hwav, (char *)&wfmtx, sizeof(wfmtx)) != sizeof(wfmtx))
  740.     {
  741.     // close file
  742.     mmioClose(hwav, 0);
  743.  
  744.     // return error, no wave format data
  745.     return(-1);
  746.     } // end if
  747.  
  748. // make sure that the data format is PCM
  749. if (wfmtx.wFormatTag != WAVE_FORMAT_PCM)
  750.     {
  751.     // close the file
  752.     mmioClose(hwav, 0);
  753.  
  754.     // return error, not the right data format
  755.     return(-1); 
  756.     } // end if
  757.  
  758. // now ascend up one level, so we can access data chunk
  759. if (mmioAscend(hwav, &child, 0))
  760.    {
  761.    // close file
  762.    mmioClose(hwav, 0);
  763.  
  764.    // return error, couldn't ascend
  765.    return(-1);     
  766.    } // end if
  767.  
  768. // descend to the data chunk 
  769. child.ckid = mmioFOURCC('d', 'a', 't', 'a');
  770.  
  771. if (mmioDescend(hwav, &child, &parent, MMIO_FINDCHUNK))
  772.     {
  773.     // close file
  774.     mmioClose(hwav, 0);
  775.  
  776.     // return error, no data
  777.     return(-1);     
  778.     } // end if
  779.  
  780. // finally!!!! now all we have to do is read the data in and
  781. // set up the directsound buffer
  782.  
  783. // allocate the memory to load sound data
  784. snd_buffer = (UCHAR *)malloc(child.cksize);
  785.  
  786. // read the wave data 
  787. mmioRead(hwav, (char *)snd_buffer, child.cksize);
  788.  
  789. // close the file
  790. mmioClose(hwav, 0);
  791.  
  792. // set rate and size in data structure
  793. sound_fx[sound_id].rate  = wfmtx.nSamplesPerSec;
  794. sound_fx[sound_id].size  = child.cksize;
  795. sound_fx[sound_id].state = SOUND_LOADED;
  796.  
  797. // set up the format data structure
  798. memset(&pcmwf, 0, sizeof(WAVEFORMATEX));
  799.  
  800. pcmwf.wFormatTag      = WAVE_FORMAT_PCM;  // pulse code modulation
  801. pcmwf.nChannels          = 1;                // mono 
  802. pcmwf.nSamplesPerSec  = 11025;            // always this rate
  803. pcmwf.nBlockAlign      = 1;                
  804. pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
  805. pcmwf.wBitsPerSample  = 8;
  806. pcmwf.cbSize          = 0;
  807.  
  808. // prepare to create sounds buffer
  809. dsbd.dwSize            = sizeof(DSBUFFERDESC);
  810. dsbd.dwFlags        = DSBCAPS_CTRLDEFAULT | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE;
  811. dsbd.dwBufferBytes    = child.cksize;
  812. dsbd.lpwfxFormat    = &pcmwf;
  813.  
  814. // create the sound buffer
  815. if (lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL)!=DS_OK)
  816.    {
  817.    // release memory
  818.    free(snd_buffer);
  819.  
  820.    // return error
  821.    return(-1);
  822.    } // end if
  823.  
  824. // copy data into sound buffer
  825. if (sound_fx[sound_id].dsbuffer->Lock(0,                     
  826.                                       child.cksize,            
  827.                                       (void **) &audio_ptr_1, 
  828.                                       &audio_length_1,
  829.                                       (void **)&audio_ptr_2, 
  830.                                       &audio_length_2,
  831.                                       DSBLOCK_FROMWRITECURSOR)!=DS_OK)
  832.                                  return(0);
  833.  
  834. // copy first section of circular buffer
  835. memcpy(audio_ptr_1, snd_buffer, audio_length_1);
  836.  
  837. // copy last section of circular buffer
  838. memcpy(audio_ptr_2, (snd_buffer+audio_length_1),audio_length_2);
  839.  
  840. // unlock the buffer
  841. if (sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1, 
  842.                                         audio_length_1, 
  843.                                         audio_ptr_2, 
  844.                                         audio_length_2)!=DS_OK)
  845.                                   return(0);
  846.  
  847. // release the temp buffer
  848. free(snd_buffer);
  849.  
  850. // return id
  851. return(sound_id);
  852.  
  853. } // end Load_WAV2
  854.  
  855. /////////////////////////////////////////////////////////////////////////////
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863. int Pause_Sound(int id)
  864. {
  865. // this function pauses
  866. if (sound_fx[id].dsbuffer)
  867.    {
  868.    sound_fx[id].dsbuffer->Stop();
  869.    } // end if
  870.  
  871. // return success
  872. return(1);
  873.  
  874. } // end Pause_Sound
  875.  
  876. ///////////////////////////////////////////////////////////
  877.  
  878. int Resume_Sound(int id, int flags=0)
  879. {
  880. // this function plays a sound, the only parameter that 
  881. // works is the flags which can be 0 to play once or
  882. // DSBPLAY_LOOPING
  883.  
  884. if (sound_fx[id].dsbuffer)
  885.     {
  886.     // continue playing
  887.      if (sound_fx[id].dsbuffer->Play(0,0,flags)!=DS_OK)
  888.         return(0);
  889.     } // end if
  890.  
  891. // return success
  892. return(1);
  893.  
  894. } // end Resume_Sound
  895.  
  896. //////////////////////////////////////////////////////////
  897.  
  898. int Load_Sound_Music(void)
  899. {
  900. // this function loads all the sounds and music
  901.  
  902. int index; // looping variable
  903.  
  904. // load in intro music
  905. if ((intro_music_id = Load_WAV("UNDSOUND/UNDINTRO.WAV",0))==-1)
  906.    return(0);
  907.     
  908. // load in credits music
  909. if ((credits_snd_id = Load_WAV("UNDSOUND/UNDCRED.WAV",0))==-1)
  910.    return(0);
  911.  
  912. // win sound/music
  913. if ((win_snd_id = Load_WAV("UNDSOUND/UNDWIN.WAV",0))==-1)
  914.    return(0);
  915.  
  916. // load the end sound/music
  917. //if ((over_snd_id = Load_WAV("NULL.WAV"))==-1)
  918. //   return(0);
  919.  
  920. // load the next level sound/music
  921. if ((level_snd_id = Load_WAV("UNDSOUND/UNDNLEV2.WAV",0))==-1)
  922.    return(0);
  923.  
  924. // load music
  925. //if ((main_music_ids[0] = Load_WAV("NULL.WAV"))==-1)
  926. //   return(0);
  927.  
  928. // load music
  929. //if ((main_music_ids[1] = Load_WAV("NULL.WAV"))==-1)
  930. //  return(0);
  931.  
  932. // load music
  933. //if ((main_music_ids[2] = Load_WAV("NULL.WAV"))==-1)
  934. //   return(0);
  935.  
  936.  
  937.  
  938.  
  939. // fire ball sounds
  940. if ((fball_snd_ids[0] = Load_WAV("UNDSOUND/UNDFBAL1.WAV",0))==-1)
  941.     return(0);
  942.  
  943. if ((fball_snd_ids[1] = Load_WAV("UNDSOUND/UNDFBAL0.WAV",0))==-1)
  944.     return(0);
  945.  
  946. // now make copies
  947. for (index=2; index < 4; index++)
  948.     {
  949.     // replicate sound
  950.     fball_snd_ids[index] = Replicate_Sound(fball_snd_ids[index%2]);  
  951.  
  952.     } // end for index
  953.  
  954. // explosion sounds
  955. if ((expl_snd_ids[0] = Load_WAV("UNDSOUND/UNDEXPL.WAV",0))==-1)
  956.     return(0);
  957.  
  958. // now make copies
  959. for (index=1; index < 4; index++)
  960.     {
  961.     // replicate sound
  962.     expl_snd_ids[index] = Replicate_Sound(expl_snd_ids[0]);  
  963.  
  964.     } // end for index
  965.  
  966.  
  967.  
  968. // crumbling rock sounds
  969. if ((crumble_snd_ids[0] = Load_WAV("UNDSOUND/UNDRHIT.WAV",0))==-1)
  970.     return(0);
  971.  
  972. // now make copies
  973. for (index=1; index < 4; index++)
  974.     {
  975.     // replicate sound
  976.     crumble_snd_ids[index] = Replicate_Sound(crumble_snd_ids[0]);  
  977.  
  978.     } // end for index
  979.  
  980.  
  981.  
  982.  
  983. // gpumps fire sound
  984. if ((gpump_snd_ids[0] = Load_WAV("UNDSOUND/UNDGPUMP.WAV",0))==-1)
  985.     return(0);
  986.  
  987. // now make copies
  988. for (index=1; index < 4; index++)
  989.     {
  990.     // replicate sound
  991.     gpump_snd_ids[index] = Replicate_Sound(gpump_snd_ids[0]);  
  992.  
  993.     } // end for index
  994.  
  995. // air sound
  996. if ((air_snd_ids[0] = Load_WAV("UNDSOUND/UNDAIR.WAV",0))==-1)
  997.     return(0);
  998.  
  999. // now make copies
  1000. for (index=1; index < 4; index++)
  1001.     {
  1002.     // replicate sound
  1003.     air_snd_ids[index] = Replicate_Sound(air_snd_ids[0]);  
  1004.  
  1005.     } // end for index
  1006.  
  1007. // pop sound
  1008. if ((pop_snd_ids[0] = Load_WAV("UNDSOUND/UNDBLOW2.WAV",0))==-1)
  1009.     return(0);
  1010.  
  1011. // now make copies
  1012. for (index=1; index < 4; index++)
  1013.     {
  1014.     // replicate sound
  1015.     pop_snd_ids[index] = Replicate_Sound(pop_snd_ids[0]);  
  1016.  
  1017.     } // end for index
  1018.  
  1019.  
  1020. // crunching sounds
  1021. if ((crunch_snd_ids[0] = Load_WAV("UNDSOUND/UNDCRUNC.WAV",0))==-1)
  1022.     return(0);
  1023.  
  1024. // now make copies
  1025. for (index=1; index < 4; index++)
  1026.     {
  1027.     // replicate sound
  1028.     crunch_snd_ids[index] = Replicate_Sound(crunch_snd_ids[0]);  
  1029.  
  1030.     } // end for index
  1031.  
  1032.  
  1033. // rock shake and falling sound
  1034. if ((fall_snd_ids[0] = Load_WAV("UNDSOUND/UNDSHAK2.WAV",0))==-1)
  1035.     return(0);
  1036.  
  1037. // now make copies
  1038. for (index=1; index < 4; index++)
  1039.     {
  1040.     // replicate sound
  1041.     fall_snd_ids[index] = Replicate_Sound(fall_snd_ids[0]);  
  1042.  
  1043.     } // end for index
  1044.  
  1045.  
  1046. // dyclops talking
  1047. for (index=0; index<4; index++)
  1048.     {
  1049.     sprintf(buffer,"UNDSOUND/UNDDYTK%d.WAV",index);
  1050.     if ((dyclops_talk_snd_ids[index] = Load_WAV(buffer,0))==-1)
  1051.         return(0);
  1052.     } // end for index
  1053.  
  1054.  
  1055. // puff dragons growling
  1056. for (index=0; index<4; index++)
  1057.     {
  1058.     sprintf(buffer,"UNDSOUND/UNDPFTK%d.WAV",index);
  1059.     if ((puff_talk_snd_ids[index] = Load_WAV(buffer,0))==-1)
  1060.         return(0);
  1061.     } // end for index
  1062.  
  1063.  
  1064. // dug walking sound
  1065. //if ((dug_walk_snd_id = Load_WAV("NULL.WAV"))==-1)
  1066. //    return(0);
  1067.  
  1068. if ((dug_push_snd_id = Load_WAV("UNDSOUND/UNDPUSH1.WAV",0))==-1)
  1069.     return(0);
  1070.  
  1071.  
  1072. // dug dying sound
  1073. if ((dug_die_snd_id = Load_WAV("UNDSOUND/UNDDIE.WAV",0))==-1)
  1074.     return(0);
  1075.  
  1076. // dug transport sound
  1077. if ((dug_trans_snd_id = Load_WAV("UNDSOUND/UNDTRANS.WAV",0))==-1)
  1078.     return(0);
  1079.  
  1080. // dug game over sound
  1081. if ((game_over_snd_id = Load_WAV("UNDSOUND/UNDOVER.WAV",0))==-1)
  1082.     return(0);
  1083.  
  1084. // dug new life
  1085. if ((dug_life_snd_id = Load_WAV("UNDSOUND/UNDLIFE.WAV",0))==-1)
  1086.     return(0);
  1087.  
  1088. // prize out sound
  1089. if ((prize_out_snd_id = Load_WAV("UNDSOUND/UNDPRIZ0.WAV",0))==-1)
  1090.     return(0);
  1091.  
  1092. // prize win sound
  1093. if ((prize_win_snd_id = Load_WAV("UNDSOUND/UNDPRIZ1.WAV",0))==-1)
  1094.     return(0);
  1095.  
  1096.  
  1097. // radiation level critical
  1098. if ((radiation_snd_id = Load_WAV("UNDSOUND/UNDRAD.WAV",0))==-1)
  1099.     return(0);
  1100.  
  1101.  
  1102. // the ambient fire
  1103. //if ((fire_snd_id = Load_WAV("NULL.WAV"))==-1)
  1104. //    return(0);
  1105.  
  1106.  
  1107. // return sucess
  1108. return(1);
  1109.  
  1110. } // end Load_Sound_Music
  1111.  
  1112. ///////////////////////////////////////////////////////////////
  1113.  
  1114. int Play_Sound_From_Pool(int *ids, int num_ids)
  1115. {
  1116. // this function starts a sound given the array of sounds and number of available replicants
  1117.  
  1118. // start sound up
  1119. for (int sound_index=0; sound_index < num_ids; sound_index++)
  1120.     {
  1121.     // test if this sound is playing
  1122.     if (Status_Sound(ids[sound_index])==0)
  1123.        {
  1124.        Play_Sound(ids[sound_index]);
  1125.        return(1);
  1126.        } // end if
  1127.         
  1128.     } // end for sound_index 
  1129.  
  1130. // error
  1131. return(-1);
  1132.  
  1133. } // end Play_Sound_From_Pool
  1134.  
  1135. ///////////////////////////////////////////////////////////////
  1136.  
  1137. int Draw_String(BITMAP_IMAGE_PTR font_ptr,
  1138.                 char *string,
  1139.                 int x, int y, 
  1140.                 UCHAR *buffer, 
  1141.                 int lpitch, 
  1142.                 int trans)
  1143. {
  1144. // this function draws a string on the screen using the loaded bitmap font
  1145.  
  1146. // get length to print
  1147. int length = strlen(string);
  1148.  
  1149. // print the string
  1150. for (int index=0; index<length; index++)
  1151.     {
  1152.     // get index of character
  1153.     int cindex = string[index] - ' ';
  1154.  
  1155.     // set x,y
  1156.     font_ptr[cindex].x = x;
  1157.     font_ptr[cindex].y = y;
  1158.  
  1159.     // draw the bitmap
  1160.     Draw_Bitmap2(&font_ptr[cindex],buffer,lpitch,trans);
  1161.  
  1162.     // move over to next character position
  1163.     if (string[index] >= ' ' && string[index] <= '9')
  1164.        x+=(FONT_WIDTH_NEXT_NUM);
  1165.     else
  1166.     if (string[index] >= ':' && string[index] <= 'Z')
  1167.        x+=(FONT_WIDTH_NEXT_UPPER);
  1168.     else
  1169.     if (string[index] > 'Z' && string[index] <= '~')
  1170.        x+=FONT_WIDTH_NEXT_LOWER;
  1171.  
  1172.     } // end if
  1173.  
  1174. // return success
  1175. return(1);
  1176.  
  1177. } // end Draw_String
  1178.  
  1179. ////////////////////////////////////////////////////////////////
  1180.  
  1181. int Copy_Screen(UCHAR *source_bitmap,UCHAR *dest_buffer, int lpitch, int transparent)
  1182. {
  1183. // this function draws the bitmap onto the destination memory surface
  1184. // if transparent is 1 then color 0 will be transparent
  1185. // note this function does NOT clip, so be carefull!!!
  1186.  
  1187. UCHAR *dest_addr,   // starting address of bitmap in destination
  1188.       *source_addr; // starting adddress of bitmap data in source
  1189.  
  1190. UCHAR pixel;        // used to hold pixel value
  1191.  
  1192. int index,          // looping vars
  1193.     pixel_x;
  1194.  
  1195. // test if this bitmap is loaded
  1196.  
  1197.    // compute starting destination address
  1198.    dest_addr = dest_buffer;
  1199.  
  1200.    // compute the starting source address
  1201.    source_addr = source_bitmap;
  1202.  
  1203.    // is this bitmap transparent
  1204.    if (transparent)
  1205.    {
  1206.    // copy each line of bitmap into destination with transparency
  1207.    for (index=0; index < SCREEN_HEIGHT; index++)
  1208.        {
  1209.        // copy the memory
  1210.        for (pixel_x=0; pixel_x < SCREEN_WIDTH; pixel_x++)
  1211.            {
  1212.            if ((pixel = source_addr[pixel_x])!=0)
  1213.                dest_addr[pixel_x] = pixel;
  1214.  
  1215.            } // end if
  1216.  
  1217.        // advance all the pointers
  1218.        dest_addr   += lpitch;
  1219.        source_addr += SCREEN_WIDTH;
  1220.  
  1221.        } // end for index
  1222.    } // end if
  1223.    else
  1224.    {
  1225.    // non-transparent version
  1226.    // copy each line of bitmap into destination
  1227.  
  1228.    for (index=0; index < SCREEN_HEIGHT; index++)
  1229.        {
  1230.        // copy the memory
  1231.        memcpy(dest_addr, source_addr, SCREEN_WIDTH);
  1232.  
  1233.        // advance all the pointers
  1234.        dest_addr   += lpitch;
  1235.        source_addr += SCREEN_WIDTH;
  1236.  
  1237.        } // end for index
  1238.  
  1239.    } // end else
  1240.  
  1241.    // return success
  1242.    return(1);
  1243.  
  1244. } // end Copy_Screen
  1245.  
  1246. /////////////////////////////////////////////////////////////////////////
  1247.  
  1248. int Fast_Distance(int x, int y)
  1249. {
  1250. // this function computes the distance from 0,0 to x,y with 3.5% error
  1251.  
  1252. // first compute the absolute value of x,y
  1253.  
  1254. x = abs(x);
  1255. y = abs(y);
  1256.  
  1257. // compute the minimum of x,y
  1258.  
  1259. int mn = min(x,y);
  1260.  
  1261. // return the distance
  1262.  
  1263. return(x+y-(mn>>1)-(mn>>2)+(mn>>4));
  1264.  
  1265. } // end Fast_Distance
  1266.  
  1267. ///////////////////////////////////////////////////////////////
  1268.  
  1269. int Animate_BOB2(BOB_PTR bob)
  1270. {
  1271. // this function animates a bob, basically it takes a look at
  1272. // the attributes of the bob and determines if the bob is 
  1273. // a single frame, multiframe, or multi animation, updates
  1274. // the counters and frames appropriately
  1275.  
  1276.  
  1277. // is this a valid bob
  1278. if (!bob)
  1279.    return(0);
  1280.  
  1281. // test the level of animation
  1282. if (bob->attr & BOB_ATTR_SINGLE_FRAME)
  1283.     {
  1284.     // current frame always = 0
  1285.     bob->curr_frame = 0;
  1286.     return(1);
  1287.     } // end if
  1288. else
  1289. if (bob->attr & BOB_ATTR_MULTI_FRAME)
  1290.    {
  1291.    // update the counter and test if its time to increment frame
  1292.    if (++bob->anim_counter >= bob->anim_count_max)
  1293.       {
  1294.       // reset counter
  1295.       bob->anim_counter = 0;
  1296.  
  1297.       // move to next frame
  1298.       if (++bob->curr_frame >= bob->num_frames)
  1299.          {
  1300.          // reset frame
  1301.          bob->curr_frame = 0;
  1302.          // set animation state message to done
  1303.          bob->anim_state = BOB_STATE_ANIM_DONE;
  1304.          } // end if
  1305.  
  1306.       } // end if
  1307.   
  1308.    } // end elseif
  1309. else
  1310. if (bob->attr & BOB_ATTR_MULTI_ANIM)
  1311.    {
  1312.    // this is the most complex of the animations it must look up the
  1313.    // next frame in the animation sequence
  1314.  
  1315.    // first test if its time to animate
  1316.    if (++bob->anim_counter >= bob->anim_count_max)
  1317.       {
  1318.       // reset counter
  1319.       bob->anim_counter = 0;
  1320.  
  1321.       // increment the animation frame index
  1322.       bob->anim_index++;
  1323.       
  1324.       // extract the next frame from animation list 
  1325.       bob->curr_frame = bob->animations[bob->curr_animation][bob->anim_index];
  1326.      
  1327.       // is this and end sequence flag -1
  1328.       if (bob->curr_frame == -1)
  1329.          {
  1330.          // test if this is a single shot animation
  1331.          if (bob->attr & BOB_ATTR_ANIM_ONE_SHOT)
  1332.             {
  1333.             // set animation state message to done
  1334.             bob->anim_state = BOB_STATE_ANIM_DONE;
  1335.             
  1336.             // reset frame back one
  1337.             bob->anim_index--;
  1338.  
  1339.             // extract animation frame
  1340.             bob->curr_frame = bob->animations[bob->curr_animation][bob->anim_index];    
  1341.  
  1342.             } // end if
  1343.         else
  1344.            {
  1345.            // reset animation index
  1346.            bob->anim_index = 0;
  1347.  
  1348.            // extract first animation frame
  1349.            bob->curr_frame = bob->animations[bob->curr_animation][bob->anim_index];
  1350.  
  1351.            // set animation state message to done
  1352.            bob->anim_state = BOB_STATE_ANIM_DONE; 
  1353.  
  1354.            } // end else
  1355.  
  1356.          }  // end if
  1357.       
  1358.       } // end if
  1359.  
  1360.    } // end elseif
  1361.  
  1362. // return success
  1363. return(1);
  1364.  
  1365. } // end Animate_BOB2
  1366.  
  1367. ///////////////////////////////////////////////////////////
  1368.  
  1369. int Set_Animation_BOB2(BOB_PTR bob, int anim_index)
  1370. {
  1371. // this function sets the animation to play
  1372.  
  1373. // is this a valid bob
  1374. if (!bob)
  1375.    return(0);
  1376.  
  1377. // set the animation index
  1378. bob->curr_animation = anim_index;
  1379.  
  1380. // reset animation 
  1381. bob->anim_index   = 0;
  1382. bob->anim_counter = 0;
  1383. bob->anim_state   = 0;
  1384. bob->curr_frame   = bob->animations[bob->curr_animation][bob->anim_index];
  1385.  
  1386. // return success
  1387. return(1);
  1388.  
  1389. } // end Set_Animation_BOB2
  1390.  
  1391. //////////////////////////////////////////////////////////////////
  1392.  
  1393. UCHAR Get_Pixel(int x, int y,UCHAR *video_buffer, int lpitch)
  1394. {
  1395. // this function gets the pixel value at x,y
  1396.  
  1397. return(video_buffer[x + y*lpitch]);
  1398.  
  1399. } // end Get_Pixel
  1400.  
  1401. ///////////////////////////////////////////////////////////////
  1402.  
  1403. void Dig_Hole(void)
  1404. {
  1405. // this function digs the hole infront of dug
  1406.  
  1407. // test if dug can dig
  1408. if ((dug.y < 64 && dug.varsI[DUG_INDEX_DIR]==DIR_UP)   ||
  1409.     (dug.y < 42 && dug.varsI[DUG_INDEX_DIR]==DIR_DOWN) || 
  1410.     (dug.y == 32) )
  1411.   return;
  1412.  
  1413. int hole_noise = ((rand()%2) << 2);
  1414.  
  1415. dug_holes[dug.varsI[DUG_INDEX_DIR]+hole_noise].x = dug.x; 
  1416. dug_holes[dug.varsI[DUG_INDEX_DIR]+hole_noise].y = dug.y;
  1417. Draw_Bitmap(&dug_holes[dug.varsI[DUG_INDEX_DIR]+hole_noise],background_bmp.buffer,background_bmp.width,1);
  1418.  
  1419. } // end Dig_Hole
  1420.  
  1421. ///////////////////////////////////////////////////////////////
  1422.  
  1423. void Dug_Dig_Test(int x, int y)
  1424. {
  1425. // this function tests if dug needs to dig and sets the animation sequence appropriately
  1426.  
  1427. static int score_counter = 0; // used to track when to add to score
  1428.  
  1429. // first test if dug is up top, if so override
  1430. if ( (dug.y == 32) && (dug.varsI[DUG_INDEX_ANIM_MODE]!=DUG_ANIM_WALK))
  1431.    {
  1432.    // set to walk mode -- no digging!!!
  1433.    dug.varsI[DUG_INDEX_ANIM_MODE] = DUG_ANIM_WALK;
  1434.    Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  1435.    return;
  1436.    } // end if
  1437. else
  1438. if (dug.y == 32) 
  1439.    return;
  1440.  
  1441. // first test if there is any rock ahead
  1442. if (Get_Pixel(x,y,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) 
  1443.    {
  1444.    // turn digging on if it's off
  1445.    if (dug.varsI[DUG_INDEX_ANIM_MODE]!=DUG_ANIM_DIG)
  1446.       {
  1447.       dug.varsI[DUG_INDEX_ANIM_MODE] = DUG_ANIM_DIG;
  1448.       Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  1449.       } // end if
  1450.    if (++score_counter > 5)
  1451.       {
  1452.       // add some to the score
  1453.       dug.varsI[DUG_INDEX_SCORE]+=10;
  1454.     
  1455.       // reset counter
  1456.       score_counter = 0;     
  1457.  
  1458.       } // end if
  1459.  
  1460.    } // end if
  1461. else
  1462. if (dug.varsI[DUG_INDEX_ANIM_MODE]!=DUG_ANIM_WALK)
  1463.    {
  1464.    dug.varsI[DUG_INDEX_ANIM_MODE] = DUG_ANIM_WALK;
  1465.    Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  1466.    } // end if
  1467.  
  1468. } // end Dug_Dig_Test
  1469.  
  1470. ///////////////////////////////////////////////////////////////
  1471.  
  1472. void Draw_Info(void)
  1473. {
  1474. // this function draws all the information about the game including bitmaps of the player
  1475. // and level
  1476.  
  1477. static int blink_counter = 0, // state of all blinkin objects
  1478.            blink_state   = 1,
  1479.            glow_color    = 128;
  1480.  
  1481. int index; // looping var
  1482.  
  1483. char blank_number[8]; // used to generate 7 digit numbers
  1484.  
  1485. // draw the name of the level
  1486. if (level_name_counter > 0)
  1487.    {
  1488.    // draw the level name  
  1489.    Draw_Text_GDI(game_levels[curr_level].level_name,
  1490.                 (SCREEN_WIDTH/2) - 4*strlen(game_levels[curr_level].level_name), 
  1491.                 SCORE_Y+16,
  1492.                 RGB(0,(glow_color%256),0),lpddsback);
  1493.    
  1494.    glow_color+=16;
  1495.  
  1496.    // dec counter
  1497.    level_name_counter--;
  1498.  
  1499.    //sprintf(buffer,"LeveL=%d Name='%s'",curr_level,game_levels[curr_level].level_name);
  1500.    //mono.set_cursor(0,6);
  1501.    //mono.print(buffer);
  1502.  
  1503.    } // end if
  1504. else
  1505. {
  1506. // update blinker
  1507. if (++blink_counter > 15)
  1508.    {
  1509.    // reset counter
  1510.    blink_counter = 0;
  1511.  
  1512.    // toggle state of blink
  1513.    blink_state=-blink_state;
  1514.    } // end if
  1515.  
  1516. // lock back buffer
  1517. DD_Lock_Back_Surface();
  1518.  
  1519. if (keyboard_state[DIK_RCONTROL] && keyboard_state[DIK_RALT] && keyboard_state[DIK_A])
  1520.     {
  1521.     Draw_String(font,"Created by Andre' LaMothe 1998",320-180,240,back_buffer, back_lpitch,0);
  1522.     Draw_Bitmap(&andre,back_buffer, back_lpitch,0);
  1523.     } // end if
  1524.  
  1525. // first the current score
  1526. if (blink_state==1)
  1527.    Draw_String(font,"1UP",SCORE_X-16,SCORE_Y,back_buffer, back_lpitch,0);
  1528.  
  1529. //Draw_Text_GDI("1UP", SCORE_X, SCORE_Y, SCORE_COLOR_BOLD, lpddsback);
  1530.  
  1531. // sprintf(buffer, "%d",dug.varsI[DUG_INDEX_SCORE]);
  1532. itoa(dug.varsI[DUG_INDEX_SCORE],buffer,10);
  1533.  
  1534. strcpy(blank_number,"0000000");
  1535. memcpy(blank_number+7-strlen(buffer),buffer,strlen(buffer));
  1536. Draw_String(font,blank_number,SCORE_X+36,SCORE_Y,back_buffer, back_lpitch,0);
  1537.  
  1538. // draw rads
  1539. itoa(dug.varsI[DUG_INDEX_DAMAGE],buffer,10);
  1540. Draw_String(font,buffer,SCORE_X+36,SCORE_Y+16,back_buffer, back_lpitch,0);
  1541.  
  1542. // Draw_Text_GDI(blank_number, SCORE_X+36, SCORE_Y,SCORE_COLOR_TEXT, lpddsback);
  1543.  
  1544. // draw the psi display
  1545. //Draw_String(font,"PSI",SCORE_X+136,SCORE_Y,back_buffer, back_lpitch,0);
  1546. //Draw_Text_GDI("PSI", SCORE_X+128, SCORE_Y, SCORE_COLOR_BOLD, lpddsback);
  1547.  
  1548. // sprintf(buffer, "%d",dug.varsI[DUG_INDEX_SCORE]);
  1549. itoa(dug.varsI[DUG_INDEX_PUMP_PSI],buffer,10);
  1550. Draw_String(font,buffer,SCORE_X+180,SCORE_Y,back_buffer, back_lpitch,0);
  1551. //Draw_Text_GDI(buffer, SCORE_X+156, SCORE_Y,SCORE_COLOR_TEXT, lpddsback);
  1552.  
  1553. // now the high score
  1554. //Draw_String(font,"HIGH SCORE",SCORE_X+240,SCORE_Y,back_buffer, back_lpitch,0);
  1555. //Draw_Text_GDI("HIGH SCORE", SCORE_X+240, SCORE_Y, SCORE_COLOR_BOLD, lpddsback);
  1556.  
  1557. // sprintf(buffer, "%d",high_score);
  1558. itoa(high_score,buffer,10);
  1559.  
  1560. strcpy(blank_number,"0000000");
  1561. memcpy(blank_number+7-strlen(buffer),buffer,strlen(buffer));
  1562. Draw_String(font,blank_number,SCORE_X+368,SCORE_Y,back_buffer, back_lpitch,0);
  1563. //Draw_Text_GDI(blank_number, SCORE_X+332, SCORE_Y, SCORE_COLOR_TEXT, lpddsback);
  1564.  
  1565. // now the level
  1566. //Draw_String(font,"LEVEL",SCORE_X+500,SCORE_Y,back_buffer, back_lpitch,0);
  1567. //Draw_Text_GDI("LEVEL", SCORE_X+500, SCORE_Y, SCORE_COLOR_BOLD, lpddsback);
  1568.  
  1569. // sprintf(buffer, "%d",dug.varsI[DUG_INDEX_LEVEL]);
  1570. itoa(dug.varsI[DUG_INDEX_LEVEL]+1,buffer,10);
  1571. Draw_String(font,buffer,SCORE_X+564,SCORE_Y,back_buffer, back_lpitch,0);
  1572. //Draw_Text_GDI(buffer, SCORE_X+548, SCORE_Y, SCORE_COLOR_TEXT, lpddsback);
  1573.  
  1574. } // end text info
  1575.  
  1576. // unlock back buffer
  1577. DD_Unlock_Back_Surface();
  1578.  
  1579. // bitmap of the level with mushrooms
  1580. int mush_tens = (dug.varsI[DUG_INDEX_LEVEL]+1) / 10;
  1581. int mush_ones = (dug.varsI[DUG_INDEX_LEVEL]+1) % 10;
  1582.  
  1583. // start off in starting position
  1584. int mush_x = MUSH_START_X;
  1585. int mush_y = MUSH_START_Y;
  1586.  
  1587. // draw the tens mushrooms
  1588. for (index=0; index < mush_tens; index++, mush_x-=32)
  1589.     {
  1590.     // set the position of the sprite
  1591.     mushroom.x = mush_x;
  1592.     mushroom.y = mush_y;
  1593.     
  1594.     // set frame to tens 
  1595.     mushroom.curr_frame = 1;
  1596.  
  1597.     // draw the mushroom
  1598.     Draw_BOB(&mushroom, lpddsback);
  1599.  
  1600.     } // end for index
  1601.  
  1602. // draw the ones mushrooms
  1603. for (index=0; index < mush_ones; index++, mush_x-=32)
  1604.     {
  1605.     // set the position of the sprite
  1606.     mushroom.x = mush_x;
  1607.     mushroom.y = mush_y;
  1608.     
  1609.     // set frame to tens 
  1610.     mushroom.curr_frame = 0;
  1611.  
  1612.     // draw the mushroom
  1613.     Draw_BOB(&mushroom, lpddsback);
  1614.  
  1615.     } // end for index
  1616.  
  1617. // bitmaps of number of players left
  1618. small_dug.x = DUG_LIVES_X;
  1619. small_dug.y = DUG_LIVES_Y;
  1620.  
  1621. for (index=0; index < dug.varsI[DUG_INDEX_LIVES]; index++, small_dug.x+=16)
  1622.     {
  1623.     // draw another little man
  1624.     Draw_BOB(&small_dug, lpddsback);
  1625.  
  1626.     } // end for index
  1627.  
  1628. } // end Draw_Info
  1629.  
  1630. ///////////////////////////////////////////////////////////////
  1631.  
  1632. int Draw_Bitmap2(BITMAP_IMAGE_PTR source_bitmap,UCHAR *dest_buffer, int lpitch, int transparent)
  1633. {
  1634. // this function draws the bitmap onto the destination memory surface
  1635. // if transparent is 1 then color 0 will be transparent
  1636. // note this function does NOT clip, so be carefull!!!
  1637.  
  1638. UCHAR *dest_addr,   // starting address of bitmap in destination
  1639.       *source_addr; // starting adddress of bitmap data in source
  1640.  
  1641. UCHAR pixel;        // used to hold pixel value
  1642.  
  1643. int index,          // looping vars
  1644.     pixel_x;
  1645.  
  1646. // test if this bitmap is loaded
  1647.  
  1648. if (source_bitmap->attr & BITMAP_ATTR_LOADED)
  1649.    {
  1650.    // compute starting destination address
  1651.    dest_addr = dest_buffer + (int)source_bitmap->y*lpitch + (int)source_bitmap->x;
  1652.  
  1653.    // compute the starting source address
  1654.    source_addr = source_bitmap->buffer;
  1655.  
  1656.    // is this bitmap transparent
  1657.    if (transparent)
  1658.    {
  1659.    // copy each line of bitmap into destination with transparency
  1660.    for (index=0; index<source_bitmap->height; index++)
  1661.        {
  1662.        // copy the memory
  1663.        for (pixel_x=0; pixel_x<source_bitmap->width; pixel_x++)
  1664.            {
  1665.            if ((pixel = source_addr[pixel_x])!=0)
  1666.                dest_addr[pixel_x] = pixel;
  1667.  
  1668.            } // end if
  1669.  
  1670.        // advance all the pointers
  1671.        dest_addr   += lpitch;
  1672.        source_addr += source_bitmap->width;
  1673.  
  1674.        } // end for index
  1675.    } // end if
  1676.    else
  1677.    {
  1678.    // non-transparent version
  1679.    // copy each line of bitmap into destination
  1680.  
  1681.    int lwidth = source_bitmap->width;
  1682.    int lheight = source_bitmap->height;
  1683.  
  1684.        _asm 
  1685.            {
  1686.            mov edx, lheight               // counter = height
  1687.        
  1688.            copy_loop:
  1689.  
  1690.            mov edi, dest_addr             // set destination address
  1691.            mov esi, source_addr           // set source address 
  1692.            mov ecx, lwidth                // set number of bytes
  1693.            shr ecx, 2                     // compute number of quads     
  1694.            rep movsd                      // perform movement
  1695.  
  1696.            mov eax, lpitch                // dest+=lpitch
  1697.            add dest_addr, eax
  1698.            
  1699.            mov ebx, lwidth                // source+=lwidth
  1700.            add source_addr, ebx
  1701.  
  1702.            dec edx                        // if edx > 0 loop
  1703.            jne copy_loop
  1704.            
  1705.            } // end asm      
  1706.  
  1707.  
  1708.    } // end else
  1709.  
  1710.    // return success
  1711.    return(1);
  1712.  
  1713.    } // end if
  1714. else
  1715.    return(0);
  1716.  
  1717. } // end Draw_Bitmap2
  1718.  
  1719. ////////////////////////////////////////////////////////////////////
  1720.  
  1721. int Get_Line(char *string, FILE *fp)
  1722. {
  1723. // this is a little helper function that reads until it finds a line
  1724.  
  1725. // find data line, skip blank lines
  1726. while(1)
  1727.      {
  1728.      // get the current line
  1729.      if (!fgets(string, 80, fp))
  1730.         return(0);
  1731.  
  1732.      // we have a string, now test if it's good
  1733.      for (int scan=0; scan < strlen(string); scan++)
  1734.          {
  1735.          if (string[scan]=='<' || string[scan]=='.')
  1736.             {
  1737.             // found a good string, so return success
  1738.             return(1);
  1739.             } // end if
  1740.          else
  1741.          if (string[scan]=='#')
  1742.             break;
  1743.  
  1744.          } // end if
  1745.  
  1746.      } // end while
  1747.  
  1748. // return error
  1749. return(0);
  1750.  
  1751. } // end Get_Line
  1752.  
  1753. /////////////////////////////////////////////////////////////////////
  1754.  
  1755. int Parse_Value(char *source, char *value)
  1756. {
  1757. // this function scans for the value between the " symbol
  1758.  
  1759. int start = 0,   // start of value
  1760.     end   = 0;   // end of value
  1761.  
  1762. // find first quote
  1763. while((source[start]!='"') && (start < strlen(source)))
  1764.      start++;
  1765.  
  1766. // test for error
  1767. if (start >= strlen(source))
  1768.    return(0);
  1769.  
  1770. // set scanner right after 
  1771. end = ++start;
  1772.  
  1773. // find second quote
  1774. while((source[end]!='"') && (end < strlen(source)))
  1775.      end++;
  1776.  
  1777. // test for error
  1778. if (end >= strlen(source))
  1779.    return(0);
  1780.  
  1781. // now value is trapped from start to end inclusive
  1782. memcpy(value, &source[start], end-start);
  1783.  
  1784. // null terminate
  1785. value[end-start] = 0;
  1786.  
  1787. // return success
  1788. return(1);
  1789.  
  1790. } // end Parse_Value
  1791.  
  1792. /////////////////////////////////////////////////////////////////////
  1793.  
  1794. int Load_Levels(char *level_filename)
  1795. {
  1796. // this function loads the level file data into the level array
  1797.  
  1798. FILE *fp_level;   // used to open level file
  1799. char string[80],  // data string
  1800.      value[80];   // value string
  1801.  
  1802. // open file
  1803. if ((fp_level = fopen(level_filename,"r"))==NULL)
  1804.    {
  1805.    // return error
  1806.    return(0);
  1807.    } // end if
  1808.  
  1809. // load in the number of levels
  1810. if (!Get_Line(string, fp_level)) return(0);
  1811. if (!Parse_Value(string,value)) return(0);
  1812.  
  1813. // set number of levels
  1814. num_levels = atoi(value);
  1815.  
  1816. Write_Error("\nNumber of levels = %d",num_levels);
  1817.  
  1818. #if 0
  1819. // this contains the data of a single level
  1820. typedef struct LEVEL_REC_TYP
  1821.         {
  1822.         char level_name[80]; // name if level
  1823.         char image_file[80]; // file name of .BMP file containing image
  1824.         char author[80];     // name of author
  1825.         int  bonus;          // special bonus for level
  1826.         int  diff;           // difficulty of level from 1 to 100
  1827.  
  1828.         CHAR data[LEVEL_ROWS][LEVEL_COLUMNS]; // level data
  1829.  
  1830.         } LEVEL_REC, *LEVEL_REC_PTR;
  1831.  
  1832. #endif
  1833.  
  1834. // now load all thel levels in
  1835. for (int curr_level = 0; curr_level < num_levels; curr_level++)
  1836.     {
  1837.     // first load the level name
  1838.     if (!Get_Line(string, fp_level)) return(0);
  1839.     if (!Parse_Value(string,value)) return(0);
  1840.     strcpy(game_levels[curr_level].level_name,value);
  1841.  
  1842.     Write_Error("\nLevel name = %s", game_levels[curr_level].level_name);    
  1843.  
  1844.     // now load the name of the file containing bitmap
  1845.     if (!Get_Line(string, fp_level)) return(0);
  1846.     if (!Parse_Value(string,value)) return(0);
  1847.     strcpy(game_levels[curr_level].image_file,value);
  1848.  
  1849.     Write_Error("\nimage file = %s", game_levels[curr_level].image_file);  
  1850.  
  1851.     // now the author
  1852.     if (!Get_Line(string, fp_level)) return(0);
  1853.     if (!Parse_Value(string,value)) return(0);    
  1854.     strcpy(game_levels[curr_level].author,value); 
  1855.  
  1856.     Write_Error("\nauthor name = %s", game_levels[curr_level].author);    
  1857.   
  1858.     // the bonus
  1859.     if (!Get_Line(string, fp_level)) return(0);
  1860.     if (!Parse_Value(string,value)) return(0);
  1861.     game_levels[curr_level].bonus = atoi(value);
  1862.   
  1863.     Write_Error("\nbonus = %d", game_levels[curr_level].bonus);    
  1864.  
  1865.     // the difficulty level
  1866.     if (!Get_Line(string, fp_level)) return(0);
  1867.     if (!Parse_Value(string,value)) return(0);    
  1868.     game_levels[curr_level].diff = atoi(value);
  1869.     Write_Error("\ndiff = %d\n", game_levels[curr_level].diff);    
  1870.  
  1871.     // load level data itself
  1872.     for (int row=0, start=0; row < LEVEL_ROWS; row++)
  1873.         {
  1874.         // load the next line of data
  1875.         if (!Get_Line(string, fp_level)) return(0);
  1876.         
  1877.         // kill any whitespace
  1878.         start = 0;
  1879.         while(isspace(string[start]))
  1880.              start++;      
  1881.  
  1882.         strcpy(buffer, &string[start]);
  1883.         Write_Error(buffer);
  1884.  
  1885.         // copy data into array
  1886.         memcpy(game_levels[curr_level].data[row], &string[start], 16);
  1887.  
  1888.         } // end for row
  1889.  
  1890.     } // end for curr_level
  1891.  
  1892. // close the level file
  1893. fclose(fp_level);
  1894.  
  1895. // return success
  1896. return(1);
  1897.  
  1898. } // end Load_Levels
  1899.  
  1900. ///////////////////////////////////////////////////////////////
  1901.  
  1902. int Start_Level(int level)
  1903. {
  1904. // this function starts a level up and resets everything
  1905.  
  1906. // reset everything
  1907. level_name_counter = 75;
  1908.  
  1909. // set current level
  1910. curr_level = level;
  1911.  
  1912. // load image
  1913. Load_Bitmap_File(&bitmap8bit, game_levels[level].image_file);
  1914.  
  1915. // scan image into bitmap
  1916. Load_Image_Bitmap(&background_bmp,&bitmap8bit,0,0,BITMAP_EXTRACT_MODE_ABS);
  1917.  
  1918. // draw display header info
  1919. Draw_String(font,"PSI",SCORE_X+136,SCORE_Y,background_bmp.buffer, SCREEN_WIDTH,0);
  1920. Draw_String(font,"HIGH SCORE",SCORE_X+240,SCORE_Y,background_bmp.buffer, SCREEN_WIDTH,0);
  1921. Draw_String(font,"LEVEL",SCORE_X+500,SCORE_Y,background_bmp.buffer, SCREEN_WIDTH,0);
  1922. Draw_String(font,"Rads",SCORE_X-16,SCORE_Y+16,background_bmp.buffer, SCREEN_WIDTH,0);
  1923.  
  1924. // unload object bitmap
  1925. Unload_Bitmap_File(&bitmap8bit);
  1926.  
  1927. // process level data: dig holes, place objects
  1928. for (int row=0; row < LEVEL_ROWS; row++)
  1929.     {
  1930.     for (int col=0; col < LEVEL_COLUMNS; col++)
  1931.         {
  1932.         // get data values
  1933.         char data = game_levels[level].data[row][col];        
  1934.     
  1935.         // what is the data object
  1936.         switch(data)
  1937.               {
  1938.               case OBJECT_ID_ROCK:
  1939.                    {
  1940.                    // start a rock
  1941.                    Start_Rock(0 + col*40,64+24 + row*40);
  1942.  
  1943.                    } break;
  1944.  
  1945.               case OBJECT_ID_POO: 
  1946.               case OBJECT_ID_PUFF: 
  1947.                    {
  1948.                    // increase number of creatures on level
  1949.                    num_creatures_on_level++;                   
  1950.                    
  1951.                    // dig a horizontal tunnel segment
  1952.                    dug_holes[HOLE_INDEX_H].x = 0  + col*40;
  1953.                    dug_holes[HOLE_INDEX_H].y = 64+8 + row*40;
  1954.                    Draw_Bitmap(&dug_holes[HOLE_INDEX_H],background_bmp.buffer,background_bmp.width,1);
  1955.                    
  1956.                    // test if there is a segment downward
  1957.                    char data_dx;
  1958.                    
  1959.                    if (col < LEVEL_COLUMNS-1)
  1960.                    {
  1961.                       data_dx = game_levels[level].data[row][col+1]; 
  1962.                    
  1963.                    // is the index directly under another vertical or horizontal hole
  1964.                    if ((data_dx==OBJECT_ID_VHOLE) ||  
  1965.                        (data_dx==OBJECT_ID_HHOLE) || 
  1966.                        (data_dx==OBJECT_ID_POO)   || 
  1967.                        (data_dx==OBJECT_ID_PUFF))
  1968.                       {    
  1969.                       // draw inbetween chunk
  1970.                       dug_holes[HOLE_INDEX_H].x = 0  + col*40 + 16;
  1971.                       dug_holes[HOLE_INDEX_H].y = 64+8 + row*40;
  1972.                       Draw_Bitmap(&dug_holes[HOLE_INDEX_H],background_bmp.buffer,background_bmp.width,1);
  1973.                       } // end if
  1974.  
  1975.                    } // end if
  1976.  
  1977.                    // test if there is a segment downward
  1978.                    char data_dy;
  1979.                    
  1980.                    if (row < LEVEL_ROWS-1)
  1981.                    {
  1982.                    data_dy = game_levels[level].data[row+1][col]; 
  1983.  
  1984.                    // is the index directly under another vertical or horizontal hole
  1985.                    if ((data_dy==OBJECT_ID_VHOLE) ||  
  1986.                        (data_dy==OBJECT_ID_HHOLE) || 
  1987.                        (data_dy==OBJECT_ID_POO)   || 
  1988.                        (data_dy==OBJECT_ID_PUFF))                      
  1989.                       {    
  1990.                       // draw inbetween chunk
  1991.                       dug_holes[HOLE_INDEX_V].x = 0  + col*40;
  1992.                       dug_holes[HOLE_INDEX_V].y = 64+8 + row*40 + 16;
  1993.                       Draw_Bitmap(&dug_holes[HOLE_INDEX_V],background_bmp.buffer,background_bmp.width,1);
  1994.                       } // end if
  1995.  
  1996.                     } // end if
  1997.  
  1998.                    // test for poo
  1999.                    if (data==OBJECT_ID_POO)
  2000.                       {
  2001.                       int sx = col*40,
  2002.                           sy = 64+8 + row*40;
  2003.                
  2004.                      // start a poo in the right direction
  2005.                      if (Get_Pixel(sx - 2,sy + 16,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  2006.                         Start_Poo(sx,sy, DIR_LEFT); 
  2007.                      else
  2008.                      if (Get_Pixel(sx + 34,sy + 16,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  2009.                         Start_Poo(sx,sy, DIR_RIGHT); 
  2010.                      else
  2011.                      if (Get_Pixel(sx + 16,sy - 2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  2012.                         Start_Poo(sx,sy, DIR_UP); 
  2013.                      else
  2014.                      if (Get_Pixel(sx + 16,sy + 34,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  2015.                         Start_Poo(sx,sy, DIR_DOWN); 
  2016.                      else
  2017.                         Start_Poo(sx,sy, rand()%4); 
  2018.  
  2019.                       } // end if
  2020.                    else         
  2021.                    if (data==OBJECT_ID_PUFF)
  2022.                       {
  2023.                       int sx = col*40,
  2024.                           sy = 64+8 + row*40;
  2025.                
  2026.                      // start a puff in the right direction
  2027.                      if (Get_Pixel(sx - 2,sy + 16,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  2028.                         Start_Puff(sx,sy, DIR_LEFT); 
  2029.                      else
  2030.                      if (Get_Pixel(sx + 34,sy + 16,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  2031.                         Start_Puff(sx,sy, DIR_RIGHT); 
  2032.                      else
  2033.                      if (Get_Pixel(sx + 16,sy - 2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  2034.                         Start_Puff(sx,sy, DIR_UP); 
  2035.                      else
  2036.                      if (Get_Pixel(sx + 16,sy + 34,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  2037.                         Start_Puff(sx,sy, DIR_DOWN); 
  2038.                      else
  2039.                         Start_Puff(sx,sy,rand()%4);
  2040.   
  2041.                       } // end if
  2042.  
  2043.                    } break;
  2044.  
  2045.               case OBJECT_ID_VHOLE:
  2046.                    {
  2047.                    // dig a vertical tunnel segment
  2048.                    dug_holes[HOLE_INDEX_V].x = 0  + col*40;
  2049.                    dug_holes[HOLE_INDEX_V].y = 64+8 + row*40;
  2050.                    Draw_Bitmap(&dug_holes[HOLE_INDEX_V],background_bmp.buffer,background_bmp.width,1);
  2051.  
  2052.                    // test if there is a segment downward
  2053.                    char data_dy;
  2054.                    
  2055.                    if (row < LEVEL_ROWS-1)
  2056.                       data_dy = game_levels[level].data[row+1][col]; 
  2057.                    else
  2058.                       break;
  2059.  
  2060.                    // is the index directly under another vertical or horizontal hole
  2061.                    if ((data_dy==OBJECT_ID_VHOLE) ||  
  2062.                        (data_dy==OBJECT_ID_HHOLE) || 
  2063.                        (data_dy==OBJECT_ID_POO)   || 
  2064.                        (data_dy==OBJECT_ID_PUFF))                      
  2065.                       {    
  2066.                       // draw inbetween chunk
  2067.                       dug_holes[HOLE_INDEX_V].y +=16;
  2068.                       Draw_Bitmap(&dug_holes[HOLE_INDEX_V],background_bmp.buffer,background_bmp.width,1);
  2069.                       } // end if
  2070.  
  2071.                    } break;
  2072.  
  2073.               case OBJECT_ID_HHOLE:
  2074.                    {
  2075.                    // dig a horizontal tunnel segment
  2076.                    dug_holes[HOLE_INDEX_H].x = 0  + col*40;
  2077.                    dug_holes[HOLE_INDEX_H].y = 64+8 + row*40;
  2078.                    Draw_Bitmap(&dug_holes[HOLE_INDEX_H],background_bmp.buffer,background_bmp.width,1);
  2079.                    
  2080.                    // test if there is a segment downward
  2081.                    char data_dx;
  2082.                    
  2083.                    if (col < LEVEL_COLUMNS-1)
  2084.                       data_dx = game_levels[level].data[row][col+1]; 
  2085.                    else
  2086.                       break;
  2087.  
  2088.                    // is the index directly under another vertical or horizontal hole
  2089.                    if ((data_dx==OBJECT_ID_VHOLE) ||  
  2090.                        (data_dx==OBJECT_ID_HHOLE) || 
  2091.                        (data_dx==OBJECT_ID_POO)   || 
  2092.                        (data_dx==OBJECT_ID_PUFF))
  2093.                       {    
  2094.                       // draw inbetween chunk
  2095.                       dug_holes[HOLE_INDEX_H].x +=16;
  2096.                       Draw_Bitmap(&dug_holes[HOLE_INDEX_H],background_bmp.buffer,background_bmp.width,1);
  2097.                       } // end if
  2098.  
  2099.                    } break;
  2100.               
  2101.               default: break;
  2102.  
  2103.               } // end switch
  2104.         
  2105.         } // end for col
  2106.  
  2107.     } // end for row
  2108.  
  2109. // return success
  2110. return(1);
  2111.  
  2112. } // end Start_Level
  2113.  
  2114. ///////////////////////////////////////////////////////////////
  2115.  
  2116. int Start_Rock(int x, int y)
  2117. {
  2118. // this function starts a rock
  2119.  
  2120. for (int rindex = 0; rindex < NUM_ROCKS; rindex++)
  2121.     {
  2122.     // is this rock dead?
  2123.     if (rocks[rindex].state == ROCK_STATE_DEAD)
  2124.        {
  2125.        // compute position of new rock
  2126.        rocks[rindex].x =  x;
  2127.        rocks[rindex].y =  y;
  2128.  
  2129.        // set state of rock
  2130.        rocks[rindex].state = ROCK_STATE_STABLE;
  2131.        rocks[rindex].anim_state = 0;
  2132.                           
  2133.        // set current frame of rock
  2134.        rocks[rindex].curr_frame = 0;
  2135.                                 
  2136.        // set number of rocks dropped to 0
  2137.     
  2138.        // note the use of rocks[0] to store the global
  2139.        rocks[0].varsI[8] = 0;
  2140.                      
  2141.       // success, so exit case
  2142.       return(rindex);
  2143.  
  2144.       } // end if
  2145.  
  2146.    } // end for rindex
  2147.  
  2148. // return failure
  2149. return(0);
  2150.  
  2151. } // end Start_Rock
  2152.  
  2153. //////////////////////////////////////////////////////////////////
  2154.  
  2155. int Process_Rocks(void)
  2156. {
  2157. // this function process all the rocks
  2158. for (int index=0; index < NUM_ROCKS; index++)
  2159.     {
  2160.     // test state of rock
  2161.     switch(rocks[index].state)
  2162.           {
  2163.           case ROCK_STATE_DEAD: 
  2164.                break;
  2165.  
  2166.           case ROCK_STATE_STABLE:
  2167.                {
  2168.                // check if it's time to shake!
  2169.                
  2170.                // compute sample position
  2171.                int sx = rocks[index].x;
  2172.                int sy = rocks[index].y + 32+6;
  2173.  
  2174.                // test samples 
  2175.                if ( (Get_Pixel(sx+2,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) ||
  2176.                     (Get_Pixel(sx+6,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) ||
  2177.                     (Get_Pixel(sx+10,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) ||
  2178.                     (Get_Pixel(sx+16,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) ||
  2179.                     (Get_Pixel(sx+22,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) ||
  2180.                     (Get_Pixel(sx+26,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) ||
  2181.                     (Get_Pixel(sx+30,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) )
  2182.                    {
  2183.                    // nothing there
  2184.                    break;
  2185.  
  2186.                    } // end if
  2187.                else
  2188.                     {
  2189.                     // last test to see if dug is in the way?
  2190.                     int dx = abs(dug.x - rocks[index].x);
  2191.                     int dy = abs(dug.y - rocks[index].y);
  2192.  
  2193.                     // test how far dug is
  2194.                     if (dx >=4 || dy >= 34)
  2195.                         {
  2196.                         // save current position for shaking algorithm
  2197.                         // in 0,1 
  2198.                         rocks[index].varsI[0] = rocks[index].x;
  2199.                         rocks[index].varsI[1] = rocks[index].y;
  2200.  
  2201.                         // set shake count
  2202.                         rocks[index].counter_1 = ROCK_COUNT_SHAKE;           
  2203.  
  2204.                         // set new state
  2205.                         rocks[index].state = ROCK_STATE_SHAKING;
  2206.  
  2207.                         // start sound
  2208.                         Play_Sound_From_Pool(fall_snd_ids, 4);
  2209.  
  2210.                         } // end if
  2211.  
  2212.                    } // end else
  2213.  
  2214.                } break;
  2215.  
  2216.           case ROCK_STATE_SHAKING:
  2217.                {
  2218.                // shake rock randomly
  2219.                rocks[index].x = rocks[index].varsI[0]-2+rand()%5;
  2220.                rocks[index].y = rocks[index].varsI[1]-2+rand()%5;
  2221.    
  2222.                // decrement shaking counter
  2223.                if (--rocks[index].counter_1 < 0)
  2224.                   {
  2225.                   // switch states to falling
  2226.                   //...
  2227.   
  2228.                   // set new state to falling
  2229.                   rocks[index].state = ROCK_STATE_FALLING;
  2230.  
  2231.                   // set gravity
  2232.                   rocks[index].varsF[0] = ROCK_INIT_VELOCITY;
  2233.  
  2234.                   // reset initial position
  2235.                   rocks[index].x = rocks[index].varsI[0];
  2236.                   rocks[index].y = rocks[index].varsI[1];
  2237.  
  2238.                   } // end if
  2239.  
  2240.                } break;
  2241.  
  2242.           case ROCK_STATE_FALLING:     
  2243.                {
  2244.                // test if rock has hit bottom
  2245.                int sx = rocks[index].x;
  2246.                int sy = rocks[index].y + 32;
  2247.  
  2248.                // test samples 
  2249.                if ( (Get_Pixel(sx+6,sy,background_bmp.buffer,  background_bmp.width)!=COLOR_INDEX_HOLE) ||
  2250.                     (Get_Pixel(sx+16,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) ||
  2251.                     (Get_Pixel(sx+26,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE) ||
  2252.                     rocks[index].y >= (SCREEN_HEIGHT - 32))
  2253.                     {
  2254.                     // stop rock, it's stable
  2255.                     rocks[index].state = ROCK_STATE_CRUMBLING;
  2256.          
  2257.                     // start sound
  2258.                     Play_Sound_From_Pool(crumble_snd_ids, 4);
  2259.  
  2260.                     } // end if
  2261.                else
  2262.                     {
  2263.                     // move rock
  2264.                     rocks[index].y+=rocks[index].varsF[0];
  2265.  
  2266.                     // apply gravity    
  2267.                     rocks[index].varsF[0]+=ROCK_GRAVITY;
  2268.       
  2269.                     }
  2270.  
  2271.                } break;
  2272.  
  2273.           case ROCK_STATE_CRUMBLING:        
  2274.                {
  2275.                // just let the animation do it's thing
  2276.                }  break;
  2277.  
  2278.           default: break;
  2279.  
  2280.           } // end switch
  2281.  
  2282.     } // end for index
  2283.  
  2284. // return success
  2285. return(1);
  2286.  
  2287. } // end Process_Rocks
  2288.  
  2289. ///////////////////////////////////////////////////////////////
  2290.  
  2291. int Draw_Rocks(void)
  2292. {
  2293. // this function draws and animates all the rocks
  2294.  
  2295. for (int index=0; index<NUM_ROCKS; index++)
  2296.     {
  2297.     // test state of rock
  2298.     switch(rocks[index].state)
  2299.           {
  2300.           case ROCK_STATE_DEAD: 
  2301.                break;
  2302.  
  2303.           case ROCK_STATE_STABLE:
  2304.           case ROCK_STATE_SHAKING:
  2305.           case ROCK_STATE_FALLING:     
  2306.             {
  2307.             // draw the first frame only
  2308.             Draw_BOB(&rocks[index],lpddsback);
  2309.  
  2310.             } break;
  2311.  
  2312.           case ROCK_STATE_CRUMBLING:        
  2313.             {
  2314.             // draw the bob
  2315.             Draw_BOB(&rocks[index],lpddsback);
  2316.  
  2317.             // animate the bob
  2318.             Animate_BOB2(&rocks[index]);
  2319.  
  2320.             // test if animation is done
  2321.             if (rocks[index].anim_state == BOB_STATE_ANIM_DONE)
  2322.                {
  2323.                // kill the rock
  2324.                rocks[index].state = ROCK_STATE_DEAD;
  2325.                rocks[index].anim_state = 0;
  2326.                // send message to add up score
  2327.                //...
  2328.                
  2329.                // increment number of rocks dropped
  2330.                if (++rocks[0].varsI[8] == ROCKS_DROP_FOR_PRIZE)
  2331.                   Init_Prize(rand()%NUM_PRIZES,PRIZE_DISPLAY_TIME);              
  2332.  
  2333.  
  2334.                } // end if
  2335.  
  2336.             } break;
  2337.  
  2338.           default: break;
  2339.  
  2340.           } // end switch
  2341.  
  2342.     } // end for index
  2343.  
  2344. // return success
  2345. return(1);
  2346.  
  2347. } // end Draw_Rocks
  2348.  
  2349. ///////////////////////////////////////////////////////////////
  2350.  
  2351. int Init_Prize(int prize_index, int count)
  2352. {
  2353. // this function initializes a prize to be displayed
  2354.  
  2355. // prize 0 is the control bob and the remaining prize bobs are slaves
  2356. prizes[0].state     = PRIZE_STATE_ON; 
  2357. prizes[0].counter_1 = count; 
  2358. prizes[0].varsI[0]  = prize_index; // store this for later use
  2359.  
  2360. // make sound
  2361. Play_Sound(prize_out_snd_id);
  2362.  
  2363. // return success
  2364. return(1);
  2365.  
  2366. } // end Init_Prize
  2367.  
  2368. ////////////////////////////////////////////////////////////////
  2369.  
  2370. int Process_Prize(void)
  2371. {
  2372. // this function processes a prize and tests if it is picked up by
  2373. // the player
  2374.  
  2375. // is prize out?
  2376. if (prizes[0].state == PRIZE_STATE_OFF)
  2377.     return(0);
  2378.  
  2379. // test for collision with player
  2380. if (Collision_BOBS(&dug, &prizes[0]))
  2381.     {
  2382.     // add in score and display
  2383.     dug.varsI[DUG_INDEX_SCORE]+=prizes[prizes[0].varsI[0]].varsI[1];
  2384.  
  2385.     // display a score
  2386.     Start_Score(prizes[0].x+16,prizes[0].y+16, prizes[prizes[0].varsI[0]].varsI[1]);
  2387.  
  2388.     // play win prize sound
  2389.     Play_Sound(prize_win_snd_id);
  2390.     
  2391.     // terminate the prize
  2392.     prizes[0].state     = PRIZE_STATE_OFF; 
  2393.     prizes[0].counter_1 = 0; 
  2394.     prizes[0].varsI[0]  = 0;
  2395.  
  2396.     // return terminate
  2397.     return(1);
  2398.     
  2399.     } // end if
  2400.  
  2401. // update and terminate?
  2402. if (--prizes[0].counter_1 < 0)
  2403.    {
  2404.    // terminate the prize -- too bad!
  2405.    prizes[0].state     = PRIZE_STATE_OFF; 
  2406.    prizes[0].counter_1 = 0; 
  2407.    prizes[0].varsI[0]  = 0;
  2408.  
  2409.    // return terminate
  2410.    return(0);
  2411.  
  2412.    } // end if
  2413.  
  2414. // return success
  2415. return(1);
  2416.  
  2417. } // end Process_Prize
  2418.  
  2419. ///////////////////////////////////////////////////////////////
  2420.  
  2421. int Draw_Prize(void)
  2422. {
  2423. // this function draws the prize (if there is one)
  2424.  
  2425. // is prize out?
  2426. if (prizes[0].state == PRIZE_STATE_OFF)
  2427.     return(0);
  2428.  
  2429. // extract the active prize
  2430. int active_prize = prizes[0].varsI[0];
  2431.  
  2432. // draw the prize
  2433. Draw_BOB(&prizes[active_prize], lpddsback);
  2434.  
  2435. // animate the prize
  2436. Animate_BOB(&prizes[active_prize]);
  2437.  
  2438. // return success
  2439. return(1);
  2440.  
  2441. } // end Draw_Prize
  2442.  
  2443. ////////////////////////////////////////////////////////////
  2444.  
  2445. int Start_Fball(int x, int y, int dir, int fball_type = FBALL_TYPE_RED)
  2446. {
  2447.     // this function starts a fire ball from the given position and direction
  2448.  
  2449.     // scan for an unused fire ball
  2450.     for (int index=0; index < NUM_FBALLS; index++)
  2451.         {
  2452.         // test if this fire ball is usuable
  2453.         if (fballs[index].state==FBALL_STATE_DEAD)
  2454.            {
  2455.            // set the fire ball up
  2456.            fballs[index].state      = FBALL_STATE_MOVING;
  2457.            fballs[index].anim_state = 0;
  2458.            fballs[index].x          = x;
  2459.            fballs[index].y          = y;
  2460.  
  2461.            // play sound
  2462.            Play_Sound_From_Pool(fball_snd_ids,4);
  2463.  
  2464.            // talk shit
  2465.            if (rand()%10==1)
  2466.               Play_Sound(puff_talk_snd_ids[rand()%4]);
  2467.  
  2468.            // select velocity and animation based on direction
  2469.            switch(dir)
  2470.                  {
  2471.                  case DIR_RIGHT:
  2472.                       {
  2473.                       // set velocity
  2474.                       fballs[index].xv = FBALL_SPEED;
  2475.                       fballs[index].yv = 0;
  2476.  
  2477.                       // set animation
  2478.                       Set_Animation_BOB2(&fballs[index], fball_type*2);
  2479.  
  2480.                       } break;
  2481.  
  2482.                  case DIR_LEFT:
  2483.                       {
  2484.                       // set velocity
  2485.                       fballs[index].xv = -FBALL_SPEED;
  2486.                       fballs[index].yv = 0;
  2487.  
  2488.                       // set animation
  2489.                       Set_Animation_BOB2(&fballs[index], fball_type*2);
  2490.  
  2491.                       } break;
  2492.  
  2493.                  case DIR_UP:
  2494.                       {
  2495.                       // set velocity
  2496.                       fballs[index].xv = 0;
  2497.                       fballs[index].yv = -FBALL_SPEED;
  2498.  
  2499.                       // set animation
  2500.                       Set_Animation_BOB2(&fballs[index], fball_type*2);
  2501.                   
  2502.                       } break;
  2503.  
  2504.                  case DIR_DOWN:
  2505.                       {
  2506.                       // set velocity
  2507.                       fballs[index].xv = 0;
  2508.                       fballs[index].yv = FBALL_SPEED;
  2509.  
  2510.                       // set animation
  2511.                       Set_Animation_BOB2(&fballs[index], fball_type*2);
  2512.                   
  2513.                       } break;
  2514.  
  2515.                  default:break;
  2516.  
  2517.                  } // end switch
  2518.  
  2519.            // return success
  2520.            return(1);
  2521.  
  2522.            } // end if
  2523.  
  2524.         } // end for index
  2525.  
  2526.     // return failure
  2527.     return(0);
  2528.  
  2529.     } // end Start_Fball
  2530.  
  2531.     ///////////////////////////////////////////////////////////////
  2532.  
  2533.     int Process_Fballs(void)
  2534.     {
  2535.     // this functions processes all the fballs, moves, and tests for collisions
  2536.  
  2537.     // process all fire balls
  2538.     for (int index=0; index < NUM_FBALLS; index++)
  2539.         {
  2540.         // test if this fire ball is active
  2541.         if (fballs[index].state==FBALL_STATE_MOVING)
  2542.            {
  2543.            // move fire ball
  2544.            Move_BOB(&fballs[index]);
  2545.  
  2546.            // test for gravity
  2547.            if ((int)fballs[index].yv==0 && (((int)fballs[index].y-2) % DUG_X_INTERVAL))
  2548.                fballs[index].y++;
  2549.  
  2550.            // test for hit with offscreen
  2551.            if (fballs[index].x > SCREEN_WIDTH-16  || fballs[index].x <= 0 ||
  2552.                fballs[index].y > SCREEN_HEIGHT-16 || fballs[index].y <= 0 ) // DUG_MIN_ROCK_LINE)
  2553.              {
  2554.              // put fireball into dying state and switch animation sequence
  2555.              fballs[index].state = FBALL_STATE_EXPLODING;
  2556.  
  2557.              // play explosion sound
  2558.              Play_Sound_From_Pool(expl_snd_ids,4);
  2559.          
  2560.              // set animation
  2561.              Set_Animation_BOB2(&fballs[index], fballs[index].curr_animation+1);
  2562.  
  2563.              // reset animation state
  2564.              fballs[index].anim_state = 0;
  2565.  
  2566.              // process next
  2567.              continue;
  2568.  
  2569.              } // end if
  2570.  
  2571.            // only test in lower region
  2572.            if (fballs[index].y >= DUG_MIN_ROCK_LINE)
  2573.                {
  2574.                // test for material hit
  2575.                int sx = fballs[index].x+8;
  2576.                int sy = fballs[index].y+8;
  2577.  
  2578.                // test sample
  2579.                if (Get_Pixel(sx,sy,background_bmp.buffer,background_bmp.width)!=COLOR_INDEX_HOLE)
  2580.                    {
  2581.                    // put fireball into dying state and switch animation sequence
  2582.                    fballs[index].state = FBALL_STATE_EXPLODING;
  2583.       
  2584.                    // play explosion sound
  2585.                    Play_Sound_From_Pool(expl_snd_ids,4);
  2586.  
  2587.                    // set animation
  2588.                    Set_Animation_BOB2(&fballs[index], fballs[index].curr_animation+1);
  2589.  
  2590.                    // reset animation state
  2591.                    fballs[index].anim_state = 0;
  2592.  
  2593.                    // process next
  2594.                    continue;
  2595.  
  2596.                    } // end if
  2597.  
  2598.                 } // end if
  2599.  
  2600.            // test for collisions here
  2601.            if (dug.state == DUG_STATE_ALIVE)
  2602.               {
  2603.               if (Collision_BOBS(&dug,&fballs[index]))
  2604.                  {
  2605.                  // start the death sequence
  2606.                  Start_Dug_Death();
  2607.  
  2608.                  // put fireball into dying state and switch animation sequence
  2609.                  fballs[index].state = FBALL_STATE_EXPLODING;
  2610.  
  2611.                  // play explosion sound
  2612.                  Play_Sound_From_Pool(expl_snd_ids,4);
  2613.          
  2614.                  // set animation
  2615.                  Set_Animation_BOB2(&fballs[index], fballs[index].curr_animation+1);
  2616.  
  2617.                  // reset animation state
  2618.                  fballs[index].anim_state = 0;
  2619.  
  2620.                  } // end if
  2621.               } // end if dug alive
  2622.  
  2623.            } // end if alive
  2624.     
  2625.         } // end for index
  2626.  
  2627.     // return sucess
  2628.     return(1);
  2629.  
  2630.     } // end Process_Fballs
  2631.  
  2632.     ////////////////////////////////////////////////////////////////
  2633.  
  2634.     int Draw_Fballs(void)
  2635.     {
  2636.     // this function draws and animates all the fballs
  2637.     static int blasting = 0;
  2638.  
  2639.     // process all fire balls
  2640.     for (int index=0; index < NUM_FBALLS; index++)
  2641.         {
  2642.         // test if this fire ball is usuable
  2643.         if (fballs[index].state!=FBALL_STATE_DEAD)
  2644.            {
  2645.            // draw the bob first
  2646.            Draw_BOB(&fballs[index], lpddsback);
  2647.  
  2648.            // animate the bob
  2649.            Animate_BOB2(&fballs[index]);
  2650.             
  2651.            // eat rock away
  2652.            if (fballs[index].state==FBALL_STATE_EXPLODING) // && fballs[index].y>=DUG_MIN_ROCK_LINE)
  2653.               {
  2654.               int fcx = fballs[index].x;
  2655.               int fcy = fballs[index].y;
  2656.               int num_chunks = 6 + rand()%6;
  2657.  
  2658.               // destruction
  2659.               for (int chunks=0; chunks < num_chunks; chunks++)
  2660.                   {
  2661.                   int blast_shape = rand()%NUM_FBLASTS;
  2662.  
  2663.                   fblasts[blast_shape].x = fcx - 8 + rand()%17; 
  2664.                   fblasts[blast_shape].y = fcy - 8 + rand()%17;
  2665.     
  2666.                   // clip blast coords
  2667.                   if (fblasts[blast_shape].x >= SCREEN_WIDTH - 16)
  2668.                      fblasts[blast_shape].x = SCREEN_WIDTH - 16;
  2669.                   else
  2670.                   if (fblasts[blast_shape].x < 2)
  2671.                      fblasts[blast_shape].x = 2;
  2672.  
  2673.                   if (fblasts[blast_shape].y < DUG_MIN_ROCK_LINE)
  2674.                      fblasts[blast_shape].y = DUG_MIN_ROCK_LINE;
  2675.                   else
  2676.                   if (fblasts[blast_shape].y >= SCREEN_HEIGHT - 16)
  2677.                      fblasts[blast_shape].y = SCREEN_HEIGHT - 16;
  2678.  
  2679.                   // draw the damage
  2680.                   Draw_Bitmap(&fblasts[blast_shape],background_bmp.buffer,background_bmp.width,1);     
  2681.                   
  2682.                   } // end for chunks
  2683.  
  2684.               } // end if 
  2685.  
  2686.            // test if in dying state
  2687.            if (fballs[index].state==FBALL_STATE_EXPLODING && 
  2688.                fballs[index].anim_state==BOB_STATE_ANIM_DONE)
  2689.               {
  2690.               // your terminated fucker!
  2691.               fballs[index].state=FBALL_STATE_DEAD;
  2692.  
  2693.               } // end if   
  2694.  
  2695.            } // end if
  2696.     
  2697.         } // end for index
  2698.  
  2699.     // return sucess
  2700.     return(1);
  2701.  
  2702. } // end Draw_Fballs
  2703.  
  2704. /////////////////////////////////////////////////////////////////
  2705.  
  2706. int Start_Gpump(int x, int y, int dir)
  2707. {
  2708. // this function starts a grappling pump from the given position and direction
  2709.  
  2710. // scan for an unused pump
  2711. for (int index=0; index < NUM_GPUMPS; index++)
  2712.     {
  2713.     // test if this pump is usuable
  2714.     if (gpumps[index].state==GPUMP_STATE_DEAD)
  2715.        {
  2716.        // set the pump up
  2717.        gpumps[index].state      = GPUMP_STATE_MOVING;
  2718.        gpumps[index].anim_state = 0;
  2719.        gpumps[index].x          = x;
  2720.        gpumps[index].y          = y;
  2721.  
  2722.        // select velocity and animation based on direction
  2723.        switch(dir)
  2724.              {
  2725.              case DIR_RIGHT:
  2726.                   {
  2727.                   // set velocity
  2728.                   gpumps[index].xv = GPUMP_SPEED;
  2729.                   gpumps[index].yv = 0;
  2730.  
  2731.                   // set animation
  2732.                   Set_Animation_BOB2(&gpumps[index], dir);
  2733.  
  2734.                   } break;
  2735.  
  2736.              case DIR_LEFT:
  2737.                   {
  2738.                   // set velocity
  2739.                   gpumps[index].xv = -GPUMP_SPEED;
  2740.                   gpumps[index].yv = 0;
  2741.  
  2742.                   // set animation
  2743.                   Set_Animation_BOB2(&gpumps[index], dir);
  2744.  
  2745.                   } break;
  2746.  
  2747.              case DIR_UP:
  2748.                   {
  2749.                   // set velocity
  2750.                   gpumps[index].xv = 0;
  2751.                   gpumps[index].yv = -GPUMP_SPEED;
  2752.  
  2753.                   // set animation
  2754.                   Set_Animation_BOB2(&gpumps[index], dir);
  2755.  
  2756.                   } break;
  2757.  
  2758.              case DIR_DOWN:
  2759.                   {
  2760.                   // set velocity
  2761.                   gpumps[index].xv = 0;
  2762.                   gpumps[index].yv = GPUMP_SPEED;
  2763.  
  2764.                   // set animation
  2765.                   Set_Animation_BOB2(&gpumps[index], dir);
  2766.  
  2767.                   } break;
  2768.  
  2769.              default:break;
  2770.  
  2771.              } // end switch
  2772.  
  2773.        // start sound
  2774.        Play_Sound_From_Pool(gpump_snd_ids, 4);
  2775.  
  2776.        // return success
  2777.        return(1);
  2778.  
  2779.        } // end if
  2780.  
  2781.     } // end for index
  2782.  
  2783. // return failure
  2784. return(0);
  2785.  
  2786. } // end Start_Gpump
  2787.  
  2788. ///////////////////////////////////////////////////////////////
  2789.  
  2790. int Process_Gpumps(void)
  2791. {
  2792. // this functions processes all the gpumps, moves, and tests for collisions
  2793.  
  2794. // process all pumps
  2795. for (int index=0; index < NUM_GPUMPS; index++)
  2796.     {
  2797.     // test if this pump is usuable
  2798.     if (gpumps[index].state!=GPUMP_STATE_DEAD)
  2799.        {
  2800.        // move pump
  2801.        Move_BOB(&gpumps[index]);
  2802.  
  2803.        // test for hit with offscreen
  2804.        if (gpumps[index].x > SCREEN_WIDTH  || gpumps[index].x < -16 ||
  2805.            gpumps[index].y > SCREEN_HEIGHT || gpumps[index].y < -16)
  2806.          {
  2807.          // kill the pump
  2808.          gpumps[index].state = GPUMP_STATE_DEAD;
  2809.  
  2810.          } // end if
  2811.  
  2812.        // only test in lower region
  2813.        if (gpumps[index].y >= DUG_MIN_ROCK_LINE)
  2814.            {
  2815.            // test for material hit
  2816.            int sx = gpumps[index].x+8;
  2817.            int sy = gpumps[index].y+8;
  2818.  
  2819.            // test sample
  2820.            if (Get_Pixel(sx,sy,background_bmp.buffer,background_bmp.width)!=COLOR_INDEX_HOLE)
  2821.                {
  2822.                // kill the pump
  2823.                gpumps[index].state = GPUMP_STATE_DEAD;
  2824.  
  2825.                } // end if
  2826.  
  2827.             } // end if
  2828.  
  2829.        } // end if alive
  2830.     
  2831.     } // end for index
  2832.  
  2833. // return sucess
  2834. return(1);
  2835.  
  2836. } // end Process_Gpumps
  2837.  
  2838. ////////////////////////////////////////////////////////////////
  2839.  
  2840. int Draw_Gpumps(void)
  2841. {
  2842. // this function draws and animates all the gpumps
  2843. // process all pumps
  2844. for (int index=0; index < NUM_GPUMPS; index++)
  2845.     {
  2846.     // test if this pump is usuable
  2847.     if (gpumps[index].state!=GPUMP_STATE_DEAD)
  2848.        {
  2849.        // draw the bob first
  2850.        Draw_BOB(&gpumps[index], lpddsback);
  2851.  
  2852.        // animate the bob
  2853.        Animate_BOB(&gpumps[index]);
  2854.  
  2855.        } // end if
  2856.     
  2857.     } // end for index
  2858.  
  2859. // return sucess
  2860. return(1);
  2861.  
  2862. } // end Draw_Gpumps
  2863.  
  2864. ///////////////////////////////////////////////////////////////
  2865.  
  2866. int Start_Poo(int x, int y, int dir)
  2867. {
  2868. // this function attempts to start a poo up with the desired
  2869. // position and direction
  2870.  
  2871. int index; // looping index
  2872.  
  2873. // find an unused poo
  2874. for (index=0; index < NUM_POOS; index++)
  2875.     {
  2876.     // is poo this available
  2877.     if (poos[index].state == POO_STATE_DEAD)
  2878.        {
  2879.        // set poo up
  2880.        poos[index].state                        = POO_STATE_ALIVE;
  2881.        poos[index].varsI[POO_INDEX_AI_STATE]    = POO_AI_STATE_EXPLORE;
  2882.        poos[index].varsI[POO_INDEX_ANIM_STATE]  = POO_ANIM_STATE_BOUNCE; 
  2883.        poos[index].varsI[POO_INDEX_CURR_DIR]    = dir;
  2884.        poos[index].varsI[POO_INDEX_LAST_DIR]    = dir;
  2885.        poos[index].varsI[POO_INDEX_DESIRED_DIR] = dir;
  2886.        poos[index].varsI[POO_INDEX_PSI_COUNT]   = 0;       
  2887.        poos[index].max_count_2                  = 0;
  2888.  
  2889.        poos[index].varsI[POO_INDEX_EXPLORE_COUNTER] = 2*POO_EXPLORE_TIME + rand()%POO_EXPLORE_TIME;
  2890.  
  2891.        // reset averaging vars
  2892.        poos[index].varsI[POO_INDEX_SUM_X]      = 0;     
  2893.        poos[index].varsI[POO_INDEX_SUM_Y]      = 0;    
  2894.        
  2895.        if ((poos[index].varsI[POO_INDEX_BOUNCE_MAX] = (6 + rand()%6) - dug.varsI[DUG_INDEX_LEVEL]/2) < 2)
  2896.            poos[index].varsI[POO_INDEX_BOUNCE_MAX] = 2;
  2897.  
  2898.        // general counters
  2899.        poos[index].counter_1 = 0;
  2900.        poos[index].counter_2 = 0;
  2901.  
  2902.        // set position
  2903.        poos[index].x = x;
  2904.        poos[index].y = y;
  2905.  
  2906.        // save for restart
  2907.        poos[index].varsI[POO_INDEX_SAVED_X]   = x;               
  2908.        poos[index].varsI[POO_INDEX_SAVED_Y]   = y;              
  2909.        poos[index].varsI[POO_INDEX_SAVED_DIR] = dir;    
  2910.  
  2911.        // the the current animation of poo
  2912.        if (dir==DIR_LEFT || dir==DIR_UP)    
  2913.           {
  2914.           Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT);
  2915.           poos[index].varsI[POO_INDEX_ANIM_DIR] = DIR_LEFT;
  2916.           } // end if
  2917.        else
  2918.        if (dir==DIR_RIGHT || dir==DIR_DOWN)    
  2919.           {
  2920.           Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT);
  2921.           poos[index].varsI[POO_INDEX_ANIM_DIR] = DIR_RIGHT;
  2922.           } // end if
  2923.  
  2924.        // return success
  2925.        return(1);
  2926.  
  2927.        } // end if
  2928.  
  2929.     } // end for index
  2930.  
  2931. // return failure 
  2932. return(0);
  2933.  
  2934. } // end Start_Poo
  2935.  
  2936. //////////////////////////////////////////////////////////////
  2937.  
  2938. int Process_Poos(void)
  2939. {
  2940. // this function processes and controls the ai for al the poos
  2941.  
  2942. int index,    // looping variable
  2943.     pdx,pdy,  // velocity
  2944.     sx,sy;    // sample points
  2945.  
  2946. static int poo_counter_1   = 0; // used to initiate random events
  2947. static char *state_names[] = {"fire","explore","chase","evade","burrow","crush","inflating","popped"};
  2948.  
  2949. // loop and process all poos
  2950. //mono.set_cursor(0,1);
  2951. //mono.print("Poo System States");
  2952.  
  2953. // draw each poo
  2954. for (index=0; index < NUM_POOS; index++)
  2955.     {
  2956.     // is poo this available
  2957.     if (poos[index].state != POO_STATE_DEAD)
  2958.        {
  2959.  
  2960. //       sprintf(buffer,"\nPoo %d,  AI State = %s, XB = %d, YB=%d, PSI = %d , count_2  = %d        ",index,
  2961. //              state_names[poos[index].varsI[POO_INDEX_AI_STATE]],
  2962. //              poos[index].varsI[POO_INDEX_SUM_X],
  2963. //              poos[index].varsI[POO_INDEX_SUM_Y],
  2964. //              poos[index].varsI[POO_INDEX_PSI_COUNT],
  2965. //              poos[index].max_count_2);
  2966.  
  2967. //       mono.print(buffer);
  2968.  
  2969.        // talk shit
  2970.        if (rand()%750==100)
  2971.           Play_Sound(dyclops_talk_snd_ids[rand()%4]);
  2972.  
  2973.        // test for collisions here
  2974.        if (dug.state == DUG_STATE_ALIVE && 
  2975.            poos[index].varsI[POO_INDEX_AI_STATE] != POO_AI_STATE_CRUSHED &&
  2976.            poos[index].varsI[POO_INDEX_AI_STATE] != POO_AI_STATE_INFLATING)
  2977.           {
  2978.           if (Collision_BOBS(&dug,&poos[index]))
  2979.              {
  2980.              // start the death sequence
  2981.              Start_Dug_Death();
  2982.  
  2983.              } // end if
  2984.  
  2985.           } // end if
  2986.  
  2987.       // test for being crushed by rock
  2988.       for (int rindex=0; rindex < NUM_ROCKS; rindex++)
  2989.           {
  2990.           // test if rock is alive
  2991.           if (rocks[rindex].state==ROCK_STATE_FALLING)
  2992.              {
  2993.              // rock is alive, so test for collision with poo
  2994.              if (Collision_BOBS(&rocks[rindex],&poos[index]) && poos[index].varsI[POO_INDEX_AI_STATE] != POO_AI_STATE_CRUSHED) 
  2995.                 {
  2996.  
  2997.                 // first reset all state information of poo
  2998.                 //poos[index].state = POO_STATE_DYING;
  2999.  
  3000.                 poos[index].varsI[POO_INDEX_AI_STATE]   = POO_AI_STATE_CRUSHED;
  3001.                 poos[index].varsI[POO_INDEX_ANIM_STATE] = POO_ANIM_STATE_CRUSHED;
  3002.  
  3003.                 // start crunch sound
  3004.                 Play_Sound_From_Pool(crunch_snd_ids,4);
  3005.  
  3006.                 // tag rock
  3007.                 poos[index].varsI[POO_INDEX_OBJECT_PTR] = rindex;
  3008.  
  3009.                 // set animation
  3010.                 if (poos[index].varsI[POO_INDEX_CURR_DIR] == DIR_RIGHT || 
  3011.                     poos[index].varsI[POO_INDEX_CURR_DIR] == DIR_UP)
  3012.                    {
  3013.                    // set new animation
  3014.                    Set_Animation_BOB2(&poos[index],POO_ANIM_CRUSH_RIGHT);  
  3015.                    } // end if
  3016.                 else
  3017.                    {
  3018.                    // set new animation
  3019.                    Set_Animation_BOB2(&poos[index],POO_ANIM_CRUSH_LEFT);  
  3020.                    } // end if
  3021.  
  3022.                 // that's it
  3023.                 break;
  3024.                 
  3025.                 } // end if
  3026.  
  3027.              } // end if
  3028.  
  3029.           } // end for rindex
  3030.  
  3031.       // check for hit with pumps
  3032.       for (int gindex=0; gindex < NUM_GPUMPS; gindex++)
  3033.           {
  3034.           // test if this pump is usuable
  3035.           if (gpumps[gindex].state!=GPUMP_STATE_DEAD && 
  3036.               poos[index].max_count_2==0 &&
  3037.               poos[index].varsI[POO_INDEX_AI_STATE] != POO_AI_STATE_CRUSHED )
  3038.              { 
  3039.              if (Collision_BOBS(&gpumps[gindex],&poos[index]))
  3040.                 {
  3041.                 // kill the pump
  3042.                 gpumps[gindex].state=GPUMP_STATE_DEAD;
  3043.  
  3044.                 // make pump sound
  3045.                 Play_Sound_From_Pool(air_snd_ids, 4);
  3046.  
  3047.                 // change to inflate mode
  3048.                 poos[index].varsI[POO_INDEX_AI_STATE]   =  POO_AI_STATE_INFLATING;
  3049.                 poos[index].varsI[POO_INDEX_ANIM_STATE] =  POO_ANIM_STATE_INFLATING;
  3050.  
  3051.                 if (poos[index].varsI[POO_INDEX_PSI_COUNT] < 3*GPUMP_INJECTION)
  3052.                    {
  3053.                    poos[index].varsI[POO_INDEX_PSI_COUNT]  += (GPUMP_INJECTION-1);
  3054.  
  3055.                    if (poos[index].varsI[POO_INDEX_PSI_COUNT] > 3*GPUMP_INJECTION)
  3056.                        poos[index].varsI[POO_INDEX_PSI_COUNT] = 3*GPUMP_INJECTION;
  3057.                       
  3058.                    } // end if
  3059.  
  3060.                 // this is a pump poo!
  3061.                 break;
  3062.  
  3063.                 } // end if
  3064.  
  3065.              } // end if
  3066.  
  3067.           } // end gindex
  3068.  
  3069.  
  3070.        // what is the ai state of the poo
  3071.        // C R U S H E D   L O G I C //////////////////////////////////////////////////
  3072.  
  3073.        if (poos[index].varsI[POO_INDEX_AI_STATE] == POO_AI_STATE_CRUSHED)
  3074.           {
  3075.  
  3076.           // the poo is getting crushed, simple track tagged rock
  3077.           poos[index].x = rocks[poos[index].varsI[POO_INDEX_OBJECT_PTR]].x;
  3078.           poos[index].y = rocks[poos[index].varsI[POO_INDEX_OBJECT_PTR]].y+8;
  3079.  
  3080.           // test if rock is complete and in crumble mode
  3081.           if (rocks[poos[index].varsI[POO_INDEX_OBJECT_PTR]].state==ROCK_STATE_DEAD)
  3082.              {
  3083.              // terminate poo
  3084.              poos[index].state = POO_STATE_DEAD;
  3085.  
  3086.              // one more for the gipper
  3087.              dug.varsI[DUG_INDEX_KILLS]++;
  3088.  
  3089.              int score = 100+100*(poos[index].y/100);
  3090.  
  3091.              // start up score object
  3092.              Start_Score(poos[index].x+16 - 4 + rand()%8,poos[index].y+16 - 4+rand()%8,score);
  3093.              dug.varsI[DUG_INDEX_SCORE]+=score;
  3094.  
  3095.              } // end if
  3096.  
  3097.           } // end if   
  3098.        else
  3099.        //// S T O P   L O G I C  /////////////////////////////////////////////////////
  3100.        if (poos[index].varsI[POO_INDEX_AI_STATE]==POO_AI_STATE_STOP)
  3101.           {
  3102.           // the poo is stopped to think
  3103.           if (--poos[index].counter_1 <= 0)
  3104.              {
  3105.              // select new state
  3106.  
  3107.              } // end if
  3108.  
  3109.           } // end if
  3110.        //// I N F L A T I O N   S T A T E /////////////////////////////////////////////
  3111.        if (poos[index].varsI[POO_INDEX_AI_STATE]==POO_AI_STATE_INFLATING)
  3112.           {
  3113.  
  3114.           if (poos[index].varsI[POO_INDEX_PSI_COUNT] < 3*GPUMP_INJECTION)
  3115.           {
  3116.           // decrease inflation
  3117.           if (--poos[index].varsI[POO_INDEX_PSI_COUNT] <= 0)
  3118.              {
  3119.              // switch to chase mode
  3120.  
  3121.              // reset bounce counters
  3122.              poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3123.              poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3124.              poos[index].max_count_2 = 0;
  3125.  
  3126.              // change modes
  3127.              poos[index].varsI[POO_INDEX_AI_STATE] = POO_AI_STATE_CHASE;             
  3128.  
  3129.              // set animation correctly
  3130.              // the the current animation of poo
  3131.              if (poos[index].varsI[POO_INDEX_CURR_DIR]==DIR_LEFT || poos[index].varsI[POO_INDEX_CURR_DIR]==DIR_UP)    
  3132.                 {
  3133.                 Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT);
  3134.                 poos[index].varsI[POO_INDEX_ANIM_STATE] = POO_ANIM_STATE_BOUNCE;
  3135.                 } // end if
  3136.             else
  3137.                 {
  3138.                 Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT);
  3139.                 poos[index].varsI[POO_INDEX_ANIM_STATE] = POO_ANIM_STATE_BOUNCE;
  3140.                 } // end if
  3141.  
  3142.              } // end if
  3143.  
  3144.           } // end if
  3145.           else
  3146.           if (++poos[index].varsI[POO_INDEX_PSI_COUNT] > (3*GPUMP_INJECTION + GPUMP_INJECTION/2))
  3147.              {
  3148.              // kill the poo
  3149.              poos[index].state = POO_STATE_DEAD;
  3150.              poos[index].max_count_2 = 0;
  3151.  
  3152.              // one more for the gipper
  3153.              dug.varsI[DUG_INDEX_KILLS]++;
  3154.  
  3155.              int score = 100+100*(poos[index].y/100);
  3156.           
  3157.              if (dug.varsI[DUG_INDEX_DIR] == DIR_LEFT ||  dug.varsI[DUG_INDEX_DIR] == DIR_RIGHT)
  3158.                 score+=50;           
  3159.  
  3160.              // start up score object
  3161.              Start_Score(poos[index].x+16 - 4 + rand()%8,poos[index].y+16 - 4+rand()%8,score);
  3162.              dug.varsI[DUG_INDEX_SCORE]+=score;             
  3163.  
  3164.              } // end if
  3165.  
  3166.           } // end if
  3167.  
  3168.        else // E X P L O R E   L O G I C ///////////////////////////////////////////////////
  3169.        if (poos[index].varsI[POO_INDEX_AI_STATE]==POO_AI_STATE_EXPLORE)
  3170.           {
  3171.           // this is the general exploration ai
  3172.           // test the current direction of the poo
  3173.           switch(poos[index].varsI[POO_INDEX_CURR_DIR])
  3174.                 {
  3175.                 case DIR_LEFT:
  3176.                      {
  3177.                      // compute velocity changes
  3178.                      pdx = -POO_SPEED;
  3179.                      pdy = 0;
  3180.  
  3181.                      // move poo
  3182.                      poos[index].x+=pdx;
  3183.                      poos[index].y+=pdy;
  3184.  
  3185.                      // compute sample position
  3186.                      sx = poos[index].x; 
  3187.                      sy = poos[index].y + 16;
  3188.      
  3189.                      // check for collision
  3190.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE || 
  3191.                          poos[index].x <= 0)
  3192.                         {
  3193.                         // reverse the direction of motion
  3194.                         poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3195.                         poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_RIGHT;
  3196.                         
  3197.                         // set new animation
  3198.                         Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT);                        
  3199.  
  3200.                         // increment x-axis bounce counter
  3201.                         poos[index].varsI[POO_INDEX_SUM_X]++;
  3202.                         poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3203.    
  3204.                         } // end if 
  3205.  
  3206.                      } break;        
  3207.  
  3208.                 case DIR_RIGHT:
  3209.                      {
  3210.                      // compute velocity changes
  3211.                      pdx = POO_SPEED;
  3212.                      pdy = 0;
  3213.  
  3214.                      // move poo
  3215.                      poos[index].x+=pdx;
  3216.                      poos[index].y+=pdy;
  3217.  
  3218.                      // compute sample position
  3219.                      sx = poos[index].x + 31;
  3220.                      sy = poos[index].y + 16;
  3221.      
  3222.                      // check for collision
  3223.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE  || 
  3224.                         poos[index].x >= (SCREEN_WIDTH-32))
  3225.                         {
  3226.                         // reverse the direction of motion
  3227.                         poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3228.                         poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_LEFT;
  3229.                         
  3230.                         // set new animation
  3231.                         Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT);                        
  3232.  
  3233.                         // increment x-axis bounce counter
  3234.                         poos[index].varsI[POO_INDEX_SUM_X]++;
  3235.                         poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3236.       
  3237.                         } // end if 
  3238.                      } break;        
  3239.  
  3240.                 case DIR_UP:
  3241.                      {
  3242.                      // compute velocity changes
  3243.                      pdy = -POO_SPEED;
  3244.                      pdx = 0;
  3245.  
  3246.                      // move poo
  3247.                      poos[index].x+=pdx;
  3248.                      poos[index].y+=pdy;
  3249.  
  3250.                      // compute sample position
  3251.                      sx = poos[index].x + 16;
  3252.                      sy = poos[index].y;
  3253.      
  3254.                      // check for collision
  3255.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE  || 
  3256.                          poos[index].y <= DUG_MIN_ROCK_LINE)
  3257.                         {
  3258.                         // reverse the direction of motion
  3259.                         poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3260.                         poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_DOWN;
  3261.  
  3262.                         // increment x-axis bounce counter
  3263.                         poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3264.                         poos[index].varsI[POO_INDEX_SUM_Y]++;
  3265.                         
  3266.                         } // end if 
  3267.  
  3268.                      } break;        
  3269.  
  3270.                 case DIR_DOWN:
  3271.                      {
  3272.                      // compute velocity changes
  3273.                      pdy = POO_SPEED;
  3274.                      pdx = 0;
  3275.  
  3276.                      // move poo
  3277.                      poos[index].x+=pdx;
  3278.                      poos[index].y+=pdy;
  3279.  
  3280.                      // compute sample position
  3281.                      sx = poos[index].x + 16;
  3282.                      sy = poos[index].y + 31;
  3283.      
  3284.                      // check for collision
  3285.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE  || 
  3286.                         poos[index].y >= (SCREEN_HEIGHT-32))
  3287.                         {
  3288.                         // reverse the direction of motion
  3289.                         poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3290.                         poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_UP;
  3291.  
  3292.                         // increment x-axis bounce counter
  3293.                         poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3294.                         poos[index].varsI[POO_INDEX_SUM_Y]++;
  3295.                         
  3296.                         } // end if 
  3297.  
  3298.                      } break;        
  3299.  
  3300.                 default:break;
  3301.  
  3302.                 } // end switch 
  3303.  
  3304.          // at this point the poo has moved, let's test if we can make a turn
  3305.          if (poos[index].varsI[POO_INDEX_CURR_DIR] == DIR_LEFT || 
  3306.              poos[index].varsI[POO_INDEX_CURR_DIR] == DIR_RIGHT)
  3307.             {
  3308.             // try for up or down turn
  3309.             if (!((int)poos[index].x % DUG_X_INTERVAL))
  3310.                {
  3311.                // it legal to make a turn
  3312.                // select a direction
  3313.                if ((rand()%2) == 1)
  3314.                {
  3315.                // try and turn up
  3316.                sx = poos[index].x + 16;
  3317.                sy = poos[index].y - 1;
  3318.      
  3319.                // check for collision
  3320.                if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE &&
  3321.                    Get_Pixel(sx,sy-2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3322.                   {
  3323.                   // reverse the direction of motion
  3324.                   poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3325.                   poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_UP;
  3326.  
  3327.                   // reset bounce counters
  3328.                   poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3329.                   poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3330.  
  3331.                   } // end if
  3332.  
  3333.                }
  3334.                else
  3335.                {
  3336.                // try and turn down
  3337.                sx = poos[index].x + 16;
  3338.                sy = poos[index].y + 32;
  3339.      
  3340.                // check for collision
  3341.                if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE &&
  3342.                    Get_Pixel(sx,sy+2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3343.                   {
  3344.                   // reverse the direction of motion
  3345.                   poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3346.                   poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_DOWN;
  3347.  
  3348.                   // reset bounce counters
  3349.                   poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3350.                   poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3351.  
  3352.                   } // end if
  3353.  
  3354.                } // end else
  3355.  
  3356.                } // end if  
  3357.  
  3358.             } // end if
  3359.          else
  3360.          if (poos[index].varsI[POO_INDEX_CURR_DIR] == DIR_UP || 
  3361.              poos[index].varsI[POO_INDEX_CURR_DIR] == DIR_DOWN)          
  3362.             { 
  3363.             // try for up or down turn
  3364.             if (!(((int)poos[index].y + 8) % DUG_X_INTERVAL))
  3365.                {
  3366.                // it legal to make a turn
  3367.                // select a direction
  3368.                if ((rand()%2)==1)
  3369.                {
  3370.                // try and turn right 
  3371.                sx = poos[index].x + 32;
  3372.                sy = poos[index].y + 16;
  3373.      
  3374.                // check for collision
  3375.                if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3376.                    Get_Pixel(sx + 2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3377.                   {
  3378.                   // reverse the direction of motion
  3379.                   poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3380.                   poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_RIGHT;
  3381.                   Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT);   
  3382.  
  3383.                   // reset bounce counters
  3384.                   poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3385.                   poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3386.  
  3387.                   } // end if
  3388.                } // end if
  3389.  
  3390.                else
  3391.                {
  3392.                // try and turn down
  3393.                sx = poos[index].x - 1;
  3394.                sy = poos[index].y + 16;
  3395.      
  3396.                // check for collision
  3397.                if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3398.                    Get_Pixel(sx - 2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3399.                   {
  3400.                   // reverse the direction of motion
  3401.                   poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3402.                   poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_LEFT;
  3403.                   Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT);   
  3404.  
  3405.                   // reset bounce counters
  3406.                   poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3407.                   poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3408.  
  3409.                   } // end if
  3410.  
  3411.                } // end else
  3412.  
  3413.                } // end if  
  3414.  
  3415.             } // end if
  3416.  
  3417.           // test for state exits
  3418.           if (--poos[index].varsI[POO_INDEX_EXPLORE_COUNTER] <=0)
  3419.              {
  3420.              // set state to chase
  3421.              poos[index].varsI[POO_INDEX_AI_STATE]=POO_AI_STATE_CHASE;
  3422.  
  3423.              // reset counter
  3424.              poos[index].varsI[POO_INDEX_EXPLORE_COUNTER] = POO_EXPLORE_TIME;
  3425.  
  3426.              } // end if
  3427.  
  3428.          // test for switch into burrow mode
  3429.          if (poos[index].varsI[POO_INDEX_SUM_X] > poos[index].varsI[POO_INDEX_BOUNCE_MAX] || 
  3430.              poos[index].varsI[POO_INDEX_SUM_Y] > poos[index].varsI[POO_INDEX_BOUNCE_MAX])
  3431.             {
  3432.             // reset bounce counters
  3433.             poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3434.             poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3435.  
  3436.             // change modes to burrow
  3437.             poos[index].varsI[POO_INDEX_AI_STATE] = POO_AI_STATE_BURROW;
  3438.             Set_Animation_BOB2(&poos[index],POO_ANIM_BURROW);  
  3439.  
  3440.             poos[index].varsI[POO_INDEX_ANIM_STATE] = POO_ANIM_STATE_BURROW;
  3441.  
  3442.             // start directional rescan
  3443.             poos[index].counter_2 = 0;
  3444.  
  3445.             // set maximum burrow time
  3446.             //poos[index].varsI[POO_INDEX_EXPLORE_COUNTER] = (POO_EXPLORE_TIME >> 2) + (rand()%POO_EXPLORE_TIME);
  3447.  
  3448.             } // end if
  3449.  
  3450.           } // end if explore
  3451.  
  3452.        else /// C H A S E  L O G I C ///////////////////////////////////////////////////
  3453.        if (poos[index].varsI[POO_INDEX_AI_STATE]==POO_AI_STATE_CHASE)
  3454.           {
  3455.           int desired_taken = 0; // used to track if desired was taken
  3456.  
  3457.           // test the current direction of the poo
  3458.           switch(poos[index].varsI[POO_INDEX_CURR_DIR])
  3459.                 {
  3460.                 case DIR_LEFT:
  3461.                      {
  3462.                      // compute velocity changes
  3463.                      pdx = -POO_SPEED;
  3464.                      pdy = 0;
  3465.  
  3466.                      // move poo
  3467.                      poos[index].x+=pdx;
  3468.                      poos[index].y+=pdy;
  3469.  
  3470.                      // compute sample position
  3471.                      sx = poos[index].x;
  3472.                      sy = poos[index].y + 16;
  3473.      
  3474.                      // check for collision
  3475.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE || 
  3476.                          poos[index].x <= 0)
  3477.                         {
  3478.                         // reverse the direction of motion
  3479.                         poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3480.                         poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_RIGHT;
  3481.  
  3482.                         // set new animation
  3483.                         Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT);                        
  3484.  
  3485.                         // increment x-axis bounce counter
  3486.                         poos[index].varsI[POO_INDEX_SUM_X]++;
  3487.                         poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3488.       
  3489.                         } // end if 
  3490.  
  3491.                      } break;        
  3492.  
  3493.                 case DIR_RIGHT:
  3494.                      {
  3495.                      // compute velocity changes
  3496.                      pdx = POO_SPEED;
  3497.                      pdy = 0;
  3498.  
  3499.                      // move poo
  3500.                      poos[index].x+=pdx;
  3501.                      poos[index].y+=pdy;
  3502.  
  3503.                      // compute sample position
  3504.                      sx = poos[index].x + 31;
  3505.                      sy = poos[index].y + 16;
  3506.      
  3507.                      // check for collision
  3508.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE || 
  3509.                          poos[index].x >= (SCREEN_WIDTH-32))
  3510.                         {
  3511.                         // reverse the direction of motion
  3512.                         poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3513.                         poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_LEFT;
  3514.  
  3515.                         // set new animation
  3516.                         Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT);                        
  3517.  
  3518.                         // increment x-axis bounce counter
  3519.                         poos[index].varsI[POO_INDEX_SUM_X]++;
  3520.                         poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3521.        
  3522.                         } // end if 
  3523.                      } break;        
  3524.  
  3525.                 case DIR_UP:
  3526.                      {
  3527.                      // compute velocity changes
  3528.                      pdy = -POO_SPEED;
  3529.                      pdx = 0;
  3530.  
  3531.                      // move poo
  3532.                      poos[index].x+=pdx;
  3533.                      poos[index].y+=pdy;
  3534.  
  3535.                      // compute sample position
  3536.                      sx = poos[index].x + 16;
  3537.                      sy = poos[index].y;
  3538.      
  3539.                      // check for collision
  3540.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE || 
  3541.                          poos[index].y <= (DUG_MIN_ROCK_LINE))
  3542.                         {
  3543.                         // reverse the direction of motion
  3544.                         poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3545.                         poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_DOWN;
  3546.  
  3547.                         // increment y-axis bounce counter
  3548.                         poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3549.                         poos[index].varsI[POO_INDEX_SUM_Y]++;
  3550.  
  3551.                         } // end if 
  3552.  
  3553.                      } break;        
  3554.  
  3555.                 case DIR_DOWN:
  3556.                      {
  3557.                      // compute velocity changes
  3558.                      pdy = POO_SPEED;
  3559.                      pdx = 0;
  3560.  
  3561.                      // move poo
  3562.                      poos[index].x+=pdx;
  3563.                      poos[index].y+=pdy;
  3564.  
  3565.                      // compute sample position
  3566.                      sx = poos[index].x + 16;
  3567.                      sy = poos[index].y + 31;
  3568.      
  3569.                      // check for collision
  3570.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE || 
  3571.                         poos[index].y >= (SCREEN_HEIGHT-32))
  3572.                         {
  3573.                         // reverse the direction of motion
  3574.                         poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3575.                         poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_UP;
  3576.  
  3577.                         // increment y-axis bounce counter
  3578.                         poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3579.                         poos[index].varsI[POO_INDEX_SUM_Y]++;
  3580.                     
  3581.                         } // end if 
  3582.  
  3583.                      } break;        
  3584.  
  3585.                 default:break;
  3586.  
  3587.                 } // end switch 
  3588.  
  3589.          // at this point the poo has moved, let's test if we can make a turn
  3590.          // compute the desired new direction
  3591.          // compute dx and dy
  3592.  
  3593.          int dx = dug.x - poos[index].x;
  3594.          int dy = dug.y - poos[index].y;
  3595.  
  3596.          // decide which way we want to go
  3597.          if (abs(dx) > abs(dy))
  3598.             {
  3599.             // set primary desired direction to minimize dx 
  3600.             if (dx > 0)
  3601.                poos[index].varsI[POO_INDEX_DESIRED_DIR] = DIR_RIGHT;
  3602.             else
  3603.                poos[index].varsI[POO_INDEX_DESIRED_DIR] = DIR_LEFT;
  3604.  
  3605.             // set secondary direction only if delta is > 16
  3606.             if (abs(dy) > 16)
  3607.                {
  3608.                 if (dy > 0)
  3609.                    poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] = DIR_DOWN;
  3610.                 else
  3611.                    poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] = DIR_UP;
  3612.                 } // end if
  3613.             else
  3614.                poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] = DIR_NULL;
  3615.  
  3616.             } // end if
  3617.          else
  3618.             {
  3619.             // set primary desired direction to minimize dy
  3620.             if (dy > 0)
  3621.                poos[index].varsI[POO_INDEX_DESIRED_DIR] = DIR_DOWN;
  3622.             else
  3623.                poos[index].varsI[POO_INDEX_DESIRED_DIR] = DIR_UP;
  3624.  
  3625.             // set secondary desired direction to minimize dx, only if dx > 16
  3626.             if (abs(dx) > 16)
  3627.                {
  3628.                if (dx > 0)
  3629.                   poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] = DIR_RIGHT;
  3630.                else
  3631.                   poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] = DIR_LEFT;
  3632.                } // end if
  3633.              else
  3634.                 poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] = DIR_NULL;
  3635.  
  3636.             } // end if               
  3637.  
  3638.         // once in a blue moon swap primary and secondary
  3639.         if ((rand()%10)==1)
  3640.            {
  3641.            // swap
  3642.            int temp = poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR];
  3643.            poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] = poos[index].varsI[POO_INDEX_DESIRED_DIR];
  3644.            poos[index].varsI[POO_INDEX_DESIRED_DIR]     = temp;
  3645.  
  3646.            } // end if
  3647.          
  3648.         // make sure we don't want to go the same way
  3649.         if ((poos[index].varsI[POO_INDEX_DESIRED_DIR] >> 1) != (poos[index].varsI[POO_INDEX_CURR_DIR] >> 1))
  3650.         {
  3651.            
  3652.          // test for desired right turn     
  3653.          if (poos[index].varsI[POO_INDEX_DESIRED_DIR] == DIR_RIGHT && 
  3654.              !(((int)poos[index].y+8) % DUG_X_INTERVAL))
  3655.             {
  3656.             // try and turn up
  3657.             sx = poos[index].x + 32;
  3658.             sy = poos[index].y + 16;
  3659.      
  3660.             // check for collision
  3661.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3662.                 Get_Pixel(sx+2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3663.                {
  3664.                // reverse the direction of motion
  3665.                poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3666.                poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_RIGHT;
  3667.  
  3668.                // set new animation
  3669.                Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT);   
  3670.  
  3671.                // set taken flag
  3672.                desired_taken = 1;
  3673.  
  3674.                // reset bounce counters
  3675.                poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3676.                poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3677.  
  3678.                } // end if
  3679.  
  3680.             } // end if
  3681.  
  3682.          // test for desired right turn     
  3683.          else
  3684.          if (poos[index].varsI[POO_INDEX_DESIRED_DIR] == DIR_LEFT && 
  3685.              !(((int)poos[index].y+8) % DUG_X_INTERVAL))
  3686.             {
  3687.             // try and turn up
  3688.             sx = poos[index].x - 1;
  3689.             sy = poos[index].y + 16;
  3690.      
  3691.             // check for collision
  3692.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3693.                 Get_Pixel(sx - 2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3694.                {
  3695.                // reverse the direction of motion
  3696.                poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3697.                poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_LEFT;
  3698.  
  3699.                // set new animation
  3700.                Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT);   
  3701.  
  3702.                // set taken flag
  3703.                desired_taken = 1;
  3704.  
  3705.                // reset bounce counters
  3706.                poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3707.                poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3708.  
  3709.                } // end if
  3710.  
  3711.             } // end if
  3712.          else
  3713.          if (poos[index].varsI[POO_INDEX_DESIRED_DIR] == DIR_UP && 
  3714.              !(((int)poos[index].x) % DUG_X_INTERVAL))
  3715.             {
  3716.             // try and turn up
  3717.             sx = poos[index].x + 16;
  3718.             sy = poos[index].y - 1;
  3719.      
  3720.             // check for collision
  3721.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE &&
  3722.                 Get_Pixel(sx,sy - 2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3723.                {
  3724.                // reverse the direction of motion
  3725.                poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3726.                poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_UP;
  3727.  
  3728.                // set taken flag
  3729.                desired_taken = 1;
  3730.  
  3731.                // reset bounce counters
  3732.                poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3733.                poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3734.  
  3735.                } // end if
  3736.  
  3737.             } // end if
  3738.          else
  3739.          if (poos[index].varsI[POO_INDEX_DESIRED_DIR] == DIR_DOWN && 
  3740.              !(((int)poos[index].x) % DUG_X_INTERVAL))
  3741.             {
  3742.             // try and turn up
  3743.             sx = poos[index].x + 16;
  3744.             sy = poos[index].y + 32;
  3745.      
  3746.             // check for collision
  3747.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3748.                Get_Pixel(sx,sy+2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3749.                {
  3750.                // reverse the direction of motion
  3751.                poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3752.                poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_DOWN;
  3753.  
  3754.                // set taken flag
  3755.                desired_taken = 1;
  3756.  
  3757.                // reset bounce counters
  3758.                poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3759.                poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3760.  
  3761.                } // end if
  3762.  
  3763.             } // end if
  3764.  
  3765.          } // end if primary valid
  3766.  
  3767.  
  3768.          ///////////////////////////////////////////////////////////////////////
  3769.          // test for secondary turns
  3770.      
  3771.          if (!desired_taken && 
  3772.             (poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR]!=DIR_NULL) &&
  3773.             (poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] >> 1) != (poos[index].varsI[POO_INDEX_CURR_DIR] >> 1) )
  3774.          {
  3775.          // test for desired right turn
  3776.          if (poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] == DIR_RIGHT && 
  3777.              !(((int)poos[index].y+8) % DUG_X_INTERVAL))
  3778.             {
  3779.             // try and turn up
  3780.             sx = poos[index].x + 32;
  3781.             sy = poos[index].y + 16;
  3782.      
  3783.             // check for collision
  3784.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3785.                 Get_Pixel(sx+2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3786.                {
  3787.                // reverse the direction of motion
  3788.                poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3789.                poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_RIGHT;
  3790.  
  3791.                // set new animation
  3792.                Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT);   
  3793.                // set taken flag
  3794.                desired_taken = 1;
  3795.  
  3796.                // reset bounce counters
  3797.                poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3798.                poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3799.  
  3800.                } // end if
  3801.  
  3802.             } // end if
  3803.  
  3804.          // test for desired right turn     
  3805.          else
  3806.          if (poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] == DIR_LEFT && 
  3807.              !(((int)poos[index].y+8) % DUG_X_INTERVAL))
  3808.             {
  3809.             // try and turn up
  3810.             sx = poos[index].x - 1;
  3811.             sy = poos[index].y + 16;
  3812.      
  3813.             // check for collision
  3814.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3815.                 Get_Pixel(sx - 2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3816.                {
  3817.                // reverse the direction of motion
  3818.                poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3819.                poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_LEFT;
  3820.  
  3821.                // set new animation
  3822.                Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT);   
  3823.  
  3824.                // set taken flag
  3825.                desired_taken = 1;
  3826.  
  3827.                // reset bounce counters
  3828.                poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3829.                poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3830.  
  3831.                } // end if
  3832.  
  3833.             } // end if
  3834.          else
  3835.          if (poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] == DIR_UP && 
  3836.              !(((int)poos[index].x) % DUG_X_INTERVAL))
  3837.             {
  3838.             // try and turn up
  3839.             sx = poos[index].x + 16;
  3840.             sy = poos[index].y - 1;
  3841.      
  3842.             // check for collision
  3843.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE &&
  3844.                 Get_Pixel(sx,sy - 2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3845.                {
  3846.                // reverse the direction of motion
  3847.                poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3848.                poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_UP;
  3849.  
  3850.                // set taken flag
  3851.                desired_taken = 1;
  3852.  
  3853.                } // end if
  3854.  
  3855.             } // end if
  3856.          else
  3857.          if (poos[index].varsI[POO_INDEX_2ND_DESIRED_DIR] == DIR_DOWN && 
  3858.              !(((int)poos[index].x) % DUG_X_INTERVAL))
  3859.             {
  3860.             // try and turn up
  3861.             sx = poos[index].x + 16;
  3862.             sy = poos[index].y + 32;
  3863.      
  3864.             // check for collision
  3865.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3866.                Get_Pixel(sx,sy+2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3867.                {
  3868.                // reverse the direction of motion
  3869.                poos[index].varsI[POO_INDEX_LAST_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  3870.                poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_DOWN;
  3871.  
  3872.                // set taken flag
  3873.                desired_taken = 1;
  3874.  
  3875.                // reset bounce counters
  3876.                poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3877.                poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3878.  
  3879.                } // end if
  3880.  
  3881.             } // end if
  3882.  
  3883.           } // end else 2nd desired
  3884.  
  3885.  
  3886. // test for global randomness ////////////////////////////////////////////////////
  3887.           if (++poo_counter_1 > 200)
  3888.              poo_counter_1 = 0;
  3889.  
  3890.           // test for random event
  3891.           if ((poo_counter_1 == 0) && 
  3892.               ((rand()%3)==1) && 
  3893.               (Fast_Distance(poos[index].x-dug.x, poos[index].y-dug.y) > 300))
  3894.               {
  3895.               // reverse direction
  3896.               switch(poos[index].varsI[POO_INDEX_CURR_DIR])
  3897.                     {
  3898.                     case DIR_LEFT:  
  3899.                          {
  3900.                          poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_RIGHT;  
  3901.                          // set new animation
  3902.                          Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT);   
  3903.                          } break;
  3904.  
  3905.                     case DIR_RIGHT: 
  3906.                          {
  3907.                          poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_LEFT;  
  3908.                          // set new animation
  3909.                          Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT);   
  3910.                          } break;
  3911.  
  3912.                     case DIR_UP:    poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_DOWN; break;
  3913.                     case DIR_DOWN:  poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_UP; break;
  3914.  
  3915.                     default:break;
  3916.                     } // end switch
  3917.  
  3918.               } // end if
  3919. ///////////////////////////////////////////////////////////////////////////
  3920.  
  3921.          // test for pre-emptive state transitions
  3922.          if (poos[index].varsI[POO_INDEX_SUM_X] > POO_BOUNCES_PREMPT || poos[index].varsI[POO_INDEX_SUM_Y] > POO_BOUNCES_PREMPT)
  3923.             {
  3924.             // reset bounce counters
  3925.             poos[index].varsI[POO_INDEX_SUM_X] = 0;
  3926.             poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  3927.  
  3928.             // change modes
  3929.             poos[index].varsI[POO_INDEX_AI_STATE]   =   POO_AI_STATE_EXPLORE;
  3930.             poos[index].varsI[POO_INDEX_EXPLORE_COUNTER] = (POO_EXPLORE_TIME >> 2) + (rand()%POO_EXPLORE_TIME);
  3931.  
  3932.             } // end if
  3933.  
  3934.  
  3935.           } // end if chase
  3936.  
  3937.        else //////////////////////////////////////////////////////////////////////////
  3938.        if (poos[index].varsI[POO_INDEX_AI_STATE]==POO_AI_STATE_EVADE)
  3939.           {
  3940.  
  3941.           } // end if
  3942.        
  3943.        else /////////////////////////////////////////////////////////////////////////
  3944.        if (poos[index].varsI[POO_INDEX_AI_STATE]==POO_AI_STATE_BURROW)
  3945.           {
  3946.           // select tracking direction
  3947.           int burst_speed = 1;
  3948.  
  3949.           // compute added velocity due to level
  3950.           if ((rand()%(100-dug.varsI[DUG_INDEX_LEVEL]))==1)
  3951.              burst_speed = 2; 
  3952.  
  3953.           // x tracking
  3954.           if (rand()%3==1)
  3955.               {
  3956.               if (dug.x > poos[index].x)
  3957.                  poos[index].x+=(burst_speed );
  3958.               else
  3959.               if (dug.x < poos[index].x)
  3960.                  poos[index].x-=(burst_speed );
  3961.               } // end if
  3962.  
  3963.           // y tracking
  3964.           if (rand()%3==1)
  3965.              {
  3966.              if (dug.y < poos[index].y)
  3967.                  poos[index].y-=(burst_speed );
  3968.              else
  3969.              if (dug.y > poos[index].y)
  3970.                  poos[index].y+=(burst_speed );
  3971.  
  3972.               } // end if
  3973.  
  3974.           // test for clip
  3975.           if (poos[index].y < DUG_MIN_ROCK_LINE)
  3976.              poos[index].y+=(1);
  3977.  
  3978.            int sx = poos[index].x,
  3979.                sy = poos[index].y;
  3980.  
  3981.            // test if done burrowing
  3982.            if (Get_Pixel(sx,   sy,   background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE &&
  3983.                Get_Pixel(sx+31,sy,   background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3984.                Get_Pixel(sx,   sy+31,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  3985.                Get_Pixel(sx+31,sy+31,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  3986.               {
  3987.               // set state to chase
  3988.               poos[index].varsI[POO_INDEX_AI_STATE]=POO_AI_STATE_CHASE; 
  3989.               poos[index].varsI[POO_INDEX_ANIM_STATE] = POO_ANIM_STATE_BOUNCE;
  3990.  
  3991.               // reset counter
  3992.               poos[index].varsI[POO_INDEX_EXPLORE_COUNTER] = POO_EXPLORE_TIME; 
  3993.  
  3994.               // reset bounce counters
  3995.               poos[index].varsI[POO_INDEX_SUM_X] = 0; 
  3996.               poos[index].varsI[POO_INDEX_SUM_Y] = 0; 
  3997.  
  3998.               // reset bounce master
  3999.               if ((poos[index].varsI[POO_INDEX_BOUNCE_MAX] = (3 + (rand()%3) - dug.varsI[DUG_INDEX_LEVEL]/2) < 3))
  4000.                  poos[index].varsI[POO_INDEX_BOUNCE_MAX] = 3;
  4001.  
  4002.            // make a final decision on direction
  4003.               
  4004.            // lock coords
  4005.            int gdx = ((int)poos[index].x % DUG_X_INTERVAL);
  4006.            int gdy = (((int)poos[index].y+8) % DUG_X_INTERVAL);
  4007.                 
  4008.            // find the smaller of the two and align
  4009.            if (gdx <= gdy)
  4010.               {
  4011.               // align x axis, find closest interval
  4012.               if (gdx <= 19)
  4013.                  {
  4014.                  poos[index].x-=gdx;
  4015.                  } // end if
  4016.              else 
  4017.                  {
  4018.                  poos[index].x+=(DUG_X_INTERVAL - gdx);
  4019.                  } // end else
  4020.  
  4021.               // align y axis on even boundary
  4022.               poos[index].y = (int)poos[index].y & (0xfffffffe);
  4023.  
  4024.               } // end if
  4025.            else
  4026.               {
  4027.               // align y axis, find closest interval
  4028.               if (gdy <= 19)
  4029.                  {
  4030.                  poos[index].y-=gdy;
  4031.                  } // end if
  4032.              else 
  4033.                  {
  4034.                  poos[index].y+=(DUG_X_INTERVAL - gdy);
  4035.                  } // end else
  4036.  
  4037.               // align x axis on even boundary
  4038.               poos[index].x =  (int)poos[index].x & (0xfffffffe);
  4039.               } // end else
  4040.  
  4041.            // compute most desired direction
  4042.            int dx = dug.x - poos[index].x;
  4043.            int dy = dug.y - poos[index].y;
  4044.  
  4045.            // decide which way we want to go
  4046.            if (abs(dx) > abs(dy))
  4047.               {
  4048.               // set primary desired direction to minimize dx 
  4049.               if (dx > 0)
  4050.                  poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_RIGHT;
  4051.               else
  4052.                  poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_LEFT;
  4053.  
  4054.               } // end if
  4055.            else
  4056.               {
  4057.               // set primary desired direction to minimize dy
  4058.               if (dy > 0)
  4059.                  poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_DOWN;
  4060.               else
  4061.                  poos[index].varsI[POO_INDEX_CURR_DIR] = DIR_UP;
  4062.  
  4063.               } // end if               
  4064.  
  4065.               // set animation direction
  4066.               poos[index].varsI[POO_INDEX_ANIM_DIR] = poos[index].varsI[POO_INDEX_CURR_DIR];
  4067.              
  4068.               // set animation 
  4069.               if (poos[index].varsI[POO_INDEX_ANIM_DIR]==DIR_LEFT || 
  4070.                   poos[index].varsI[POO_INDEX_ANIM_DIR]==DIR_UP)    
  4071.                  {
  4072.                  Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT); 
  4073.                  } // end if 
  4074.               else
  4075.               if (poos[index].varsI[POO_INDEX_ANIM_DIR]==DIR_RIGHT || 
  4076.                   poos[index].varsI[POO_INDEX_ANIM_DIR]==DIR_DOWN)    
  4077.                  {
  4078.                  Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT); 
  4079.                  } // end if
  4080.  
  4081.               } // end if
  4082.  
  4083.           } // end if
  4084.  
  4085.        } // end if alive
  4086.  
  4087.     } // end for index
  4088.  
  4089. // return success
  4090. return(1);
  4091.  
  4092. } // end Process_Poos
  4093.  
  4094. ///////////////////////////////////////////////////////////////
  4095.  
  4096. int Draw_Poos(void)
  4097. {
  4098. // this function animates and draws all the poos
  4099.  
  4100. int index; // looping index
  4101.  
  4102. // draw each poo
  4103. for (index=0; index < NUM_POOS; index++)
  4104.     {
  4105.     // is poo this available
  4106.     if (poos[index].state != POO_STATE_DEAD)
  4107.        {
  4108.        // what is the animation state?
  4109.        switch(poos[index].varsI[POO_INDEX_ANIM_STATE])
  4110.              {
  4111.              case POO_ANIM_STATE_BOUNCE:
  4112.                   {
  4113.                   // the poo is just bouncing up and down
  4114.                   Draw_BOB(&poos[index],lpddsback);
  4115.  
  4116.                   // animate the poo
  4117.                   Animate_BOB2(&poos[index]);
  4118.  
  4119.                   } break;
  4120.  
  4121.              case POO_ANIM_STATE_CRUSHED:      
  4122.                   {
  4123.                   // the poo is being crushed
  4124.                   
  4125.                   // draw the poo
  4126.                   Draw_BOB(&poos[index],lpddsback);
  4127.  
  4128.                   if (poos[index].anim_state != BOB_STATE_ANIM_DONE)
  4129.                      {
  4130.                      // animate the poo
  4131.                      Animate_BOB2(&poos[index]);
  4132.                      } // end if
  4133.  
  4134. #if 0
  4135.            bob->anim_index = 2;
  4136.            bob->curr_frame = bob->animations[bob->curr_animation][bob->anim_index];
  4137. #endif
  4138.  
  4139.                   } break;
  4140.  
  4141.              case POO_ANIM_STATE_BURROW:      
  4142.                   {
  4143.                   // the poo is just bouncing up and down
  4144.                   Draw_BOB(&poos[index],lpddsback);
  4145.  
  4146.                   // animate the poo
  4147.                   Animate_BOB2(&poos[index]);
  4148.  
  4149.                   } break;
  4150.  
  4151.              case POO_ANIM_STATE_INFLATING:
  4152.                   {
  4153.                   // set the position of the puffy
  4154.                   puffy.x = poos[index].x-12;
  4155.                   puffy.y = poos[index].y-20;
  4156.  
  4157.                   // compute frame offset
  4158.                   int frame = (poos[index].varsI[POO_INDEX_PSI_COUNT]/50);
  4159.  
  4160.                   if (frame >= 3)
  4161.                      {
  4162.                      frame = 3;
  4163.  
  4164.                      // make pop sound
  4165.                      if (poos[index].max_count_2==0)
  4166.                         {
  4167.                         // make pop sound
  4168.                         Play_Sound_From_Pool(pop_snd_ids, 4);
  4169.                         poos[index].max_count_2=1;
  4170.  
  4171.                         } // end if
  4172.                      } // end if
  4173.  
  4174.                   // set frame
  4175.                   puffy.curr_frame = 4*(poos[index].varsI[POO_INDEX_CURR_DIR]%2) + frame;
  4176.  
  4177.                   // draw the puffy
  4178.                   Draw_BOB(&puffy,lpddsback);
  4179.  
  4180.                   } break;
  4181.  
  4182.              default:break;
  4183.  
  4184.              } // end switch
  4185.  
  4186.  
  4187.        } // end if
  4188.  
  4189.      } // end for index
  4190.  
  4191. // return success
  4192. return(1);
  4193.  
  4194. } // end Draw_Poos
  4195.  
  4196. ////////////////////////////////////////////////////////////////
  4197.  
  4198. int Start_Puff(int x, int y, int dir)
  4199. {
  4200. // this function attempts to start a puff up with the desired
  4201. // position and direction
  4202.  
  4203. int index; // looping index
  4204.  
  4205. // find an unused puff
  4206. for (index=0; index < NUM_PUFFS; index++)
  4207.     {
  4208.     // is puff this available
  4209.     if (puffs[index].state == PUFF_STATE_DEAD)
  4210.        {
  4211.        // set puff up
  4212.        puffs[index].state                          = PUFF_STATE_ALIVE;
  4213.        puffs[index].varsI[PUFF_INDEX_AI_STATE]     = PUFF_AI_STATE_EXPLORE;
  4214.        puffs[index].varsI[PUFF_INDEX_ANIM_STATE]   = PUFF_ANIM_STATE_BOUNCE; 
  4215.        puffs[index].varsI[PUFF_INDEX_CURR_DIR]     = dir;
  4216.        puffs[index].varsI[PUFF_INDEX_LAST_DIR]     = dir;
  4217.        puffs[index].varsI[PUFF_INDEX_DESIRED_DIR]  = dir;
  4218.        puffs[index].varsI[PUFF_INDEX_PSI_COUNT]    = 0;       
  4219.        puffs[index].max_count_2                    = 0;
  4220.  
  4221.        puffs[index].varsI[PUFF_INDEX_EXPLORE_COUNTER] = 2*PUFF_EXPLORE_TIME + rand()%PUFF_EXPLORE_TIME;
  4222.  
  4223.        // reset averaging vars
  4224.        puffs[index].varsI[PUFF_INDEX_SUM_X]      = 0;     
  4225.        puffs[index].varsI[PUFF_INDEX_SUM_Y]      = 0;    
  4226.        puffs[index].varsI[PUFF_INDEX_BOUNCE_MAX] = 12 + rand()%20; // + f(level)
  4227.  
  4228.        // general counters
  4229.        puffs[index].counter_1 = 0;
  4230.        puffs[index].counter_2 = 0;
  4231.  
  4232.        // set position
  4233.        puffs[index].x = x;
  4234.        puffs[index].y = y;
  4235.  
  4236.        // save for restart
  4237.        puffs[index].varsI[PUFF_INDEX_SAVED_X]   = x;               
  4238.        puffs[index].varsI[PUFF_INDEX_SAVED_Y]   = y;              
  4239.        puffs[index].varsI[PUFF_INDEX_SAVED_DIR] = dir;    
  4240.  
  4241.        // the the current animation of puff
  4242.        if (dir==DIR_LEFT || dir==DIR_UP)    
  4243.           {
  4244.           Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_LEFT);
  4245.           puffs[index].varsI[PUFF_INDEX_ANIM_DIR]     = DIR_LEFT;
  4246.           } // end if
  4247.        else
  4248.        if (dir==DIR_RIGHT || dir==DIR_DOWN)    
  4249.           {
  4250.           Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_RIGHT);
  4251.           puffs[index].varsI[PUFF_INDEX_ANIM_DIR]     = DIR_RIGHT;
  4252.           } // end if
  4253.  
  4254.        // return success
  4255.        return(1);
  4256.  
  4257.        } // end if
  4258.  
  4259.     } // end for index
  4260.  
  4261. // return failure 
  4262. return(0);
  4263.  
  4264. } // end Start_Puff
  4265.  
  4266. //////////////////////////////////////////////////////////////
  4267.  
  4268. int Process_Puffs(void)
  4269. {
  4270. // this function processes and controls the ai for al the puffs
  4271.  
  4272. int index,    // looping variable
  4273.     pdx,pdy,  // velocity
  4274.     sx,sy;    // sample points
  4275.  
  4276. static int puff_counter_1 = 0; // used to initiate random events
  4277.  
  4278. static char *state_names[] = {"stop","explore","chase","evade","burrow","crushed","inflating", "popped"};
  4279.  
  4280. // loop and process all puffs
  4281. //mono.set_cursor(0,15);
  4282. //mono.print("Puff System States");
  4283.  
  4284. // draw each puff
  4285. for (index=0; index < NUM_PUFFS; index++)
  4286.     {
  4287.     // is puff this available
  4288.     if (puffs[index].state != PUFF_STATE_DEAD)
  4289.        {
  4290. //       sprintf(buffer,"\nPuff %d,  AI State = %s, XB = %d, YB=%d, PSI = %d, count_2 = %d        ",index,
  4291. //              state_names[puffs[index].varsI[PUFF_INDEX_AI_STATE]],
  4292. //              puffs[index].varsI[PUFF_INDEX_SUM_X],
  4293. //              puffs[index].varsI[PUFF_INDEX_SUM_Y],
  4294. //              puffs[index].varsI[PUFF_INDEX_PSI_COUNT],
  4295. //              puffs[index].max_count_2);
  4296.  
  4297. //        mono.print(buffer);
  4298.  
  4299.        // test for collisions here
  4300.        if (dug.state == DUG_STATE_ALIVE &&
  4301.            puffs[index].varsI[PUFF_INDEX_AI_STATE] != PUFF_AI_STATE_CRUSHED &&
  4302.            puffs[index].varsI[PUFF_INDEX_AI_STATE] != PUFF_AI_STATE_INFLATING)
  4303.           {
  4304.           if (Collision_BOBS(&dug,&puffs[index]))
  4305.              {
  4306.              // start the death sequence
  4307.              Start_Dug_Death();
  4308.  
  4309.              } // end if
  4310.           } // end if
  4311.  
  4312.       // test for being crushed by rock
  4313.       for (int rindex=0; rindex < NUM_ROCKS; rindex++)
  4314.           {
  4315.           // test if rock is alive
  4316.           if (rocks[rindex].state==ROCK_STATE_FALLING)
  4317.              {
  4318.              // rock is alive, so test for collision with puff
  4319.              if (Collision_BOBS(&rocks[rindex],&puffs[index]) && puffs[index].varsI[PUFF_INDEX_AI_STATE] != PUFF_AI_STATE_CRUSHED)
  4320.                 {
  4321.                 // first reset all state information of puff
  4322.                 //puffs[index].state = PUFF_STATE_DYING;
  4323.  
  4324.                 puffs[index].varsI[PUFF_INDEX_AI_STATE]   = PUFF_AI_STATE_CRUSHED;
  4325.                 puffs[index].varsI[PUFF_INDEX_ANIM_STATE] = PUFF_ANIM_STATE_CRUSHED;
  4326.  
  4327.                 // start crunch sound
  4328.                 Play_Sound_From_Pool(crunch_snd_ids,4);
  4329.  
  4330.                 // tag rock
  4331.                 puffs[index].varsI[PUFF_INDEX_OBJECT_PTR] = rindex;
  4332.  
  4333.                 // set animation
  4334.                 if (puffs[index].varsI[PUFF_INDEX_CURR_DIR] == DIR_RIGHT || 
  4335.                     puffs[index].varsI[PUFF_INDEX_CURR_DIR] == DIR_UP)
  4336.                    {
  4337.                    // set new animation
  4338.                    Set_Animation_BOB2(&puffs[index],PUFF_ANIM_CRUSH_RIGHT);  
  4339.                    } // end if
  4340.                 else
  4341.                    {
  4342.                    // set new animation
  4343.                    Set_Animation_BOB2(&puffs[index],PUFF_ANIM_CRUSH_LEFT);  
  4344.                    } // end if
  4345.  
  4346.                 // that's it
  4347.                 break;
  4348.                 
  4349.                 } // end if
  4350.  
  4351.              } // end if
  4352.  
  4353.           } // end for rindex
  4354.  
  4355.  
  4356.       // check for hit with pumps
  4357.       for (int gindex=0; gindex < NUM_GPUMPS; gindex++)
  4358.           {
  4359.           // test if this pump is usuable
  4360.           if (gpumps[gindex].state!=GPUMP_STATE_DEAD && 
  4361.               puffs[index].max_count_2==0 &&
  4362.               puffs[index].varsI[PUFF_INDEX_AI_STATE] != PUFF_AI_STATE_CRUSHED )
  4363.              { 
  4364.              if (Collision_BOBS(&gpumps[gindex],&puffs[index]))
  4365.                 {
  4366.                 // kill the pump
  4367.                 gpumps[gindex].state=GPUMP_STATE_DEAD;
  4368.  
  4369.                 // make pump sound
  4370.                 Play_Sound_From_Pool(air_snd_ids, 4);
  4371.  
  4372.                 // change to inflate mode
  4373.                 puffs[index].varsI[PUFF_INDEX_AI_STATE]   =  PUFF_AI_STATE_INFLATING;
  4374.                 puffs[index].varsI[PUFF_INDEX_ANIM_STATE] =  PUFF_ANIM_STATE_INFLATING;
  4375.  
  4376.                 if (puffs[index].varsI[PUFF_INDEX_PSI_COUNT] < 3*GPUMP_INJECTION)
  4377.                    {
  4378.                    puffs[index].varsI[PUFF_INDEX_PSI_COUNT]  += (GPUMP_INJECTION-1);
  4379.  
  4380.                    if (puffs[index].varsI[PUFF_INDEX_PSI_COUNT] > 3*GPUMP_INJECTION)
  4381.                        puffs[index].varsI[PUFF_INDEX_PSI_COUNT] = 3*GPUMP_INJECTION;
  4382.                       
  4383.                    } // end if
  4384.  
  4385.                 // this is a pump puff!
  4386.                 break;
  4387.  
  4388.                 } // end if
  4389.  
  4390.              } // end if
  4391.  
  4392.           } // end gindex
  4393.  
  4394.  
  4395.  
  4396.        // what is the ai state of the puff
  4397.        // C R U S H E D   L O G I C //////////////////////////////////////////////////
  4398.        if (puffs[index].varsI[PUFF_INDEX_AI_STATE] == PUFF_AI_STATE_CRUSHED)
  4399.           {
  4400.           // the puff is getting crushed, simple track tagged rock
  4401.           puffs[index].x = rocks[puffs[index].varsI[PUFF_INDEX_OBJECT_PTR]].x;
  4402.           puffs[index].y = rocks[puffs[index].varsI[PUFF_INDEX_OBJECT_PTR]].y+8;
  4403.  
  4404.           // test if rock is complete and in crumble mode
  4405.           if (rocks[puffs[index].varsI[PUFF_INDEX_OBJECT_PTR]].state==ROCK_STATE_DEAD)
  4406.              {
  4407.              // terminate puff
  4408.              puffs[index].state = PUFF_STATE_DEAD;
  4409.  
  4410.              // one more for the gipper
  4411.              dug.varsI[DUG_INDEX_KILLS]++;
  4412.              
  4413.              int score = 100+100*(puffs[index].y/100);
  4414.  
  4415.              // start up score object
  4416.              dug.varsI[DUG_INDEX_SCORE]+=score;
  4417.  
  4418.              // start up score object
  4419.              Start_Score(puffs[index].x+16 - 4 + rand()%8,puffs[index].y+16 - 4+rand()%8, score);
  4420.  
  4421.              } // end if
  4422.  
  4423.           } // end if   
  4424.        else
  4425.            //// F I R E    L O G I C  /////////////////////////////////////////////////////
  4426.        if (puffs[index].varsI[PUFF_INDEX_AI_STATE]==PUFF_AI_STATE_FIRE)
  4427.           {
  4428.           // the puff is stopped to fire
  4429.           if (--puffs[index].counter_1 == 15)
  4430.              {
  4431.            // test for totally random shot
  4432.            if ((puffs[index].varsI[PUFF_INDEX_SUM_X] >= 3) || 
  4433.                (puffs[index].varsI[PUFF_INDEX_SUM_Y] >= 3) &&
  4434.                ((rand()%10)==1) )
  4435.                { 
  4436.                // if up/down then fire right/left
  4437.                if ((puffs[index].varsI[PUFF_INDEX_CURR_DIR]==DIR_UP) || 
  4438.                   (puffs[index].varsI[PUFF_INDEX_CURR_DIR]==DIR_DOWN) )
  4439.                   {
  4440.                   Start_Fball(puffs[index].x+8, puffs[index].y+2,
  4441.                               ((rand()%2) ? (DIR_RIGHT) : (DIR_LEFT)),
  4442.                               rand()%2);
  4443.                   } // end if
  4444.               else
  4445.                   {
  4446.                   // up down
  4447.                   Start_Fball(puffs[index].x+8, puffs[index].y+8,
  4448.                               ((rand()%2) ? (DIR_UP) : (DIR_DOWN)),
  4449.                               rand()%2);
  4450.                   } // end else
  4451.  
  4452.               } // end if rand
  4453.             else
  4454.             if ((puffs[index].varsI[PUFF_INDEX_CURR_DIR]==DIR_LEFT) || 
  4455.                 (puffs[index].varsI[PUFF_INDEX_CURR_DIR]==DIR_RIGHT) )
  4456.                {
  4457.                 Start_Fball(puffs[index].x+8, puffs[index].y+2,
  4458.                             puffs[index].varsI[PUFF_INDEX_CURR_DIR],
  4459.                             rand()%2);
  4460.                } // end if
  4461.             else
  4462.             if ((puffs[index].varsI[PUFF_INDEX_CURR_DIR]==DIR_UP) || 
  4463.                 (puffs[index].varsI[PUFF_INDEX_CURR_DIR]==DIR_DOWN) )
  4464.                {
  4465.                 // vertical
  4466.                 Start_Fball(puffs[index].x+8, puffs[index].y+8,
  4467.                             puffs[index].varsI[PUFF_INDEX_CURR_DIR],
  4468.                             rand()%2);
  4469.                 } // end if
  4470.  
  4471.             } // end if
  4472.          else
  4473.          if (puffs[index].counter_1 <= 0)
  4474.             {
  4475.             // set state back to chase
  4476.             puffs[index].varsI[PUFF_INDEX_AI_STATE]=PUFF_AI_STATE_CHASE;
  4477.  
  4478.             } // end if
  4479.  
  4480.           } // end if
  4481.        else
  4482.        //// I N F L A T I O N   S T A T E /////////////////////////////////////////////
  4483.        if (puffs[index].varsI[PUFF_INDEX_AI_STATE]==PUFF_AI_STATE_INFLATING)
  4484.           {
  4485.  
  4486.           if (puffs[index].varsI[PUFF_INDEX_PSI_COUNT] < 3*GPUMP_INJECTION)
  4487.           {
  4488.           // decrease inflation
  4489.           if (--puffs[index].varsI[PUFF_INDEX_PSI_COUNT] <= 0)
  4490.              {
  4491.              // switch to chase mode
  4492.  
  4493.              // reset bounce counters
  4494.              puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  4495.              puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  4496.              puffs[index].max_count_2 = 0;
  4497.  
  4498.              // change modes
  4499.              puffs[index].varsI[PUFF_INDEX_AI_STATE] = PUFF_AI_STATE_CHASE;             
  4500.  
  4501.              // set animation correctly
  4502.              // the the current animation of puff
  4503.              if (puffs[index].varsI[PUFF_INDEX_CURR_DIR]==DIR_LEFT || puffs[index].varsI[PUFF_INDEX_CURR_DIR]==DIR_UP)    
  4504.                 {
  4505.                 Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_LEFT);
  4506.                 puffs[index].varsI[PUFF_INDEX_ANIM_STATE] = PUFF_ANIM_STATE_BOUNCE;
  4507.                 } // end if
  4508.             else
  4509.                 {
  4510.                 Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_RIGHT);
  4511.                 puffs[index].varsI[PUFF_INDEX_ANIM_STATE] = PUFF_ANIM_STATE_BOUNCE;
  4512.                 } // end if
  4513.  
  4514.              } // end if
  4515.  
  4516.           } // end if
  4517.           else
  4518.           if (++puffs[index].varsI[PUFF_INDEX_PSI_COUNT] > (3*GPUMP_INJECTION + GPUMP_INJECTION/2))
  4519.              {
  4520.              // kill the puff
  4521.              puffs[index].state = PUFF_STATE_DEAD;
  4522.              puffs[index].max_count_2 = 0;
  4523.  
  4524.              // one more for the gipper
  4525.              dug.varsI[DUG_INDEX_KILLS]++;
  4526.  
  4527.              int score = 100+100*(puffs[index].y/100);
  4528.           
  4529.              if (dug.varsI[DUG_INDEX_DIR] == DIR_LEFT ||  dug.varsI[DUG_INDEX_DIR] == DIR_RIGHT)
  4530.                 score+=50;           
  4531.  
  4532.              // start up score object
  4533.              Start_Score(puffs[index].x+16 - 4 + rand()%8,puffs[index].y+16 - 4+rand()%8,score);
  4534.              dug.varsI[DUG_INDEX_SCORE]+=score;             
  4535.  
  4536.              } // end if
  4537.  
  4538.           } // end if
  4539.  
  4540.        else // E X P L O R E   L O G I C ///////////////////////////////////////////////
  4541.        if (puffs[index].varsI[PUFF_INDEX_AI_STATE]==PUFF_AI_STATE_EXPLORE)
  4542.           {
  4543.           // this is the general exploration ai
  4544.           // test the current direction of the puff
  4545.           switch(puffs[index].varsI[PUFF_INDEX_CURR_DIR])
  4546.                 {
  4547.                 case DIR_LEFT:
  4548.                      {
  4549.                      // compute velocity changes
  4550.                      pdx = -PUFF_SPEED;
  4551.                      pdy = 0;
  4552.  
  4553.                      // move puff
  4554.                      puffs[index].x+=pdx;
  4555.                      puffs[index].y+=pdy;
  4556.  
  4557.                      // compute sample position
  4558.                      sx = puffs[index].x; 
  4559.                      sy = puffs[index].y + 16;
  4560.      
  4561.                      // check for collision
  4562.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE ||
  4563.                          puffs[index].x <= 0)
  4564.                         {
  4565.                         // reverse the direction of motion
  4566.                         puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4567.                         puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_RIGHT;
  4568.                         
  4569.                         // set new animation
  4570.                         Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_RIGHT);                        
  4571.        
  4572.                         } // end if 
  4573.  
  4574.                      } break;        
  4575.  
  4576.                 case DIR_RIGHT:
  4577.                      {
  4578.                      // compute velocity changes
  4579.                      pdx = PUFF_SPEED;
  4580.                      pdy = 0;
  4581.  
  4582.                      // move puff
  4583.                      puffs[index].x+=pdx;
  4584.                      puffs[index].y+=pdy;
  4585.  
  4586.                      // compute sample position
  4587.                      sx = puffs[index].x + 31;
  4588.                      sy = puffs[index].y + 16;
  4589.      
  4590.                      // check for collision
  4591.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE || 
  4592.                         puffs[index].x >= (SCREEN_WIDTH - 32)) 
  4593.                         {
  4594.                         // reverse the direction of motion
  4595.                         puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4596.                         puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_LEFT;
  4597.                         
  4598.                         // set new animation
  4599.                         Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_LEFT);                        
  4600.        
  4601.                         } // end if 
  4602.                      } break;        
  4603.  
  4604.                 case DIR_UP:
  4605.                      {
  4606.                      // compute velocity changes
  4607.                      pdy = -PUFF_SPEED;
  4608.                      pdx = 0;
  4609.  
  4610.                      // move puff
  4611.                      puffs[index].x+=pdx;
  4612.                      puffs[index].y+=pdy;
  4613.  
  4614.                      // compute sample position
  4615.                      sx = puffs[index].x + 16;
  4616.                      sy = puffs[index].y;
  4617.      
  4618.                      // check for collision
  4619.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE  || 
  4620.                           puffs[index].y <= (DUG_MIN_ROCK_LINE))
  4621.                         {
  4622.                         // reverse the direction of motion
  4623.                         puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4624.                         puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_DOWN;
  4625.                         
  4626.                         } // end if 
  4627.  
  4628.                      } break;        
  4629.  
  4630.  
  4631.                 case DIR_DOWN:
  4632.                      {
  4633.                      // compute velocity changes
  4634.                      pdy = PUFF_SPEED;
  4635.                      pdx = 0;
  4636.  
  4637.                      // move puff
  4638.                      puffs[index].x+=pdx;
  4639.                      puffs[index].y+=pdy;
  4640.  
  4641.                      // compute sample position
  4642.                      sx = puffs[index].x + 16;
  4643.                      sy = puffs[index].y + 31;
  4644.      
  4645.                      // check for collision
  4646.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE  || 
  4647.                          puffs[index].y >= (SCREEN_HEIGHT-32))
  4648.                         {
  4649.                         // reverse the direction of motion
  4650.                         puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4651.                         puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_UP;
  4652.                         
  4653.                         } // end if 
  4654.  
  4655.                      } break;        
  4656.  
  4657.                 default:break;
  4658.  
  4659.                 } // end switch 
  4660.  
  4661.          // at this point the puff has moved, let's test if we can make a turn
  4662.          
  4663.          if (puffs[index].varsI[PUFF_INDEX_CURR_DIR] == DIR_LEFT || 
  4664.              puffs[index].varsI[PUFF_INDEX_CURR_DIR] == DIR_RIGHT)
  4665.             {
  4666.             // try for up or down turn
  4667.             if (!((int)puffs[index].x % DUG_X_INTERVAL))
  4668.                {
  4669.                // it legal to make a turn
  4670.                // select a direction
  4671.                if ((rand()%2) == 1)
  4672.                {
  4673.                // try and turn up
  4674.                sx = puffs[index].x + 16;
  4675.                sy = puffs[index].y - 1;
  4676.      
  4677.                // check for collision
  4678.                if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE &&
  4679.                    Get_Pixel(sx,sy-2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  4680.                   {
  4681.                   // reverse the direction of motion
  4682.                   puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4683.                   puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_UP;
  4684.                   } // end if
  4685.  
  4686.                }
  4687.                else
  4688.                {
  4689.                // try and turn down
  4690.                sx = puffs[index].x + 16;
  4691.                sy = puffs[index].y + 32;
  4692.      
  4693.                // check for collision
  4694.                if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE &&
  4695.                    Get_Pixel(sx,sy+2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  4696.                   {
  4697.                   // reverse the direction of motion
  4698.                   puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4699.                   puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_DOWN;
  4700.                   } // end if
  4701.  
  4702.                } // end else
  4703.  
  4704.                } // end if  
  4705.  
  4706.             } // end if
  4707.          else
  4708.          if (puffs[index].varsI[PUFF_INDEX_CURR_DIR] == DIR_UP || 
  4709.              puffs[index].varsI[PUFF_INDEX_CURR_DIR] == DIR_DOWN)          
  4710.             { 
  4711.  
  4712.             // try for up or down turn
  4713.             if (!(((int)puffs[index].y + 8) % DUG_X_INTERVAL))
  4714.                {
  4715.                // it legal to make a turn
  4716.                // select a direction
  4717.                if ((rand()%2)==1)
  4718.                {
  4719.                // try and turn right 
  4720.                sx = puffs[index].x + 32;
  4721.                sy = puffs[index].y + 16;
  4722.      
  4723.                // check for collision
  4724.                if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  4725.                    Get_Pixel(sx + 2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  4726.                   {
  4727.                   // reverse the direction of motion
  4728.                   puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4729.                   puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_RIGHT;
  4730.                   Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_RIGHT);   
  4731.                   } // end if
  4732.                } // end if
  4733.  
  4734.                else
  4735.                {
  4736.                // try and turn down
  4737.                sx = puffs[index].x - 1;
  4738.                sy = puffs[index].y + 16;
  4739.      
  4740.                // check for collision
  4741.                if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  4742.                    Get_Pixel(sx - 2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  4743.                   {
  4744.                   // reverse the direction of motion
  4745.                   puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4746.                   puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_LEFT;
  4747.                   Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_LEFT);   
  4748.                   } // end if
  4749.                } // end else
  4750.  
  4751.                } // end if  
  4752.  
  4753.             } // end if
  4754.  
  4755.          // test for fire
  4756.          if ( ((rand()%(200-dug.varsI[DUG_INDEX_LEVEL]))==1))
  4757.             {
  4758.             // set timer
  4759.             puffs[index].counter_1 = 30;
  4760.  
  4761.             // set new state
  4762.             puffs[index].varsI[PUFF_INDEX_AI_STATE] = PUFF_AI_STATE_FIRE;
  4763.  
  4764.             } // end if
  4765.  
  4766.           // test for state exit
  4767.           if (--puffs[index].varsI[PUFF_INDEX_EXPLORE_COUNTER] <=0)
  4768.              {
  4769.              // set state to chase
  4770.              puffs[index].varsI[PUFF_INDEX_AI_STATE]=PUFF_AI_STATE_CHASE;
  4771.  
  4772.              // reset counter
  4773.              puffs[index].varsI[PUFF_INDEX_EXPLORE_COUNTER] = PUFF_EXPLORE_TIME;
  4774.  
  4775.              } // end if
  4776.  
  4777.           } // end if
  4778.        else /// C H A S E  L O G I C ///////////////////////////////////////////////////
  4779.        if (puffs[index].varsI[PUFF_INDEX_AI_STATE]==PUFF_AI_STATE_CHASE)
  4780.           {
  4781.           int desired_taken = 0; // used to track if desired was taken
  4782.  
  4783.           // test the current direction of the puff
  4784.           switch(puffs[index].varsI[PUFF_INDEX_CURR_DIR])
  4785.                 {
  4786.                 case DIR_LEFT:
  4787.                      {
  4788.                      // compute velocity changes
  4789.                      pdx = -PUFF_SPEED;
  4790.                      pdy = 0;
  4791.  
  4792.                      // move puff
  4793.                      puffs[index].x+=pdx;
  4794.                      puffs[index].y+=pdy;
  4795.  
  4796.                      // compute sample position
  4797.                      sx = puffs[index].x;
  4798.                      sy = puffs[index].y + 16;
  4799.      
  4800.                      // check for collision
  4801.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE || 
  4802.                         puffs[index].x <= 0)
  4803.                         {
  4804.                         // reverse the direction of motion
  4805.                         puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4806.                         puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_RIGHT;
  4807.  
  4808.                         // set new animation
  4809.                         Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_RIGHT);                        
  4810.  
  4811.                         // increment x-axis bounce counter
  4812.                         puffs[index].varsI[PUFF_INDEX_SUM_X]++;
  4813.                         puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  4814.       
  4815.                         } // end if 
  4816.  
  4817.                      } break;        
  4818.  
  4819.                 case DIR_RIGHT:
  4820.                      {
  4821.                      // compute velocity changes
  4822.                      pdx = PUFF_SPEED;
  4823.                      pdy = 0;
  4824.  
  4825.                      // move puff
  4826.                      puffs[index].x+=pdx;
  4827.                      puffs[index].y+=pdy;
  4828.  
  4829.                      // compute sample position
  4830.                      sx = puffs[index].x + 31;
  4831.                      sy = puffs[index].y + 16;
  4832.      
  4833.                      // check for collision
  4834.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE || 
  4835.                         puffs[index].x >= (SCREEN_WIDTH - 32))
  4836.                         {
  4837.                         // reverse the direction of motion
  4838.                         puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4839.                         puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_LEFT;
  4840.  
  4841.                         // set new animation
  4842.                         Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_LEFT);                        
  4843.  
  4844.                         // increment x-axis bounce counter
  4845.                         puffs[index].varsI[PUFF_INDEX_SUM_X]++;
  4846.                         puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  4847.        
  4848.                         } // end if 
  4849.                      } break;        
  4850.  
  4851.                 case DIR_UP:
  4852.                      {
  4853.                      // compute velocity changes
  4854.                      pdy = -PUFF_SPEED;
  4855.                      pdx = 0;
  4856.  
  4857.                      // move puff
  4858.                      puffs[index].x+=pdx;
  4859.                      puffs[index].y+=pdy;
  4860.  
  4861.                      // compute sample position
  4862.                      sx = puffs[index].x + 16;
  4863.                      sy = puffs[index].y;
  4864.      
  4865.                      // check for collision
  4866.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE || 
  4867.                          puffs[index].y <= (DUG_MIN_ROCK_LINE))
  4868.                         {
  4869.                         // reverse the direction of motion
  4870.                         puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4871.                         puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_DOWN;
  4872.  
  4873.                         // increment y-axis bounce counter
  4874.                         puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  4875.                         puffs[index].varsI[PUFF_INDEX_SUM_Y]++;
  4876.  
  4877.                         } // end if 
  4878.  
  4879.                      } break;        
  4880.  
  4881.  
  4882.                 case DIR_DOWN:
  4883.                      {
  4884.                      // compute velocity changes
  4885.                      pdy = PUFF_SPEED;
  4886.                      pdx = 0;
  4887.  
  4888.                      // move puff
  4889.                      puffs[index].x+=pdx;
  4890.                      puffs[index].y+=pdy;
  4891.  
  4892.                      // compute sample position
  4893.                      sx = puffs[index].x + 16;
  4894.                      sy = puffs[index].y + 31;
  4895.      
  4896.                      // check for collision
  4897.                      if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)!=COLOR_INDEX_HOLE  || 
  4898.                          puffs[index].y >= (SCREEN_HEIGHT-32))
  4899.                         {
  4900.                         // reverse the direction of motion
  4901.                         puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4902.                         puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_UP;
  4903.  
  4904.                         // increment y-axis bounce counter
  4905.                         puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  4906.                         puffs[index].varsI[PUFF_INDEX_SUM_Y]++;
  4907.                     
  4908.                         } // end if 
  4909.  
  4910.                      } break;        
  4911.  
  4912.  
  4913.                 default:break;
  4914.  
  4915.                 } // end switch 
  4916.  
  4917.          // at this point the puff has moved, let's test if we can make a turn
  4918.          // compute the desired new direction
  4919.          // compute dx and dy
  4920.  
  4921.          int dx = dug.x - puffs[index].x;
  4922.          int dy = dug.y - puffs[index].y;
  4923.  
  4924.          // decide which way we want to go
  4925.          if (abs(dx) > abs(dy))
  4926.             {
  4927.             // set primary desired direction to minimize dx 
  4928.             if (dx > 0)
  4929.                puffs[index].varsI[PUFF_INDEX_DESIRED_DIR] = DIR_RIGHT;
  4930.             else
  4931.                puffs[index].varsI[PUFF_INDEX_DESIRED_DIR] = DIR_LEFT;
  4932.  
  4933.             // set secondary direction only if delta is > 16
  4934.             if (abs(dy) > 16)
  4935.                {
  4936.                 if (dy > 0)
  4937.                     puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] = DIR_DOWN;
  4938.                 else
  4939.                    puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] = DIR_UP;
  4940.                 } // end if
  4941.             else
  4942.                 puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] = DIR_NULL;
  4943.  
  4944.             } // end if
  4945.          else
  4946.             {
  4947.             // set primary desired direction to minimize dy
  4948.             if (dy > 0)
  4949.                puffs[index].varsI[PUFF_INDEX_DESIRED_DIR] = DIR_DOWN;
  4950.             else
  4951.                puffs[index].varsI[PUFF_INDEX_DESIRED_DIR] = DIR_UP;
  4952.  
  4953.             // set secondary desired direction to minimize dx, only if dx > 16
  4954.             if (abs(dx) > 16)
  4955.                {
  4956.                if (dx > 0)
  4957.                   puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] = DIR_RIGHT;
  4958.                else
  4959.                   puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] = DIR_LEFT;
  4960.                } // end if
  4961.              else
  4962.                 puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] = DIR_NULL;
  4963.  
  4964.             } // end if               
  4965.  
  4966.         // once in a blue moon swap primary and secondary
  4967.         if ((rand()%10)==1)
  4968.            {
  4969.            // swap
  4970.            int temp = puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR];
  4971.            puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] = puffs[index].varsI[PUFF_INDEX_DESIRED_DIR];
  4972.            puffs[index].varsI[PUFF_INDEX_DESIRED_DIR]     = temp;
  4973.  
  4974.            } // end if
  4975.          
  4976.         // make sure we don't want to go the same way
  4977.         if ( (puffs[index].varsI[PUFF_INDEX_DESIRED_DIR] >> 1) != (puffs[index].varsI[PUFF_INDEX_CURR_DIR] >> 1))
  4978.         {
  4979.            
  4980.          // test for desired right turn     
  4981.          if (puffs[index].varsI[PUFF_INDEX_DESIRED_DIR] == DIR_RIGHT && 
  4982.              !(((int)puffs[index].y+8) % DUG_X_INTERVAL))
  4983.             {
  4984.             // try and turn up
  4985.             sx = puffs[index].x + 32;
  4986.             sy = puffs[index].y + 16;
  4987.      
  4988.             // check for collision
  4989.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  4990.                 Get_Pixel(sx+2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  4991.                {
  4992.                // reverse the direction of motion
  4993.                puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  4994.                puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_RIGHT;
  4995.  
  4996.                // set new animation
  4997.                Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_RIGHT);   
  4998.  
  4999.                // set taken flag
  5000.                desired_taken = 1;
  5001.  
  5002.                // reset bounce counters
  5003.                puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  5004.                puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  5005.  
  5006.                } // end if
  5007.  
  5008.             } // end if
  5009.  
  5010.          // test for desired right turn     
  5011.          else
  5012.          if (puffs[index].varsI[PUFF_INDEX_DESIRED_DIR] == DIR_LEFT && 
  5013.              !(((int)puffs[index].y+8) % DUG_X_INTERVAL))
  5014.             {
  5015.             // try and turn up
  5016.             sx = puffs[index].x - 1;
  5017.             sy = puffs[index].y + 16;
  5018.      
  5019.             // check for collision
  5020.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  5021.                 Get_Pixel(sx - 2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  5022.                {
  5023.                // reverse the direction of motion
  5024.                puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  5025.                puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_LEFT;
  5026.  
  5027.                // set new animation
  5028.                Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_LEFT);   
  5029.  
  5030.                // set taken flag
  5031.                desired_taken = 1;
  5032.  
  5033.                // reset bounce counters
  5034.                puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  5035.                puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  5036.  
  5037.                } // end if
  5038.  
  5039.             } // end if
  5040.          else
  5041.          if (puffs[index].varsI[PUFF_INDEX_DESIRED_DIR] == DIR_UP && 
  5042.              !(((int)puffs[index].x) % DUG_X_INTERVAL))
  5043.             {
  5044.             // try and turn up
  5045.             sx = puffs[index].x + 16;
  5046.             sy = puffs[index].y - 1;
  5047.      
  5048.             // check for collision
  5049.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE &&
  5050.                 Get_Pixel(sx,sy - 2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  5051.                {
  5052.                // reverse the direction of motion
  5053.                puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  5054.                puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_UP;
  5055.  
  5056.                // set taken flag
  5057.                desired_taken = 1;
  5058.  
  5059.                // reset bounce counters
  5060.                puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  5061.                puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  5062.  
  5063.                } // end if
  5064.  
  5065.             } // end if
  5066.          else
  5067.          if (puffs[index].varsI[PUFF_INDEX_DESIRED_DIR] == DIR_DOWN && 
  5068.              !(((int)puffs[index].x) % DUG_X_INTERVAL))
  5069.             {
  5070.             // try and turn up
  5071.             sx = puffs[index].x + 16;
  5072.             sy = puffs[index].y + 32;
  5073.      
  5074.             // check for collision
  5075.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  5076.                Get_Pixel(sx,sy+2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  5077.                {
  5078.                // reverse the direction of motion
  5079.                puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  5080.                puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_DOWN;
  5081.  
  5082.                // set taken flag
  5083.                desired_taken = 1;
  5084.  
  5085.                // reset bounce counters
  5086.                puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  5087.                puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  5088.  
  5089.                } // end if
  5090.  
  5091.             } // end if
  5092.  
  5093.          } // end if primary valid
  5094.  
  5095.  
  5096.          ///////////////////////////////////////////////////////////////////////
  5097.          // test for secondary turns
  5098.      
  5099.          if (!desired_taken && 
  5100.             (puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR]!=DIR_NULL) &&
  5101.             (puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] >> 1) != (puffs[index].varsI[PUFF_INDEX_CURR_DIR] >> 1) )
  5102.          {
  5103.          // test for desired right turn
  5104.          if (puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] == DIR_RIGHT && 
  5105.              !(((int)puffs[index].y+8) % DUG_X_INTERVAL))
  5106.             {
  5107.             // try and turn up
  5108.             sx = puffs[index].x + 32;
  5109.             sy = puffs[index].y + 16;
  5110.      
  5111.             // check for collision
  5112.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  5113.                 Get_Pixel(sx+2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  5114.                {
  5115.                // reverse the direction of motion
  5116.                puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  5117.                puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_RIGHT;
  5118.  
  5119.                // set new animation
  5120.                Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_RIGHT);   
  5121.                // set taken flag
  5122.                desired_taken = 1;
  5123.  
  5124.                // reset bounce counters
  5125.                puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  5126.                puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  5127.  
  5128.                } // end if
  5129.  
  5130.             } // end if
  5131.  
  5132.          // test for desired right turn     
  5133.          else
  5134.          if (puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] == DIR_LEFT && 
  5135.              !(((int)puffs[index].y+8) % DUG_X_INTERVAL))
  5136.             {
  5137.             // try and turn up
  5138.             sx = puffs[index].x - 1;
  5139.             sy = puffs[index].y + 16;
  5140.      
  5141.             // check for collision
  5142.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  5143.                 Get_Pixel(sx - 2,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  5144.                {
  5145.                // reverse the direction of motion
  5146.                puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  5147.                puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_LEFT;
  5148.  
  5149.                // set new animation
  5150.                Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_LEFT);   
  5151.  
  5152.                // set taken flag
  5153.                desired_taken = 1;
  5154.  
  5155.                // reset bounce counters
  5156.                puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  5157.                puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  5158.  
  5159.                } // end if
  5160.  
  5161.             } // end if
  5162.          else
  5163.          if (puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] == DIR_UP && 
  5164.              !(((int)puffs[index].x) % DUG_X_INTERVAL))
  5165.             {
  5166.             // try and turn up
  5167.             sx = puffs[index].x + 16;
  5168.             sy = puffs[index].y - 1;
  5169.      
  5170.             // check for collision
  5171.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE &&
  5172.                 Get_Pixel(sx,sy - 2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  5173.                {
  5174.                // reverse the direction of motion
  5175.                puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  5176.                puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_UP;
  5177.  
  5178.                // set taken flag
  5179.                desired_taken = 1;
  5180.  
  5181.                } // end if
  5182.  
  5183.             } // end if
  5184.          else
  5185.          if (puffs[index].varsI[PUFF_INDEX_2ND_DESIRED_DIR] == DIR_DOWN && 
  5186.              !(((int)puffs[index].x) % DUG_X_INTERVAL))
  5187.             {
  5188.             // try and turn up
  5189.             sx = puffs[index].x + 16;
  5190.             sy = puffs[index].y + 32;
  5191.      
  5192.             // check for collision
  5193.             if (Get_Pixel(sx,sy,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE && 
  5194.                Get_Pixel(sx,sy+2,background_bmp.buffer, background_bmp.width)==COLOR_INDEX_HOLE)
  5195.                {
  5196.                // reverse the direction of motion
  5197.                puffs[index].varsI[PUFF_INDEX_LAST_DIR] = puffs[index].varsI[PUFF_INDEX_CURR_DIR];
  5198.                puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_DOWN;
  5199.  
  5200.                // set taken flag
  5201.                desired_taken = 1;
  5202.  
  5203.                // reset bounce counters
  5204.                puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  5205.                puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  5206.  
  5207.                } // end if
  5208.  
  5209.             } // end if
  5210.  
  5211.           } // end else 2nd desired
  5212.  
  5213.  
  5214. // test for global randomness ////////////////////////////////////////////////////
  5215.           if (++puff_counter_1 > 200)
  5216.              puff_counter_1 = 0;
  5217.  
  5218.           // test for random event
  5219.           if ((puff_counter_1 == 0) && 
  5220.               ((rand()%3)==1) && 
  5221.               (Fast_Distance(puffs[index].x-dug.x, puffs[index].y-dug.y) > 300))
  5222.               {
  5223.               // reverse direction
  5224.               switch(puffs[index].varsI[PUFF_INDEX_CURR_DIR])
  5225.                     {
  5226.                     case DIR_LEFT:  
  5227.                          {
  5228.                          puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_RIGHT;  
  5229.                          // set new animation
  5230.                          Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_RIGHT);   
  5231.                          } break;
  5232.  
  5233.                     case DIR_RIGHT: 
  5234.                          {
  5235.                          puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_LEFT;  
  5236.                          // set new animation
  5237.                          Set_Animation_BOB2(&puffs[index],PUFF_ANIM_BOUNCE_LEFT);   
  5238.                          } break;
  5239.  
  5240.                     case DIR_UP:    puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_DOWN; break;
  5241.                     case DIR_DOWN:  puffs[index].varsI[PUFF_INDEX_CURR_DIR] = DIR_UP; break;
  5242.  
  5243.                     default:break;
  5244.                     } // end switch
  5245.  
  5246.               } // end if
  5247. ///////////////////////////////////////////////////////////////////////////
  5248.  
  5249.          // test for pre-emptive state transitions
  5250.          if (puffs[index].varsI[PUFF_INDEX_SUM_X] > 3 || puffs[index].varsI[PUFF_INDEX_SUM_Y] > 3)
  5251.             {
  5252.             // reset bounce counters
  5253.             puffs[index].varsI[PUFF_INDEX_SUM_X] = 0;
  5254.             puffs[index].varsI[PUFF_INDEX_SUM_Y] = 0;
  5255.  
  5256.             // change modes
  5257.             puffs[index].varsI[PUFF_INDEX_AI_STATE]   =   PUFF_AI_STATE_EXPLORE;
  5258.             puffs[index].varsI[PUFF_INDEX_EXPLORE_COUNTER] = (PUFF_EXPLORE_TIME >> 2) + (rand()%PUFF_EXPLORE_TIME);
  5259.  
  5260.             } // end if
  5261.  
  5262.  
  5263.          // test for weapons fire, add in level here for prob
  5264.          if ( 
  5265.               //(puffs[index].varsI[PUFF_INDEX_CURR_DIR] == DIR_LEFT || puffs[index].varsI[PUFF_INDEX_CURR_DIR] == DIR_RIGHT) && 
  5266.               ((rand()%(100-dug.varsI[DUG_INDEX_LEVEL]))==1))
  5267.                // && (Fast_Distance(dug.x - puffs[index].x,dug.y - puffs[index].y) < 300))
  5268.             {
  5269.             // set timer
  5270.             puffs[index].counter_1 = 30;
  5271.  
  5272.             // set new state
  5273.             puffs[index].varsI[PUFF_INDEX_AI_STATE] = PUFF_AI_STATE_FIRE;
  5274.  
  5275.             } // end if
  5276.  
  5277.           } // end if chase
  5278.  
  5279.        else //////////////////////////////////////////////////////////////////////////
  5280.        if (puffs[index].varsI[PUFF_INDEX_AI_STATE]==PUFF_AI_STATE_EVADE)
  5281.           {
  5282.  
  5283.           } // end if
  5284.        
  5285.        else /////////////////////////////////////////////////////////////////////////
  5286.        if (puffs[index].varsI[PUFF_INDEX_AI_STATE]==PUFF_AI_STATE_BURROW)
  5287.           {
  5288.  
  5289.           } // end if
  5290.  
  5291.        } // end if alive
  5292.  
  5293.     } // end for index
  5294.  
  5295. // return success
  5296. return(1);
  5297.  
  5298. } // end Process_Puffs
  5299.  
  5300. ///////////////////////////////////////////////////////////////
  5301.  
  5302. int Draw_Puffs(void)
  5303. {
  5304. // this function animates and draws all the puffs
  5305.  
  5306. int index; // looping index
  5307.  
  5308. // draw each puff
  5309. for (index=0; index < NUM_PUFFS; index++)
  5310.     {
  5311.     // is puff this available
  5312.     if (puffs[index].state != PUFF_STATE_DEAD)
  5313.        {
  5314.        // what is the animation state?
  5315.        switch(puffs[index].varsI[PUFF_INDEX_ANIM_STATE])
  5316.              {
  5317.              case PUFF_ANIM_STATE_BOUNCE:
  5318.                   {
  5319.                   // the puff is just bouncing up and down
  5320.                   Draw_BOB(&puffs[index],lpddsback);
  5321.  
  5322.                   // animate the puff
  5323.                   Animate_BOB(&puffs[index]);
  5324.  
  5325.                   } break;
  5326.  
  5327.              case PUFF_ANIM_STATE_CRUSHED:      
  5328.                   {
  5329.  
  5330.                   // draw the puff
  5331.                   Draw_BOB(&puffs[index],lpddsback);
  5332.  
  5333.                   if (puffs[index].anim_state != BOB_STATE_ANIM_DONE)
  5334.                      {
  5335.                      // animate the puff
  5336.                      Animate_BOB2(&puffs[index]);
  5337.                      } // end if
  5338.                   
  5339.                   } break;
  5340.  
  5341.              case PUFF_ANIM_STATE_BURROW:      
  5342.                   {
  5343.                   // the puff is just bouncing up and down
  5344.                   Draw_BOB(&puffs[index],lpddsback);
  5345.  
  5346.                   // animate the puff
  5347.                   Animate_BOB(&puffs[index]);
  5348.  
  5349.                   } break;
  5350.  
  5351.              case PUFF_ANIM_STATE_INFLATING:
  5352.                   {
  5353.                   // set the position of the puffy
  5354.                   puffy.x = puffs[index].x-12;
  5355.                   puffy.y = puffs[index].y-20;
  5356.  
  5357.                   // compute frame offset
  5358.                   int frame = (puffs[index].varsI[PUFF_INDEX_PSI_COUNT]/50);
  5359.  
  5360.                   if (frame >= 3)
  5361.                      {
  5362.                      frame = 3;
  5363.  
  5364.                      // make pop sound
  5365.                      if (puffs[index].max_count_2==0)
  5366.                         {
  5367.                         // make pop sound
  5368.                         Play_Sound_From_Pool(pop_snd_ids, 4);
  5369.                         puffs[index].max_count_2=1;
  5370.  
  5371.                         } // end if
  5372.                      } // end if
  5373.  
  5374.                   // set frame
  5375.                   puffy.curr_frame = 8+4*(puffs[index].varsI[PUFF_INDEX_CURR_DIR]%2) + frame;
  5376.  
  5377.                   // draw the puffy
  5378.                   Draw_BOB(&puffy,lpddsback);
  5379.  
  5380.                   } break;
  5381.  
  5382.              default:break;
  5383.  
  5384.              } // end switch
  5385.  
  5386.  
  5387.        } // end if
  5388.  
  5389.      } // end for index
  5390.  
  5391. // return success
  5392. return(1);
  5393.  
  5394. } // end Draw_Puffs
  5395.  
  5396. ///////////////////////////////////////////////////////////////
  5397.  
  5398. int Start_Score(int x, int y, int score)
  5399. {
  5400. // this function starts a score at the given position and direction
  5401.  
  5402. // scan for an unused pump
  5403. for (int index=0; index < NUM_SCORES; index++)
  5404.     {
  5405.     // test if this score is usuable
  5406.     if (scores[index].state==SCORE_OFF)
  5407.        {
  5408.        // set the score up
  5409.        scores[index].state       = SCORE_ON;
  5410.        scores[index].x           = x-16;
  5411.        scores[index].y           = y-16;
  5412.        scores[index].max_count_1 = SCORE_DISPLAY_COUNT + rand()%25;
  5413.        scores[index].counter_1   = 0;
  5414.  
  5415.        // select proper frame
  5416.        if (score < 1000)
  5417.           scores[index].curr_frame = (score/100 - 1);
  5418.        else
  5419.           scores[index].curr_frame = ((score % 11000)/1000) + 8;        
  5420.  
  5421.        // return success
  5422.        return(1);
  5423.  
  5424.        } // end if
  5425.  
  5426.     } // end for index
  5427.  
  5428. // return failure
  5429. return(0);
  5430.  
  5431. } // end Start_Score
  5432.  
  5433. ///////////////////////////////////////////////////////////////
  5434.  
  5435. int Process_Scores(void)
  5436. {
  5437. // this functions processes all the scores
  5438.  
  5439. // process all pumps
  5440. for (int index=0; index < NUM_SCORES; index++)
  5441.     {
  5442.     // test if this score is usuable
  5443.     if (scores[index].state!=SCORE_OFF)
  5444.        {
  5445.        // decrement counter
  5446.        if (++scores[index].counter_1 > scores[index].max_count_1)
  5447.           {
  5448.           // kill score
  5449.           scores[index].state=SCORE_OFF;
  5450.  
  5451.           } // end if
  5452.  
  5453.        // move a bit
  5454.        if (scores[index].counter_1 > SCORE_DISPLAY_COUNT/2)
  5455.           scores[index].y--;
  5456.         
  5457.        } // end if alive
  5458.     
  5459.     } // end for index
  5460.  
  5461. // return sucess
  5462. return(1);
  5463.  
  5464. } // end Process_Scores
  5465.  
  5466. ////////////////////////////////////////////////////////////////
  5467.  
  5468. int Draw_Scores(void)
  5469. {
  5470. // this function draws and animates all the scores
  5471.  
  5472. // process all scores
  5473. for (int index=0; index < NUM_SCORES; index++)
  5474.     {
  5475.     // test if this scores is usuable
  5476.     if (scores[index].state!=SCORE_OFF)
  5477.        {
  5478.        // draw the bob 
  5479.        Draw_BOB(&scores[index], lpddsback);
  5480.  
  5481.        } // end if
  5482.     
  5483.     } // end for index
  5484.  
  5485. // return sucess
  5486. return(1);
  5487.  
  5488. } // end Draw_Scores
  5489.  
  5490. ////////////////////////////////////////////////////////
  5491.  
  5492. void Start_Dug_Death(void)
  5493. {
  5494. // this function starts the death sequence for the dug
  5495.  
  5496. int index; // looping index
  5497.  
  5498. // set initial animation sequence
  5499. Set_Animation_BOB2(&dug, DUG_ANIM_DEATH);
  5500. Set_Anim_Speed_BOB(&dug, 5);
  5501.  
  5502. // change states
  5503. dug.state = DUG_STATE_DYING;
  5504. dug.anim_state = 0;
  5505.  
  5506. // start sound
  5507. Play_Sound(dug_die_snd_id);
  5508.  
  5509. // reset all creatures to explore mode
  5510. for (index=0; index < NUM_POOS; index++)
  5511.     {
  5512.     // is poo this available
  5513.     if (poos[index].state != POO_STATE_DEAD && 
  5514.         poos[index].varsI[POO_INDEX_AI_STATE] != POO_AI_STATE_BURROW &&
  5515.         poos[index].varsI[POO_INDEX_AI_STATE] != POO_AI_STATE_INFLATING)
  5516.        {
  5517.        // set state to explore
  5518.        poos[index].varsI[POO_INDEX_AI_STATE] = POO_AI_STATE_EXPLORE;
  5519.        poos[index].varsI[POO_INDEX_ANIM_STATE]     = POO_ANIM_STATE_BOUNCE;
  5520.  
  5521.        // set animation
  5522.        if (poos[index].varsI[POO_INDEX_CURR_DIR] == DIR_RIGHT || 
  5523.            poos[index].varsI[POO_INDEX_CURR_DIR] == DIR_UP)
  5524.            {
  5525.            // set new animation
  5526.            Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_RIGHT);  
  5527.            } // end if
  5528.        else
  5529.            {
  5530.            // set new animation
  5531.            Set_Animation_BOB2(&poos[index],POO_ANIM_BOUNCE_LEFT);  
  5532.            } // end if      
  5533.  
  5534.        // reset counters
  5535.        poos[index].varsI[POO_INDEX_EXPLORE_COUNTER] = POO_EXPLORE_TIME + (rand()%POO_EXPLORE_TIME);
  5536.        poos[index].varsI[POO_INDEX_SUM_X] = 0;
  5537.        poos[index].varsI[POO_INDEX_SUM_Y] = 0;
  5538.  
  5539.        } // end if
  5540.  
  5541.     } // end for index
  5542.  
  5543. // add in dragon stuff
  5544.  
  5545.  
  5546. } // end Start_Dug_Death
  5547.  
  5548. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  5549.  
  5550. int Game_Init(void *parms)
  5551. {
  5552. // this function is where you do all the initialization 
  5553. // for your game
  5554.  
  5555. int index;         // looping var
  5556. char filename[80]; // used to build up files names
  5557.  
  5558. //mono.clear();
  5559. //mono.print("\ndebugger on-line\n");
  5560.  
  5561. // open the error file
  5562. Open_Error_File("Error.dat");
  5563.  
  5564. screen_width  = 640;
  5565. screen_height = 480;
  5566. screen_bpp    = 8;
  5567.  
  5568. // start up DirectDraw (replace the parms as you desire)
  5569. DD_Init(screen_width, screen_height, screen_bpp);
  5570.  
  5571. // let user knows whats up
  5572. Draw_Text_GDI("L O A D I N G . . .",
  5573.              (SCREEN_WIDTH/2) - 3*strlen("L O A D I N G . . ."), 
  5574.              (SCREEN_HEIGHT/2 - 32),
  5575.              RGB(0,0,255),lpddsprimary);
  5576.  
  5577. // initialize directsound
  5578. DSound_Init();
  5579.  
  5580. // initialize Directinput
  5581. DInput_Init();
  5582.  
  5583. // initialize all input devices
  5584. DI_Init_Keyboard();
  5585. DI_Init_Joystick(-16,16,-16,16);
  5586. DI_Init_Mouse();
  5587.  
  5588. // load all the sound and music
  5589. Load_Sound_Music();
  5590.  
  5591. // LOAD BACKGROUND ////////////////////////////////////////////
  5592.  
  5593. // create background image
  5594. Create_Bitmap(&background_bmp,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
  5595.  
  5596. // LOAD DUG ///////////////////////////////////////////////////
  5597.  
  5598. // load master dug bitmap
  5599. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDDUMB.BMP");
  5600.  
  5601. // set the palette to background image palette
  5602. Set_Palette(bitmap8bit.palette);
  5603.  
  5604. // let user knows whats up
  5605. Draw_Text_GDI("L O A D I N G . . .",
  5606.              (SCREEN_WIDTH/2) - 3*strlen("L O A D I N G . . ."), 
  5607.              (SCREEN_HEIGHT/2 - 32),
  5608.              RGB(0,255,0),lpddsprimary);
  5609.  
  5610. // fix the hole
  5611. bitmap8bit.palette[COLOR_INDEX_HOLE].peRed   = 0;
  5612. bitmap8bit.palette[COLOR_INDEX_HOLE].peGreen = 0;
  5613. bitmap8bit.palette[COLOR_INDEX_HOLE].peBlue  = 0;
  5614.  
  5615. Set_Palette_Entry(COLOR_INDEX_HOLE,&bitmap8bit.palette[COLOR_INDEX_HOLE]);
  5616.  
  5617. // create dug bob
  5618. Create_BOB(&dug,0,0,32,32,44,
  5619.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM,
  5620.            DDSCAPS_SYSTEMMEMORY);
  5621.  
  5622. // load frames for left, right, up down, (walk, dig, fire)
  5623. for (index=0; index < 32; index++)
  5624.      Load_Frame_BOB(&dug,&bitmap8bit,index,index%8,2+index/8,BITMAP_EXTRACT_MODE_CELL);  
  5625.  
  5626. // death sequence on last row
  5627. for (index=32; index < 44; index++)
  5628.      Load_Frame_BOB(&dug,&bitmap8bit,index,(index-32),6,BITMAP_EXTRACT_MODE_CELL);  
  5629.  
  5630. // load animations
  5631.  
  5632. // left
  5633. Load_Animation_BOB(&dug,0,4,dug_anims[0]);
  5634. Load_Animation_BOB(&dug,1,4,dug_anims[1]);
  5635. Load_Animation_BOB(&dug,2,2,dug_anims[2]);
  5636.  
  5637. // right
  5638. Load_Animation_BOB(&dug,3,4,dug_anims[3]);
  5639. Load_Animation_BOB(&dug,4,4,dug_anims[4]);
  5640. Load_Animation_BOB(&dug,5,2,dug_anims[5]);
  5641.  
  5642. // up
  5643. Load_Animation_BOB(&dug,6,4,dug_anims[6]);
  5644. Load_Animation_BOB(&dug,7,4,dug_anims[7]);
  5645. Load_Animation_BOB(&dug,8,2,dug_anims[8]);
  5646.  
  5647. // down
  5648. Load_Animation_BOB(&dug,9,4,dug_anims[9]);
  5649. Load_Animation_BOB(&dug,10,4,dug_anims[10]);
  5650. Load_Animation_BOB(&dug,11,2,dug_anims[11]);
  5651.  
  5652. // death
  5653. Load_Animation_BOB(&dug,12,10,dug_anims[12]);
  5654. Load_Animation_BOB(&dug,13,8,dug_anims[13]);
  5655.  
  5656. // crushing
  5657. Load_Animation_BOB(&dug,14,3,dug_anims[14]);
  5658.  
  5659. // initialize state variables in register file
  5660. dug.varsI[DUG_INDEX_SCORE]   = 0;
  5661. dug.varsI[DUG_INDEX_LIVES]   = 3;
  5662. dug.varsI[DUG_INDEX_LEVEL]   = 1;      
  5663. dug.varsI[DUG_INDEX_DAMAGE]  = 0;
  5664. dug.varsI[DUG_INDEX_KILLS]   = 0;
  5665. dug.varsI[DUG_INDEX_PUMP_PSI] = 0;
  5666.  
  5667. dug.varsI[DUG_INDEX_ANIM_MODE] = DUG_ANIM_WALK;
  5668.  
  5669. // set state to alive
  5670. dug.state = DUG_STATE_ALIVE;
  5671.  
  5672. // set direction to left
  5673. dug.varsI[DUG_INDEX_DIR] = DIR_LEFT;
  5674.  
  5675. // set initial animation sequence
  5676. Set_Animation_BOB2(&dug, DUG_ANIM_WALK + dug.varsI[DUG_INDEX_DIR]*3);
  5677.  
  5678. // set position
  5679. Set_Pos_BOB(&dug,320,32);
  5680.  
  5681. // set animation speed
  5682. Set_Anim_Speed_BOB(&dug,3);
  5683.  
  5684. // make demo clone
  5685. Clone_BOBX(&dug,&dug_demo);
  5686.  
  5687. // create digging holes
  5688. for (index=0; index < 10; index++)
  5689.     {
  5690.     // create the hole bitmap
  5691.     Create_Bitmap(&dug_holes[index],0,0,32,32);
  5692.  
  5693.     // scan it out
  5694.     Load_Image_Bitmap(&dug_holes[index],&bitmap8bit,index,10,BITMAP_EXTRACT_MODE_CELL);
  5695.  
  5696.     } // end for index
  5697.  
  5698.  
  5699. // LOAD MUSHROOMS //////////////////////////////////////////
  5700.  
  5701. // create mushroom bob
  5702. Create_BOB(&mushroom,0,0,32,32,2,
  5703.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  5704.            DDSCAPS_SYSTEMMEMORY);
  5705.  
  5706. // load frames for small and big
  5707. for (index=0; index < 2; index++)
  5708.      Load_Frame_BOB(&mushroom,&bitmap8bit,index,index,8,BITMAP_EXTRACT_MODE_CELL);  
  5709.  
  5710.  
  5711. // LOAD ROCKS ///////////////////////////////////////////////
  5712.  
  5713. // create master rock bob
  5714. Create_BOB(&rocks[0],0,0,32,32,5,
  5715.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  5716.            DDSCAPS_SYSTEMMEMORY);
  5717.  
  5718. // set state to dead
  5719. rocks[0].state = ROCK_STATE_DEAD;
  5720.  
  5721. // set animation speed
  5722. Set_Anim_Speed_BOB(&rocks[0],3);
  5723.  
  5724. // load frames in
  5725. for (index=0; index < 5; index++)
  5726.      Load_Frame_BOB(&rocks[0],&bitmap8bit,index,index,9,BITMAP_EXTRACT_MODE_CELL);  
  5727.  
  5728. // now clone bob
  5729. for (index=1; index<NUM_ROCKS; index++)
  5730.     {
  5731.     // clone the bob
  5732.     Clone_BOBX(&rocks[0], &rocks[index]);
  5733.  
  5734.     } // end for index
  5735.  
  5736.  
  5737. // LOAD THE POOS ////////////////////////////////////////////////
  5738.  
  5739. // create master poo bob
  5740. Create_BOB(&poos[0],0,0,32,32,11,
  5741.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM,
  5742.            DDSCAPS_SYSTEMMEMORY);
  5743.  
  5744. // set state to dead
  5745. poos[0].state = POO_STATE_DEAD;
  5746.  
  5747. // set animation speed
  5748. Set_Anim_Speed_BOB(&poos[0],6);
  5749.  
  5750. // load animations in
  5751. Load_Animation_BOB(&poos[0],POO_ANIM_BOUNCE_LEFT, 2,poo_anims[0]);
  5752. Load_Animation_BOB(&poos[0],POO_ANIM_BOUNCE_RIGHT,2,poo_anims[1]);
  5753. Load_Animation_BOB(&poos[0],POO_ANIM_CRUSH_LEFT,  2,poo_anims[2]);
  5754. Load_Animation_BOB(&poos[0],POO_ANIM_CRUSH_RIGHT, 2,poo_anims[3]);
  5755. Load_Animation_BOB(&poos[0],POO_ANIM_BURROW, 4,poo_anims[4]);
  5756.  
  5757. // set current animation
  5758. Set_Animation_BOB2(&poos[0], POO_ANIM_BOUNCE_LEFT);
  5759.  
  5760. // load frames in
  5761. for (index=0; index < 11; index++)
  5762.      Load_Frame_BOB(&poos[0],&bitmap8bit,index,index,1,BITMAP_EXTRACT_MODE_CELL);  
  5763.  
  5764. // now clone bob
  5765. for (index=1; index < NUM_POOS; index++)
  5766.     {
  5767.     // clone the bob
  5768.     Clone_BOBX(&poos[0], &poos[index]);
  5769.  
  5770.     // load animations in
  5771.     Load_Animation_BOB(&poos[index],POO_ANIM_BOUNCE_LEFT, 2,poo_anims[0]);
  5772.     Load_Animation_BOB(&poos[index],POO_ANIM_BOUNCE_RIGHT,2,poo_anims[1]);
  5773.     Load_Animation_BOB(&poos[index],POO_ANIM_CRUSH_LEFT,  2,poo_anims[2]);
  5774.     Load_Animation_BOB(&poos[index],POO_ANIM_CRUSH_RIGHT, 2,poo_anims[3]);
  5775.     Load_Animation_BOB(&poos[index],POO_ANIM_BURROW, 4,poo_anims[4]);
  5776.  
  5777.     // set current animation
  5778.     Set_Animation_BOB2(&poos[index], POO_ANIM_BOUNCE_LEFT);
  5779.  
  5780.     } // end for index
  5781.  
  5782.  
  5783. // make demo clone
  5784. Clone_BOBX(&poos[0], &poo_demo);
  5785.  
  5786. // LOAD THE PUFFS ////////////////////////////////////////////////
  5787.  
  5788. // create master puff bob
  5789. Create_BOB(&puffs[0],0,0,32,32,13,
  5790.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM,
  5791.            DDSCAPS_SYSTEMMEMORY);
  5792.  
  5793. // set state to dead
  5794. puffs[0].state = PUFF_STATE_DEAD;
  5795.  
  5796. // set animation speed
  5797. Set_Anim_Speed_BOB(&puffs[0],4);
  5798.  
  5799. // load animations in
  5800. Load_Animation_BOB(&puffs[0],PUFF_ANIM_BOUNCE_LEFT, 4,puff_anims[0]);
  5801. Load_Animation_BOB(&puffs[0],PUFF_ANIM_BOUNCE_RIGHT,4,puff_anims[1]);
  5802. Load_Animation_BOB(&puffs[0],PUFF_ANIM_CRUSH_LEFT,  2,puff_anims[2]);
  5803. Load_Animation_BOB(&puffs[0],PUFF_ANIM_CRUSH_RIGHT, 2,puff_anims[3]);
  5804. Load_Animation_BOB(&puffs[0],PUFF_ANIM_BURROW, 4,puff_anims[4]);
  5805.  
  5806. // set current animation
  5807. Set_Animation_BOB2(&puffs[0], PUFF_ANIM_BOUNCE_LEFT);
  5808.  
  5809. // load frames in
  5810. for (index=0; index < 13; index++)
  5811.      Load_Frame_BOB(&puffs[0],&bitmap8bit,index,index,0,BITMAP_EXTRACT_MODE_CELL);  
  5812.  
  5813. // now clone bob
  5814. for (index=1; index < NUM_PUFFS; index++)
  5815.     {
  5816.     // clone the bob
  5817.     Clone_BOBX(&puffs[0], &puffs[index]);
  5818.  
  5819.     // load animations in
  5820.     Load_Animation_BOB(&puffs[index],PUFF_ANIM_BOUNCE_LEFT, 4,puff_anims[0]);
  5821.     Load_Animation_BOB(&puffs[index],PUFF_ANIM_BOUNCE_RIGHT,4,puff_anims[1]);
  5822.     Load_Animation_BOB(&puffs[index],PUFF_ANIM_CRUSH_LEFT,  2,puff_anims[2]);
  5823.     Load_Animation_BOB(&puffs[index],PUFF_ANIM_CRUSH_RIGHT, 2,puff_anims[3]);
  5824.     Load_Animation_BOB(&puffs[index],PUFF_ANIM_BURROW, 4,puff_anims[4]);
  5825.  
  5826.     // set current animation
  5827.     Set_Animation_BOB2(&puffs[index], PUFF_ANIM_BOUNCE_LEFT);
  5828.  
  5829.     } // end for index
  5830.  
  5831. // make demo clone
  5832. Clone_BOBX(&puffs[0], &puff_demo);
  5833.  
  5834. // LOAD SCORE BITMAPS ///////////////////////////////////////////
  5835.  
  5836. // create master score
  5837. Create_BOB(&scores[0],0,0,32,32,19,
  5838.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  5839.            DDSCAPS_SYSTEMMEMORY);
  5840.  
  5841. //set state to off
  5842. scores[0].state = SCORE_OFF;
  5843.  
  5844. // load frames in
  5845. for (index=0; index < 19; index++)
  5846.      Load_Frame_BOB(&scores[0],&bitmap8bit,index,index,11,BITMAP_EXTRACT_MODE_CELL);  
  5847.  
  5848. // now clone bob
  5849. for (index=1; index < NUM_SCORES; index++)
  5850.     {
  5851.     // clone the bob
  5852.     Clone_BOBX(&scores[0], &scores[index]);
  5853.  
  5854.     } // end for index
  5855.  
  5856. // unload master bitmap file
  5857. Unload_Bitmap_File(&bitmap8bit);
  5858.  
  5859. // LOAD WEAPONS  /////////////////////////////////////////////
  5860.  
  5861. // load object bitmap
  5862. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDOBJ.BMP");
  5863.  
  5864. // fireballs
  5865.  
  5866. // create master fireball
  5867. Create_BOB(&fballs[0],0,0,16,16,16,
  5868.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM ,
  5869.            DDSCAPS_SYSTEMMEMORY);
  5870.  
  5871. // set state of gpump
  5872. fballs[0].state = FBALL_STATE_DEAD;
  5873.  
  5874. // load the animations in
  5875. Load_Animation_BOB(&fballs[0],FBALL_ANIM_RED_FLY,      5,fball_anims[0]);
  5876. Load_Animation_BOB(&fballs[0],FBALL_ANIM_RED_EXPLODE,  3,fball_anims[1]);
  5877. Load_Animation_BOB(&fballs[0],FBALL_ANIM_GREEN_FLY,    5,fball_anims[2]);
  5878. Load_Animation_BOB(&fballs[0],FBALL_ANIM_GREEN_EXPLODE,3,fball_anims[3]);
  5879.  
  5880. // set animation speed
  5881. Set_Anim_Speed_BOB(&fballs[0],4);
  5882.  
  5883. // load frames in
  5884. for (index=0; index < 16; index++)
  5885.      Load_Frame_BOB(&fballs[0],&bitmap8bit,index,index%8,index/8,BITMAP_EXTRACT_MODE_CELL);  
  5886.  
  5887. // now clone bob
  5888. for (index=1; index < NUM_FBALLS; index++)
  5889.     {
  5890.     // clone the bob
  5891.     Clone_BOBX(&fballs[0], &fballs[index]);
  5892.  
  5893.     // load the animation in
  5894.     // cloning doesn't clone animation, sorry!
  5895.     Load_Animation_BOB(&fballs[index],FBALL_ANIM_RED_FLY,      5,fball_anims[0]);
  5896.     Load_Animation_BOB(&fballs[index],FBALL_ANIM_RED_EXPLODE,  3,fball_anims[1]);
  5897.     Load_Animation_BOB(&fballs[index],FBALL_ANIM_GREEN_FLY,    5,fball_anims[2]);
  5898.     Load_Animation_BOB(&fballs[index],FBALL_ANIM_GREEN_EXPLODE,3,fball_anims[3]);
  5899.  
  5900.     } // end for index
  5901.  
  5902. // create fireball holes
  5903. for (index=0; index < NUM_FBLASTS; index++)
  5904.     {
  5905.     // create the hole bitmap
  5906.     Create_Bitmap(&fblasts[index],0,0,16,16);
  5907.  
  5908.     // scan it out
  5909.     Load_Image_Bitmap(&fblasts[index],&bitmap8bit,8+index,0,BITMAP_EXTRACT_MODE_CELL);
  5910.  
  5911.     } // end for index
  5912.  
  5913. // pumps
  5914. // create master pump
  5915. Create_BOB(&gpumps[0],0,0,16,16,12,
  5916.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM ,
  5917.            DDSCAPS_SYSTEMMEMORY);
  5918.  
  5919. // set state of gpump
  5920. gpumps[0].state = GPUMP_STATE_DEAD;
  5921.  
  5922. // load the animations in
  5923. Load_Animation_BOB(&gpumps[0],0,4,gpump_anims[0]);
  5924. Load_Animation_BOB(&gpumps[0],1,4,gpump_anims[1]);
  5925. Load_Animation_BOB(&gpumps[0],2,4,gpump_anims[2]);
  5926. Load_Animation_BOB(&gpumps[0],3,4,gpump_anims[3]);
  5927.  
  5928. // set animation speed
  5929. Set_Anim_Speed_BOB(&gpumps[0],4);
  5930.  
  5931. // load frames in
  5932. for (index=0; index < 12; index++)
  5933.      Load_Frame_BOB(&gpumps[0],&bitmap8bit,index,index,2,BITMAP_EXTRACT_MODE_CELL);  
  5934.  
  5935. // now clone bob
  5936. for (index=1; index < NUM_GPUMPS; index++)
  5937.     {
  5938.     // clone the bob
  5939.     Clone_BOBX(&gpumps[0], &gpumps[index]);
  5940.  
  5941.     // load the animation in
  5942.     // cloning doesn't clone animation, sorry!
  5943.     Load_Animation_BOB(&gpumps[index],0,3,gpump_anims[0]);
  5944.     Load_Animation_BOB(&gpumps[index],1,3,gpump_anims[1]);
  5945.     Load_Animation_BOB(&gpumps[index],2,3,gpump_anims[2]);
  5946.     Load_Animation_BOB(&gpumps[index],3,3,gpump_anims[3]);
  5947.  
  5948.     } // end for index
  5949.  
  5950. // create small dug bob
  5951. Create_BOB(&small_dug,0,0,16,16,1,
  5952.            BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME,
  5953.            DDSCAPS_SYSTEMMEMORY);
  5954.  
  5955. // load in small dug
  5956. Load_Frame_BOB(&small_dug,&bitmap8bit,0,0,3,BITMAP_EXTRACT_MODE_CELL);  
  5957.  
  5958. // unload object bitmap
  5959. Unload_Bitmap_File(&bitmap8bit);
  5960.  
  5961.  
  5962. // L O A D  P U F F Y  V E R S I O N S ////////////////////////
  5963.  
  5964. // load object bitmap
  5965. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDBLOW8.BMP");
  5966.  
  5967. // create master fireball
  5968. Create_BOB(&puffy,0,0,56,56,16,
  5969.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME ,
  5970.            DDSCAPS_SYSTEMMEMORY);
  5971.  
  5972. // load frames in
  5973. for (index=0; index < 16; index++)
  5974.      Load_Frame_BOB(&puffy,&bitmap8bit,index,index%4,index/4,BITMAP_EXTRACT_MODE_CELL);  
  5975.  
  5976. // create andre image
  5977. Create_Bitmap(&andre,320-32,260,56,56);
  5978. Load_Image_Bitmap(&andre,&bitmap8bit,0,4,BITMAP_EXTRACT_MODE_CELL);
  5979.  
  5980. // unload object bitmap
  5981. Unload_Bitmap_File(&bitmap8bit);
  5982.  
  5983. // LOAD PRIZES  /////////////////////////////////////////////
  5984.  
  5985. // load prize bitmap
  5986. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDCASH.BMP");
  5987.  
  5988. for (index=0; index < NUM_PRIZES; index++)
  5989.     {
  5990.     // create and load all the prizes
  5991.     Create_BOB(&prizes[index],280,232,32,32,8,
  5992.                BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  5993.                DDSCAPS_SYSTEMMEMORY);
  5994.  
  5995.     // set animation speed
  5996.     Set_Anim_Speed_BOB(&prizes[index],3);
  5997.  
  5998.     // set prize value in varsI[1]
  5999.     prizes[index].varsI[1] = (index+1)*1000;
  6000.    
  6001.     // load in prize frame
  6002.     for (int frame=0; frame < 8; frame++)
  6003.          Load_Frame_BOB(&prizes[index],&bitmap8bit,frame,frame,index,BITMAP_EXTRACT_MODE_CELL);  
  6004.  
  6005.     } // end for index
  6006.  
  6007. // unload object bitmap
  6008. Unload_Bitmap_File(&bitmap8bit);
  6009.  
  6010. // LOAD MENU bitmaps /////////////////////////////////////////
  6011.  
  6012. // create background image
  6013. Create_Bitmap(&menu_bmp,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
  6014.  
  6015. // load image
  6016. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDMENU8.BMP");
  6017.  
  6018. // scan image into bitmap
  6019. Load_Image_Bitmap(&menu_bmp,&bitmap8bit,0,0,BITMAP_EXTRACT_MODE_ABS);
  6020.  
  6021. // unload object bitmap
  6022. Unload_Bitmap_File(&bitmap8bit);
  6023.  
  6024.  
  6025. // LOAD TORCHES /////////////////////////////////////////////
  6026.  
  6027. // load image
  6028. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDFIRE8.BMP");
  6029.  
  6030. // create mushroom bob
  6031. Create_BOB(&torch,0,0,88,88,6,
  6032.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  6033.            DDSCAPS_SYSTEMMEMORY);
  6034.  
  6035. // set animation speed
  6036. Set_Anim_Speed_BOB(&torch,3);
  6037.  
  6038. // load frames for torch
  6039. for (index=0; index < 6; index++)
  6040.      Load_Frame_BOB(&torch,&bitmap8bit,index,index,0,BITMAP_EXTRACT_MODE_CELL);  
  6041.  
  6042. // unload object bitmap
  6043. Unload_Bitmap_File(&bitmap8bit);
  6044.  
  6045.  
  6046. // LOAD FONT ////////////////////////////////////////////////
  6047.  
  6048. // load image
  6049. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDFONT8.BMP");
  6050.  
  6051. // create font bitmaps
  6052. for (index=0; index < FONT_NUM_CHARS; index++)
  6053.     {
  6054.     // create the font bitmap
  6055.     Create_Bitmap(&font[index],0,0,16,16);
  6056.  
  6057.     // scan it out
  6058.     Load_Image_Bitmap(&font[index],&bitmap8bit,index%16,index/16,BITMAP_EXTRACT_MODE_CELL);
  6059.  
  6060.     } // end for index
  6061.  
  6062. // unload object bitmap
  6063. Unload_Bitmap_File(&bitmap8bit);
  6064.  
  6065.  
  6066.  
  6067.  
  6068.  
  6069.  
  6070.  
  6071.  
  6072. ///////////////////////////////////////////////////////////////
  6073.  
  6074. // set clipping rectangle to screen extents so objects dont
  6075. // mess up at edges
  6076. RECT screen_rect = {0,0,screen_width,screen_height};
  6077. lpddclipper = DD_Attach_Clipper(lpddsback,1,&screen_rect);
  6078.  
  6079. // seed random number generate
  6080. srand(Start_Clock());
  6081.  
  6082. // load all the levels in
  6083. if (!Load_Levels("UNDLEV.DAT"))
  6084.     {
  6085.     // file is jacked up
  6086.     MessageBox(main_window_handle, 
  6087.               "Level File 'UNDLEV.DAT' -- Data Invalid or Corrupt.", 
  6088.               "DigDumb Startup Error",
  6089.               MB_ICONERROR);
  6090.  
  6091.     // get out of here
  6092.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  6093.     return(0);
  6094.   
  6095.     } // end if
  6096.  
  6097. // hide the mouse
  6098. ShowCursor(FALSE);
  6099.  
  6100. // return success
  6101. return(1);
  6102.  
  6103. } // end Game_Init
  6104.  
  6105. ///////////////////////////////////////////////////////////
  6106.  
  6107. int Game_Reset(void)
  6108. {
  6109. // this function resets all the system variables in preparation to run a level
  6110.  
  6111. int index; // looping counter
  6112.  
  6113. // reset number of levels
  6114. num_creatures_on_level = 0;
  6115.  
  6116. // reset end level counter
  6117. end_level_counter = 0; 
  6118.  
  6119. // reset radiation level
  6120. radiation_message_played = 0;
  6121.  
  6122. // reset dug
  6123. dug.varsI[DUG_INDEX_DAMAGE]    = 0;
  6124. dug.varsI[DUG_INDEX_PUMP_PSI]  = 100;
  6125. dug.varsI[DUG_INDEX_KILLS]     = 0;
  6126. dug.varsI[DUG_INDEX_ANIM_MODE] = DUG_ANIM_WALK;
  6127.  
  6128. // set state to alive
  6129. dug.state = DUG_STATE_ALIVE;
  6130.  
  6131. // set direction to left
  6132. dug.varsI[DUG_INDEX_DIR] = DIR_LEFT;
  6133.  
  6134. // set initial animation sequence
  6135. Set_Animation_BOB2(&dug, DUG_ANIM_WALK + dug.varsI[DUG_INDEX_DIR]*3);
  6136.  
  6137. // set position
  6138. Set_Pos_BOB(&dug,320,32);
  6139.  
  6140. // set animation speed
  6141. Set_Anim_Speed_BOB(&dug,3);
  6142.  
  6143.  
  6144. // reset poos
  6145. for (index=0; index < NUM_POOS; index++)
  6146.     {
  6147.     poos[index].state = POO_STATE_DEAD;
  6148.     } // end for index
  6149.  
  6150. // reset puffs
  6151. for (index=0; index < NUM_PUFFS; index++)
  6152.     {
  6153.     puffs[index].state = PUFF_STATE_DEAD;
  6154.     } // end for index
  6155.  
  6156. // reset scores
  6157. for (index=0; index < NUM_SCORES; index++)
  6158.     {
  6159.     // test if this score is usuable
  6160.     scores[index].state = SCORE_OFF;
  6161.     } // end for index
  6162.  
  6163. // reset gpumps
  6164. for (index=0; index < NUM_GPUMPS; index++)
  6165.     {
  6166.     // test if this pump is usuable
  6167.     gpumps[index].state = GPUMP_STATE_DEAD;
  6168.     } // end for index
  6169.  
  6170. // reset gpumps
  6171. for (index=0; index < NUM_ROCKS; index++)
  6172.     {
  6173.     // is this rock dead?
  6174.     rocks[index].state = ROCK_STATE_DEAD;
  6175.     } // end if
  6176.  
  6177. // reset fire balls
  6178. for (index=0; index < NUM_FBALLS; index++)
  6179.     {
  6180.     // test if this fire ball is usuable
  6181.     fballs[index].state=FBALL_STATE_DEAD;
  6182.     } // end if
  6183.  
  6184. // reset the prize
  6185. prizes[0].state = PRIZE_STATE_OFF; 
  6186.  
  6187. // return
  6188. return(1);
  6189.  
  6190. } // end Game_Reset
  6191.  
  6192.  
  6193. ///////////////////////////////////////////////////////////
  6194.  
  6195. int Game_Shutdown(void *parms)
  6196. {
  6197. // this function is where you shutdown your game and
  6198. // release all resources that you allocated
  6199.  
  6200. int index; // looping variable
  6201.  
  6202. // kill individual bobs
  6203. Destroy_BOBX(&dug);
  6204. Destroy_BOBX(&small_dug);
  6205. Destroy_BOBX(&puffy);
  6206. Destroy_BOBX(&mushroom);
  6207. Destroy_BOBX(&torch);
  6208.  
  6209. Destroy_BOBX(&dug_demo);
  6210. Destroy_BOBX(&poo_demo);
  6211. Destroy_BOBX(&puff_demo);
  6212.  
  6213. // kill rocks
  6214. for (index=0; index<NUM_ROCKS; index++)
  6215.     Destroy_BOBX(&rocks[index]);
  6216.  
  6217. // kill puffs
  6218. for (index=0; index < NUM_PUFFS; index++)
  6219.     Destroy_BOBX(&puffs[index]);
  6220.  
  6221. // kill poos
  6222. for (index=0; index < NUM_POOS; index++)
  6223.     Destroy_BOBX(&poos[index]);
  6224.  
  6225. // kill prizes
  6226. for (index=0; index<NUM_PRIZES; index++)
  6227.     Destroy_BOBX(&prizes[index]);
  6228.  
  6229. // kill weapons
  6230. for (index=0; index<NUM_GPUMPS; index++)
  6231.     Destroy_BOBX(&gpumps[index]);
  6232.  
  6233. for (index=0; index<NUM_FBALLS; index++)
  6234.     Destroy_BOBX(&fballs[index]);
  6235.  
  6236. // kill holes
  6237. for (index=0; index<NUM_HOLE_BITMAPS; index++)
  6238.     Destroy_Bitmap(&dug_holes[index]);
  6239.  
  6240. // kill font
  6241. for (index=0; index<FONT_NUM_CHARS; index++)
  6242.     Destroy_Bitmap(&font[index]);
  6243.  
  6244. // kill scores
  6245. for (index=0; index<NUM_SCORES; index++)
  6246.     Destroy_BOBX(&scores[index]);
  6247.  
  6248. // kill all bitmaps
  6249. Destroy_Bitmap(&background_bmp);
  6250. Destroy_Bitmap(&menu_bmp);
  6251. Destroy_Bitmap(&andre);
  6252.  
  6253. // shutdown directdraw
  6254. DD_Shutdown();
  6255.  
  6256. // unload sounds
  6257. Delete_All_Sounds();
  6258.  
  6259. // shutdown directsound
  6260. DSound_Shutdown();
  6261.  
  6262. // release all input devices
  6263. DI_Release_Keyboard();
  6264. DI_Release_Joystick();
  6265. DI_Release_Mouse();
  6266.  
  6267. // close the error file
  6268. Close_Error_File();
  6269.  
  6270. // hide the mouse
  6271. ShowCursor(TRUE);
  6272.  
  6273. // return success
  6274. return(1);
  6275. } // end Game_Shutdown
  6276.  
  6277. ///////////////////////////////////////////////////////////
  6278.  
  6279. int Game_Main(void *parms)
  6280. {
  6281. // this is the workhorse of your game it will be called
  6282. // continuously in real-time this is like main() in C
  6283. // all the calls for you game go here!
  6284.  
  6285. static int fire_deb  = 0,  // used to debounce fire key
  6286.            fireb_deb = 0,  // debounceces joystick fire buttons
  6287.            esc_deb   = 0,  // debounce esc key
  6288.            pause_deb = 0;  // debounce pause key
  6289.            
  6290.  
  6291. static int rock_push  = 0, // tracks if rock is being pushed
  6292.            demo_reset = 0, // used to create demo mode
  6293.            pump_valve = 0, // used to control psi pressure rate
  6294.            heal_count = 0;  // used in healing
  6295.  
  6296. int dug_dx = 0,          // used in collision algorithm
  6297.     dug_dy = 0;
  6298.  
  6299. // what state is game in?
  6300. if (game_state == GAME_STATE_INIT)
  6301. {
  6302. // reset everything
  6303. Game_Reset();
  6304.  
  6305. // start first level
  6306. Start_Level(STARTING_LEVEL_NUMBER);
  6307.  
  6308. // reset number of lives
  6309. dug.varsI[DUG_INDEX_LIVES] = 3;
  6310. dug.varsI[DUG_INDEX_LEVEL] = 0;
  6311. dug.varsI[DUG_INDEX_SCORE] = 0;
  6312.  
  6313. // reset new man tracker
  6314. new_man_tracker = POINTS_NEW_MAN;
  6315.  
  6316. // transition to running
  6317. game_state = GAME_STATE_MENU;
  6318.  
  6319. } // end if
  6320. else
  6321. if (game_state == GAME_STATE_MENU)
  6322. {
  6323. // user is entering menu mode
  6324.  
  6325. // test for demo reset
  6326. if (demo_reset == 0)
  6327.    {
  6328.    // reset all the demo objects
  6329.  
  6330.    // dug
  6331.  
  6332.    // set initial animation sequence
  6333.    Set_Animation_BOB2(&dug_demo, DUG_ANIM_WALK + DIR_RIGHT*3);
  6334.  
  6335.    // set position
  6336.    Set_Pos_BOB(&dug_demo,DUG_DEMO_X,DUG_DEMO_Y);
  6337.  
  6338.    // set animation speed
  6339.    Set_Anim_Speed_BOB(&dug_demo,4);
  6340.  
  6341.    // poo
  6342.  
  6343.    // set initial animation sequence
  6344.    Set_Animation_BOB2(&poo_demo, POO_ANIM_BOUNCE_RIGHT);
  6345.  
  6346.    // set position
  6347.    Set_Pos_BOB(&poo_demo,POO_DEMO_X,POO_DEMO_Y);
  6348.  
  6349.    // set animation speed
  6350.    Set_Anim_Speed_BOB(&poo_demo,4);
  6351.  
  6352.    // puff
  6353.  
  6354.    // set initial animation sequence
  6355.    Set_Animation_BOB2(&puff_demo, PUFF_ANIM_BOUNCE_RIGHT);
  6356.  
  6357.    // set position
  6358.    Set_Pos_BOB(&puff_demo,PUFF_DEMO_X,PUFF_DEMO_Y);
  6359.  
  6360.    // set animation speed
  6361.    Set_Anim_Speed_BOB(&puff_demo,4);
  6362.  
  6363.    // reset demo
  6364.    demo_reset = 1;
  6365.  
  6366.    // start music
  6367.    Play_Sound(intro_music_id, DSBPLAY_LOOPING);
  6368.  
  6369.    } // end if
  6370.  
  6371.     // display menu
  6372.  
  6373.     // start the timing clock
  6374.     Start_Clock();
  6375.  
  6376.     // clear the drawing surface
  6377.     DD_Lock_Back_Surface();
  6378.     Draw_Bitmap2(&menu_bmp, back_buffer, back_lpitch,0);
  6379.     DD_Unlock_Back_Surface();
  6380.  
  6381.     // read all input devices
  6382.     DI_Read_Keyboard();
  6383.     DI_Read_Mouse();
  6384.     DI_Read_Joystick();
  6385.  
  6386.     // draw all objects
  6387.  
  6388.     // animate the torch
  6389.     Animate_BOB2(&torch);
  6390.  
  6391.     // animate poo
  6392.     Animate_BOB2(&poo_demo);
  6393.  
  6394.     // animate puff
  6395.     Animate_BOB2(&puff_demo);
  6396.  
  6397.     // animate dug
  6398.     Animate_BOB2(&dug_demo);
  6399.    
  6400.     // draw the 2 torches
  6401.     torch.x = 24;
  6402.     torch.y = 60;
  6403.     Draw_BOB(&torch, lpddsback);
  6404.  
  6405.     torch.x = 524;
  6406.     torch.y = 60;
  6407.     Draw_BOB(&torch, lpddsback);
  6408.  
  6409.     // draw puff
  6410.     Draw_BOB(&puff_demo,lpddsback);
  6411.  
  6412.     // draw poo
  6413.     Draw_BOB(&poo_demo,lpddsback);
  6414.  
  6415.     // draw dug
  6416.     Draw_BOB(&dug_demo,lpddsback);
  6417.  
  6418.     // display the next frame
  6419.     DD_Flip();
  6420.  
  6421.     // sync to 30ish fps
  6422.     Wait_Clock(30);
  6423.  
  6424.    // check of user is trying to exit
  6425.     if (!esc_deb && keyboard_state[DIK_ESCAPE])
  6426.        {
  6427.        // out of here
  6428.        game_state = GAME_STATE_EXIT;
  6429.  
  6430.        // set debounce
  6431.        esc_deb = 1;
  6432.  
  6433.        Stop_Sound(intro_music_id);
  6434.  
  6435.        } // end if
  6436.    else
  6437.    if (!keyboard_state[DIK_ESCAPE])
  6438.        esc_deb = 0;
  6439.  
  6440.     // test for restart
  6441.     if (keyboard_state[DIK_RETURN])
  6442.        {
  6443.        // transition to running
  6444.  
  6445.        // reset all the vars
  6446.        Game_Reset();
  6447.  
  6448.        Stop_Sound(intro_music_id);
  6449.  
  6450.        // start first level
  6451.        Start_Level(STARTING_LEVEL_NUMBER);
  6452.        dug.varsI[DUG_INDEX_LEVEL] = 0;
  6453.  
  6454.        // reset lives
  6455.        dug.varsI[DUG_INDEX_LIVES] = 3;
  6456.  
  6457.        // reset score
  6458.        dug.varsI[DUG_INDEX_SCORE]     = 0;
  6459.  
  6460.        // reset new man tracker
  6461.        new_man_tracker = POINTS_NEW_MAN;
  6462.  
  6463.       ///////////////////
  6464.       // reset counter for rebirth
  6465.       dug.counter_1 = 0;
  6466.  
  6467.       // reset state
  6468.       dug.state=DUG_STATE_REBIRTH;
  6469.  
  6470.       // reset vars
  6471.       dug.varsI[DUG_INDEX_ANIM_MODE] = DUG_ANIM_WALK;
  6472.  
  6473.       // set direction to left
  6474.       dug.varsI[DUG_INDEX_DIR] = DIR_LEFT;
  6475.  
  6476.       // set initial animation sequence
  6477.       Set_Animation_BOB2(&dug,DUG_ANIM_REBIRTH);
  6478. ///////////////
  6479.       
  6480.        // transition to running state
  6481.        game_state = GAME_STATE_RUNNING;       
  6482.  
  6483.        Save_Palette(save_palette);
  6484.        Screen_Transitions(SCREEN_REDNESS, primary_buffer, primary_lpitch);
  6485.        Set_Palette(save_palette);
  6486.  
  6487.        // play rebirth/trans sound
  6488.        Play_Sound(dug_trans_snd_id);
  6489.        
  6490.        } // end if
  6491.  
  6492.     // test for resume
  6493.     if (keyboard_state[DIK_SPACE])
  6494.        {
  6495.        // transition back to running state
  6496.        game_state = GAME_STATE_RUNNING;    
  6497.  
  6498.        Stop_Sound(intro_music_id);
  6499.  
  6500.        } // end if
  6501.  
  6502. } // end if
  6503. else
  6504. if (game_state == GAME_STATE_NEXT_LEVEL)
  6505. {
  6506. // move to next level
  6507. if (++curr_level >= num_levels)
  6508.     {
  6509.     // set state to game won
  6510.     game_state = GAME_STATE_WIN;
  6511.  
  6512.     } // end if
  6513. else
  6514.     {
  6515.  
  6516.     // reset all the vars
  6517.     Game_Reset();
  6518.  
  6519.     // load the next level
  6520.     Start_Level(curr_level);
  6521.  
  6522.     // wait a sec
  6523.     Sleep(1000);
  6524.     
  6525.     // play the next level sound
  6526.     Play_Sound(level_snd_id);
  6527.  
  6528.     //DD_Lock_Primary_Surface();
  6529.     Save_Palette(save_palette);
  6530.     Screen_Transitions(SCREEN_WHITENESS, primary_buffer, primary_lpitch);
  6531.     Set_Palette(save_palette);
  6532.     //DD_Unlock_Primary_Surface();
  6533.  
  6534.     // transition to running state
  6535.     game_state = GAME_STATE_RUNNING;
  6536.  
  6537.     } // end if didn't win
  6538.  
  6539. } // end if
  6540. else
  6541. if (game_state == GAME_STATE_RUNNING)
  6542. {
  6543. // reset all vars
  6544. demo_reset = 0;
  6545.  
  6546. // start the timing clock
  6547. Start_Clock();
  6548.  
  6549. // clear the drawing surface
  6550. // DD_Fill_Surface(lpddsback, 0);
  6551. DD_Lock_Back_Surface();
  6552. Draw_Bitmap2(&background_bmp, back_buffer, back_lpitch,0);
  6553. DD_Unlock_Back_Surface();
  6554.  
  6555. // read all input devices
  6556. DI_Read_Keyboard();
  6557. DI_Read_Mouse();
  6558. DI_Read_Joystick();
  6559.  
  6560.  
  6561. // what state is dug in
  6562. if (dug.state==DUG_STATE_ALIVE)
  6563. {
  6564.  
  6565. // test desired direction, and artificially set motions based on valid intervals
  6566. if ((joy_state.lY || keyboard_state[DIK_UP] || keyboard_state[DIK_DOWN]) && ((int)dug.x % DUG_X_INTERVAL))
  6567.    {
  6568.    // dug is trying to make an upward or downward turn, but isn't at a
  6569.    // valid turning interval
  6570.    if (dug.varsI[DUG_INDEX_DIR] == DIR_RIGHT)
  6571.       keyboard_state[DIK_RIGHT] |= 1;
  6572.    else
  6573.    if (dug.varsI[DUG_INDEX_DIR] == DIR_LEFT)
  6574.       keyboard_state[DIK_LEFT] |= 1;
  6575.  
  6576.    } // end if
  6577.  
  6578. // test desired direction, and artificially set motions based on valid intervals
  6579. if ((joy_state.lX || keyboard_state[DIK_RIGHT] || keyboard_state[DIK_LEFT]) && (((int)dug.y+8) % DUG_Y_INTERVAL))
  6580.    {
  6581.    // dug is trying to make an upward or downward turn, but isn't at a
  6582.    // valid turning interval
  6583.    if (dug.varsI[DUG_INDEX_DIR] == DIR_UP)
  6584.       keyboard_state[DIK_UP] |= 1;
  6585.    else
  6586.    if (dug.varsI[DUG_INDEX_DIR] == DIR_DOWN)
  6587.       keyboard_state[DIK_DOWN] |= 1;
  6588.  
  6589.    } // end if
  6590.  
  6591. // process final motion
  6592. if ( (keyboard_state[DIK_LEFT]  || joy_state.lX < 0)&& !(((int)dug.y+8) % DUG_Y_INTERVAL))
  6593.    {
  6594.    // first test if there is any rock ahead
  6595.    Dug_Dig_Test(dug.x-1,dug.y+16);
  6596.  
  6597.    // test what the current direction is
  6598.    if (dug.varsI[DUG_INDEX_DIR]!=DIR_LEFT)
  6599.       {
  6600.       // set direction to left
  6601.       dug.varsI[DUG_INDEX_DIR] = DIR_LEFT;
  6602.  
  6603.       // set animation sequence to left
  6604.       Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  6605.  
  6606.       } // end if
  6607.  
  6608.    // animate dug
  6609.    Animate_BOB(&dug);
  6610.  
  6611.    // dig hole
  6612.    Dig_Hole();
  6613.  
  6614.    // move dug
  6615.    dug.x-=DUG_SPEED; 
  6616.  
  6617.    dug_dx = -DUG_SPEED;
  6618.    dug_dy = 0;
  6619.  
  6620.    } // end if
  6621. else
  6622. if ((keyboard_state[DIK_RIGHT]  || joy_state.lX > 0) && !(((int)dug.y+8) % DUG_Y_INTERVAL))
  6623.    {
  6624.    // first test if there is any rock ahead
  6625.    Dug_Dig_Test(dug.x+32,dug.y+16);
  6626.  
  6627.    // test what the current direction is
  6628.    if (dug.varsI[DUG_INDEX_DIR]!=DIR_RIGHT)
  6629.       {
  6630.       // set direction to left
  6631.       dug.varsI[DUG_INDEX_DIR] = DIR_RIGHT;
  6632.  
  6633.       // set animation sequence to right
  6634.       Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  6635.  
  6636.       } // end if
  6637.  
  6638.    // animate dug
  6639.    Animate_BOB(&dug);
  6640.  
  6641.    // dig hole
  6642.    Dig_Hole();
  6643.  
  6644.    // move dug
  6645.    dug.x+=DUG_SPEED; 
  6646.  
  6647.    dug_dx = DUG_SPEED;
  6648.    dug_dy = 0;
  6649.  
  6650.  
  6651.    } // end if
  6652. else
  6653. if ((keyboard_state[DIK_UP] || joy_state.lY < 0)&& !((int)dug.x % DUG_X_INTERVAL))
  6654.    {
  6655.    // first test if there is any rock ahead
  6656.    Dug_Dig_Test(dug.x+16,dug.y-1);
  6657.  
  6658.    // test what the current direction is
  6659.    if (dug.varsI[DUG_INDEX_DIR]!=DIR_UP)
  6660.       {
  6661.       // set direction to left
  6662.       dug.varsI[DUG_INDEX_DIR] = DIR_UP;
  6663.  
  6664.       // set animation sequence to left
  6665.       Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  6666.  
  6667.       } // end if
  6668.  
  6669.    // animate dug
  6670.    Animate_BOB(&dug);
  6671.  
  6672.    // dig hole
  6673.    Dig_Hole();
  6674.  
  6675.    // move dug
  6676.    dug.y-=DUG_SPEED; 
  6677.  
  6678.    dug_dy = -DUG_SPEED;
  6679.    dug_dx = 0;
  6680.  
  6681.    } // end if
  6682. else
  6683. if ((keyboard_state[DIK_DOWN] || joy_state.lY > 0) && !((int)dug.x % DUG_X_INTERVAL))
  6684.    {
  6685.    // first test if there is any rock ahead
  6686.    Dug_Dig_Test(dug.x+16,dug.y+32);
  6687.  
  6688.    // test what the current direction is
  6689.    if (dug.varsI[DUG_INDEX_DIR]!=DIR_DOWN)
  6690.       {
  6691.       // set direction to left
  6692.       dug.varsI[DUG_INDEX_DIR] = DIR_DOWN;
  6693.  
  6694.       // set animation sequence to left
  6695.       Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  6696.  
  6697.       } // end if
  6698.  
  6699.    // animate dug
  6700.    Animate_BOB(&dug);
  6701.  
  6702.    // dig hole
  6703.    Dig_Hole();
  6704.  
  6705.    // move dug
  6706.    dug.y+=DUG_SPEED; 
  6707.  
  6708.    dug_dy = DUG_SPEED;
  6709.    dug_dx = 0;
  6710.  
  6711.    } // end if
  6712.  
  6713. // check for collisions with rock
  6714. if (dug_dx || dug_dy)
  6715.    {
  6716.    // scan thru rock list
  6717.    for (int rindex=0; rindex < NUM_ROCKS; rindex++)
  6718.        {
  6719.        // test for collision
  6720.        if (rocks[rindex].state!=ROCK_STATE_DEAD && Collision_BOBS(&dug, &rocks[rindex]))
  6721.           {    
  6722.           // move dug back
  6723.           dug.x-=dug_dx;
  6724.           dug.y-=dug_dy;  
  6725.  
  6726.           // push rock over a bit
  6727.           if (dug_dx && (rand()%2)==1)
  6728.              {
  6729.              // knudge rock a bit
  6730.              rocks[rindex].x+=(dug_dx/DUG_SPEED);
  6731.  
  6732.              // make sure it stays on screen
  6733.              if (rocks[rindex].x >= SCREEN_WIDTH-32)
  6734.                 rocks[rindex].x = SCREEN_WIDTH-32-1;
  6735.              else
  6736.              if (rocks[rindex].x < 0)
  6737.                  rocks[rindex].x = 0;
  6738.    
  6739.              } // end if
  6740.           
  6741.           // enable this for vertical push
  6742.           // rocks[rindex].y+=(dug_dy/DUG_SPEED);
  6743.  
  6744.           // start pushing sound
  6745.           ULONG status;
  6746.           sound_fx[dug_push_snd_id].dsbuffer->GetStatus(&status);
  6747.  
  6748.           if (status!=DSBSTATUS_LOOPING && status!=DSBSTATUS_PLAYING)
  6749.              Resume_Sound(dug_push_snd_id,DSBPLAY_LOOPING);
  6750.  
  6751.           // set flag
  6752.           rock_push = 4;
  6753.  
  6754.           // no need to process any more rocks
  6755.           break;
  6756.  
  6757.           } // end if
  6758.  
  6759.        } // end for rindex
  6760.  
  6761.    } // end if
  6762.  
  6763. // decrement rock push event
  6764. if (--rock_push < 0)
  6765.    rock_push = 0;
  6766.  
  6767. // need to turn off rock sound
  6768. if (rock_push==0)
  6769.    Pause_Sound(dug_push_snd_id);
  6770.  
  6771. // ??? this code doesn't need to execute unless dug moves
  6772.  
  6773. // clip dug to screen
  6774. if (dug.x < 0)
  6775.    dug.x=0;
  6776. else
  6777. if (dug.x > (SCREEN_WIDTH-8-dug.width))
  6778.    dug.x = (SCREEN_WIDTH-8-dug.width);
  6779.  
  6780. if (dug.y < 32)
  6781.    {
  6782.    // reset position and rotate 90 deg
  6783.    dug.y = 32;
  6784.  
  6785.    // set direction to right
  6786.    dug.varsI[DUG_INDEX_DIR] = DIR_RIGHT;
  6787.  
  6788.    // set animation sequence to right
  6789.    Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  6790.  
  6791.    } // end if
  6792. else
  6793. if (dug.y > (SCREEN_HEIGHT-16-dug.height))
  6794.    dug.y = (SCREEN_HEIGHT-16-dug.height);
  6795.  
  6796. // test for being crushed by rock, redundant loop
  6797. for (int rindex=0; rindex < NUM_ROCKS; rindex++)
  6798.     {
  6799.     // test if rock is alive
  6800.     if (rocks[rindex].state==ROCK_STATE_FALLING)
  6801.        {
  6802.        // rock is alive, so test for collision with dug
  6803.        if (Collision_BOBS(&rocks[rindex],&dug))
  6804.           {
  6805.           // first reset all state information of dug
  6806.           dug.state = DUG_STATE_CRUSHED;
  6807.           dug.anim_state = 0;
  6808.  
  6809.           // start crunch sound
  6810.           Play_Sound_From_Pool(crunch_snd_ids,4);
  6811.  
  6812.           // tag rock
  6813.           dug.varsI[DUG_INDEX_OBJECT_PTR] = rindex;
  6814.  
  6815.           // set animation
  6816.           Set_Animation_BOB2(&dug,DUG_ANIM_CRUSHED);  
  6817.  
  6818.           // set animation speed
  6819.           Set_Anim_Speed_BOB(&dug,4);
  6820.  
  6821.           // that's it
  6822.           break;
  6823.                 
  6824.           } // end if
  6825.  
  6826.        } // end if
  6827.  
  6828.     } // end for rindex
  6829.  
  6830. // process all state vars of dug ?? might want to make different
  6831. if (++pump_valve >= (1+(dug.varsI[DUG_INDEX_LEVEL] >> 4)))
  6832. {
  6833. if (++dug.varsI[DUG_INDEX_PUMP_PSI] > DUG_MAX_PSI)
  6834.     dug.varsI[DUG_INDEX_PUMP_PSI] = DUG_MAX_PSI;
  6835.  
  6836. // reset
  6837. pump_valve = 0;
  6838. } // end if
  6839.  
  6840. // animate dug in fire mode
  6841. if (dug.varsI[DUG_INDEX_ANIM_MODE]==DUG_ANIM_FIRE)
  6842.    Animate_BOB(&dug);   
  6843.  
  6844. if (keyboard_state[DIK_SPACE])
  6845.    draw_on=-draw_on;
  6846.  
  6847. // test if dug is upstairs
  6848. if (dug.y <= DUG_MIN_ROCK_LINE)
  6849.    {
  6850.    //?? is dug dead, used to be 3
  6851.    if ((dug.varsI[DUG_INDEX_DAMAGE] += ( 1 + (dug.varsI[DUG_INDEX_LEVEL] >> 4))) > DUG_MAX_RADIATION)
  6852.       {
  6853.       // ouch
  6854.       Start_Dug_Death();
  6855.       } // end if  
  6856.  
  6857.    } // end if
  6858. else
  6859.    {
  6860.    // cool radiation down
  6861.    if (dug.varsI[DUG_INDEX_DAMAGE] > 0)
  6862.       if (++heal_count > 2)
  6863.          {
  6864.          dug.varsI[DUG_INDEX_DAMAGE]--;
  6865.          heal_count=0;
  6866.          } // end if
  6867.    } // end if
  6868.  
  6869.  
  6870. // test for radiation poisoning
  6871. if (!radiation_message_played && dug.varsI[DUG_INDEX_DAMAGE] >= DUG_CRITICAL_RADIATION)
  6872.    {
  6873.    // set flag
  6874.    radiation_message_played = 1;
  6875.  
  6876.    // play warning sound
  6877.    Play_Sound(radiation_snd_id);
  6878.  
  6879.    } // end if
  6880. else
  6881. if (dug.varsI[DUG_INDEX_DAMAGE] < DUG_CRITICAL_RADIATION)
  6882.     radiation_message_played = 0;
  6883.  
  6884. // test for new man
  6885. if (dug.varsI[DUG_INDEX_SCORE] > new_man_tracker)
  6886.    {
  6887.    // give player another life
  6888.    dug.varsI[DUG_INDEX_LIVES]++;
  6889.  
  6890.    // increase threshold for a new man
  6891.    new_man_tracker+=POINTS_NEW_MAN;
  6892.  
  6893.    // play sound
  6894.    Play_Sound(dug_life_snd_id);
  6895.  
  6896.    } // end if
  6897.  
  6898.  
  6899. // test for weapons fire keyboard
  6900. if ((keyboard_state[DIK_LCONTROL]) && (!fire_deb) && (dug.varsI[DUG_INDEX_PUMP_PSI] > DUG_MIN_PSI))
  6901.    {
  6902.    // fire the pump
  6903.    if (dug.varsI[DUG_INDEX_DIR]==DIR_LEFT || dug.varsI[DUG_INDEX_DIR]==DIR_RIGHT)
  6904.       Start_Gpump(dug.x+12, dug.y+12,dug.varsI[DUG_INDEX_DIR]);
  6905.    else
  6906.       Start_Gpump(dug.x+12, dug.y+12,dug.varsI[DUG_INDEX_DIR]);
  6907.  
  6908.    // take some of dugs air out
  6909.    dug.varsI[DUG_INDEX_PUMP_PSI]-=16; //?? used to be 20
  6910.  
  6911.    // set debounce
  6912.    fire_deb=1;
  6913.  
  6914.    // check animation mode of dug
  6915.    if (dug.varsI[DUG_INDEX_ANIM_MODE] != DUG_ANIM_FIRE)
  6916.       {
  6917.       // set mode to fire
  6918.       dug.varsI[DUG_INDEX_ANIM_MODE] = DUG_ANIM_FIRE;
  6919.  
  6920.       // set animation sequence to left
  6921.       Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  6922.  
  6923.       } // end if
  6924.  
  6925.    } // end if
  6926. // debounce fire button keyboard
  6927. if (!keyboard_state[DIK_LCONTROL])
  6928.    fire_deb = 0;
  6929.  
  6930. // test for weapons fire joystick
  6931. if ((joy_state.rgbButtons[0]) && (!fireb_deb) && (dug.varsI[DUG_INDEX_PUMP_PSI] > DUG_MIN_PSI))
  6932.    {
  6933.    // fire the pump
  6934.    if (dug.varsI[DUG_INDEX_DIR]==DIR_LEFT || dug.varsI[DUG_INDEX_DIR]==DIR_RIGHT)
  6935.       Start_Gpump(dug.x+12, dug.y+12,dug.varsI[DUG_INDEX_DIR]);
  6936.    else
  6937.       Start_Gpump(dug.x+12, dug.y+12,dug.varsI[DUG_INDEX_DIR]);
  6938.  
  6939.    // take some of dugs air out
  6940.    dug.varsI[DUG_INDEX_PUMP_PSI]-=16; //?? used to be 20
  6941.  
  6942.    // set debounce
  6943.    fireb_deb=1;
  6944.  
  6945.    // check animation mode of dug
  6946.    if (dug.varsI[DUG_INDEX_ANIM_MODE] != DUG_ANIM_FIRE)
  6947.       {
  6948.       // set mode to fire
  6949.       dug.varsI[DUG_INDEX_ANIM_MODE] = DUG_ANIM_FIRE;
  6950.  
  6951.       // set animation sequence to left
  6952.       Set_Animation_BOB2(&dug, dug.varsI[DUG_INDEX_ANIM_MODE] + dug.varsI[DUG_INDEX_DIR]*3);
  6953.  
  6954.       } // end if
  6955.  
  6956.    } // end if
  6957. // debounce fire button keyboard
  6958. if (!joy_state.rgbButtons[0])
  6959.    fireb_deb = 0;
  6960.  
  6961.  
  6962. } // end if dug is alive
  6963. else
  6964. {
  6965. // not alive
  6966.  
  6967. // turn anything off
  6968. Pause_Sound(dug_push_snd_id);   
  6969.  
  6970. } // end if
  6971.  
  6972. // test of other states
  6973. if (dug.state==DUG_STATE_DYING)
  6974.    {
  6975.    // animate the death sequence
  6976.    Animate_BOB2(&dug);
  6977.  
  6978.    // test for done sequence
  6979.    if (dug.anim_state == BOB_STATE_ANIM_DONE)
  6980.       {
  6981.       // set state to dead
  6982.       dug.state      = DUG_STATE_DEAD;
  6983.       dug.anim_state = 0;
  6984.       dug.counter_1  = 100;
  6985.       Set_Anim_Speed_BOB(&dug, 3);
  6986.  
  6987.       // one less life
  6988.       if (--dug.varsI[DUG_INDEX_LIVES] < 0)
  6989.          {
  6990.          // dug is dead
  6991.          game_state = GAME_STATE_OVER;
  6992.  
  6993.          } // end if
  6994.  
  6995.       } // end if
  6996.  
  6997.    } // end if
  6998. else
  6999. if (dug.state==DUG_STATE_CRUSHED)
  7000.    {
  7001.    // dug is getting crushed, simple track tagged rock
  7002.    dug.x = rocks[dug.varsI[DUG_INDEX_OBJECT_PTR]].x;
  7003.    dug.y = rocks[dug.varsI[DUG_INDEX_OBJECT_PTR]].y+8;
  7004.  
  7005.    // test for done sequence
  7006.    if (dug.anim_state != BOB_STATE_ANIM_DONE)
  7007.       {
  7008.       // animate the rebirth sequence
  7009.       Animate_BOB2(&dug);
  7010.  
  7011.      // test if animation is complete   
  7012.      if (dug.anim_state == BOB_STATE_ANIM_DONE)
  7013.         dug.curr_frame = dug.animations[DUG_ANIM_CRUSHED][2];
  7014.  
  7015.       } // end if
  7016.  
  7017.    // test if rock is complete and in crumble mode
  7018.    if (rocks[dug.varsI[DUG_INDEX_OBJECT_PTR]].state==ROCK_STATE_DEAD)
  7019.       {
  7020.       // set state to dead
  7021.       dug.state      = DUG_STATE_DEAD;
  7022.       dug.anim_state = 0;
  7023.       dug.counter_1  = 100;
  7024.       Set_Anim_Speed_BOB(&dug, 2);
  7025.  
  7026.       // one less life
  7027.       if (--dug.varsI[DUG_INDEX_LIVES] < 0)
  7028.          {
  7029.          // dug is dead
  7030.          game_state = GAME_STATE_OVER;
  7031.  
  7032.          } // end if
  7033.  
  7034.       // start up score object
  7035.  
  7036.       } // end if
  7037.  
  7038. } // end if   
  7039. else
  7040. if (dug.state==DUG_STATE_DEAD)
  7041.    {
  7042.    // test if death is over
  7043.    if (--dug.counter_1 < 0)
  7044.       {
  7045.       // reset counter
  7046.       dug.counter_1 = 0;
  7047.  
  7048.       // reset state
  7049.       dug.state=DUG_STATE_REBIRTH;
  7050.       dug.varsI[DUG_INDEX_DAMAGE] = 0;
  7051.      
  7052.       // reset vars
  7053.       dug.varsI[DUG_INDEX_ANIM_MODE] = DUG_ANIM_WALK;
  7054.  
  7055.       // set direction to left
  7056.       dug.varsI[DUG_INDEX_DIR] = DIR_LEFT;
  7057.  
  7058.       // set initial animation sequence
  7059.       //Set_Animation_BOB2(&dug, DUG_ANIM_WALK + dug.varsI[DUG_INDEX_DIR]*3);
  7060.       Set_Animation_BOB2(&dug,DUG_ANIM_REBIRTH);
  7061.       
  7062.       // set position
  7063.       Set_Pos_BOB(&dug,320,32);       
  7064.  
  7065.       // start rebirth sound
  7066.       Play_Sound(dug_trans_snd_id);
  7067.  
  7068.       } // end if
  7069.  
  7070.    } // end if
  7071. else
  7072. if (dug.state==DUG_STATE_REBIRTH)
  7073.    {
  7074.    // animate the rebirth sequence
  7075.    Animate_BOB2(&dug);
  7076.  
  7077.    // test for done sequence
  7078.    if (dug.anim_state == BOB_STATE_ANIM_DONE)
  7079.       {
  7080.       // set state to dead
  7081.       dug.state = DUG_STATE_ALIVE;
  7082.  
  7083.       // set animation sequence to walk
  7084.       Set_Animation_BOB2(&dug, DUG_ANIM_WALK + dug.varsI[DUG_INDEX_DIR]*3);
  7085.  
  7086.       } // end if
  7087.  
  7088.    } // end if
  7089.  
  7090. // process gpumps
  7091. Process_Gpumps();
  7092.  
  7093. // process prize
  7094. Process_Prize();
  7095.  
  7096. // process score
  7097. Process_Scores();
  7098.  
  7099. //mono.clear();
  7100.  
  7101. // process poos
  7102. Process_Poos();
  7103.  
  7104. // process puffs
  7105. Process_Puffs();
  7106.  
  7107. // process fire balls
  7108. Process_Fballs();
  7109.  
  7110. // process all rocks
  7111. Process_Rocks();
  7112.  
  7113. // draw all rocks
  7114. Draw_Rocks();
  7115.  
  7116. // draw pumps
  7117. Draw_Gpumps();
  7118.  
  7119. // draw poos
  7120. Draw_Poos();
  7121.  
  7122. // draw fire balls
  7123. Draw_Fballs();
  7124.  
  7125. // draw puffs
  7126. Draw_Puffs();
  7127.  
  7128. // draw digdumb
  7129. if (dug.state!=DUG_STATE_DEAD)
  7130.     Draw_BOB(&dug,lpddsback);
  7131.  
  7132. // draw prize
  7133. Draw_Prize();
  7134.  
  7135. // draw scores
  7136. Draw_Scores();
  7137.  
  7138. // update high score
  7139. if (dug.varsI[DUG_INDEX_SCORE] > high_score)
  7140.    {
  7141.    // reset high score
  7142.    high_score = dug.varsI[DUG_INDEX_SCORE];
  7143.    } // end if
  7144.  
  7145. // draw information
  7146. Draw_Info();
  7147.  
  7148. // draw all foreground objects
  7149.  
  7150.  
  7151. // flip the surfaces
  7152. DD_Flip();
  7153.  
  7154. // sync to 40ish fps
  7155. Wait_Clock(24);
  7156.  
  7157. // test if dug is done with level
  7158. if (dug.varsI[DUG_INDEX_KILLS] >= num_creatures_on_level && ++end_level_counter >= END_LEVEL_DELAY)
  7159.    {
  7160.    // transition to next level
  7161.    game_state = GAME_STATE_NEXT_LEVEL;
  7162.  
  7163.    // reset counter
  7164.    end_level_counter = 0;
  7165.  
  7166.    // increment level number
  7167.    dug.varsI[DUG_INDEX_LEVEL]++;
  7168.  
  7169.    } // end if
  7170.  
  7171.  
  7172. // test for exit to menu
  7173. if (!esc_deb && keyboard_state[DIK_ESCAPE])
  7174.    {
  7175.    game_state = GAME_STATE_MENU;
  7176.  
  7177.    esc_deb = 1;
  7178.    } // end if
  7179. else
  7180. if (!keyboard_state[DIK_ESCAPE])
  7181.     esc_deb = 0;
  7182.  
  7183. // check for pause mode
  7184. if (!pause_deb && keyboard_state[DIK_P])
  7185.    {
  7186.    game_state = GAME_STATE_PAUSED;
  7187.    pause_deb = 1;
  7188.  
  7189.    // display paused in primary buffer
  7190.    Draw_Text_GDI("Game Paused - Press <P> to Continue...", 
  7191.                  SCREEN_WIDTH/2 - 4*strlen("Game Paused - Press <P> to Continue..."), SCREEN_HEIGHT/2, 
  7192.                  RGB(0,255,0),lpddsprimary);
  7193.  
  7194.    } // end if
  7195. else
  7196. if (!keyboard_state[DIK_P])
  7197.     pause_deb = 0;
  7198.  
  7199.  
  7200. #if 0
  7201.  
  7202. // diagnostic printing area
  7203. sprintf(buffer,"curr_anim=%d curr_frame=%d       ",dug.curr_animation, dug.curr_frame);
  7204. mono.set_cursor(0,1);
  7205. mono.print(buffer);
  7206.  
  7207. sprintf(buffer,"draw_on=%d  ",draw_on);
  7208. mono.set_cursor(0,2);
  7209. mono.print(buffer);
  7210.  
  7211. sprintf(buffer,"dug x=%d y=%d  ",dug.x, dug.y);
  7212. mono.set_cursor(0,3);
  7213. mono.print(buffer);
  7214.  
  7215. sprintf(buffer,"dug psi=%d  ",dug.varsI[DUG_INDEX_PUMP_PSI]);
  7216. mono.set_cursor(0,4);
  7217. mono.print(buffer);
  7218.  
  7219. sprintf(buffer,"dug kills=%d  ",dug.varsI[DUG_INDEX_KILLS]);
  7220. mono.set_cursor(0,5);
  7221. mono.print(buffer);
  7222.  
  7223. sprintf(buffer,"num_creatures_on_level=%d  ",num_creatures_on_level);
  7224. mono.set_cursor(0,6);
  7225. mono.print(buffer);
  7226.  
  7227.  
  7228. #endif
  7229.  
  7230.  
  7231. } // end if 
  7232. else
  7233. if (game_state == GAME_STATE_PAUSED)
  7234. {
  7235. // get input
  7236. DI_Read_Keyboard();
  7237. //DI_Read_Mouse();
  7238. //DI_Read_Joystick();
  7239.  
  7240. // the game is paused, wait for player to hit pause key again
  7241. if (!pause_deb && keyboard_state[DIK_P])
  7242.    {
  7243.    game_state = GAME_STATE_RUNNING;
  7244.    pause_deb = 1;
  7245.    } // end if
  7246. else
  7247. if (!keyboard_state[DIK_P])
  7248.     pause_deb = 0;
  7249.  
  7250. } // end if
  7251. else
  7252. if (game_state == GAME_STATE_WIN)
  7253. {
  7254. // clear out back surface
  7255. DD_Fill_Surface(lpddsback, 0);
  7256.  
  7257. // wait a sec
  7258. //Sleep(2000);
  7259.  
  7260. // play game over animation
  7261. if ((rand()%2)==1)
  7262.     {
  7263.     DD_Lock_Primary_Surface();
  7264.     Screen_Transitions(SCREEN_DISOLVE, primary_buffer, primary_lpitch);
  7265.     DD_Unlock_Primary_Surface();
  7266.    
  7267.     // clear out primary surface
  7268.     DD_Fill_Surface(lpddsprimary, 0);
  7269.  
  7270.     }
  7271. else
  7272.     {
  7273.     Save_Palette(save_palette);
  7274.     Screen_Transitions(SCREEN_DARKNESS, primary_buffer, primary_lpitch);
  7275.  
  7276.     // clear out primary surface
  7277.     DD_Fill_Surface(lpddsprimary, 0);
  7278.  
  7279.     Set_Palette(save_palette);
  7280.     } // end if
  7281.  
  7282. // draw in game over screen
  7283. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDWIN8.BMP");
  7284.  
  7285. // play sound
  7286. Play_Sound(win_snd_id);
  7287.  
  7288. // copy the bitmap to primary buffer
  7289. DD_Lock_Primary_Surface();
  7290. Copy_Screen(bitmap8bit.buffer,primary_buffer, primary_lpitch, 0);
  7291. DD_Unlock_Primary_Surface();
  7292.  
  7293. // unload the bitmap
  7294. Unload_Bitmap_File(&bitmap8bit);
  7295.  
  7296. // wait for sound to stop
  7297. while(1)
  7298.      {
  7299.      // is music done yet
  7300.      ULONG status;
  7301.      sound_fx[win_snd_id].dsbuffer->GetStatus(&status);
  7302.  
  7303.      if (status==0)
  7304.          break;
  7305.  
  7306.      } // end while
  7307.  
  7308. // wait a sec
  7309. Sleep(1000);
  7310.  
  7311. // fade away
  7312. Save_Palette(save_palette);
  7313. Screen_Transitions(SCREEN_DARKNESS, primary_buffer, primary_lpitch);
  7314. // clear out primary surface
  7315. DD_Fill_Surface(lpddsprimary, 0);
  7316. Set_Palette(save_palette);
  7317.  
  7318.  
  7319. // set state to menu
  7320. game_state = GAME_STATE_INIT;
  7321.  
  7322. } // end if
  7323. else
  7324. if (game_state == GAME_STATE_OVER)
  7325. {
  7326. // clear out back surface
  7327. DD_Fill_Surface(lpddsback, 0);
  7328.  
  7329. // wait a sec
  7330. Sleep(2000);
  7331.  
  7332. // play game over animation
  7333. if ((rand()%2)==1)
  7334.     {
  7335.     DD_Lock_Primary_Surface();
  7336.     Screen_Transitions(SCREEN_DISOLVE, primary_buffer, primary_lpitch);
  7337.     DD_Unlock_Primary_Surface();
  7338.    
  7339.     // clear out primary surface
  7340.     DD_Fill_Surface(lpddsprimary, 0);
  7341.  
  7342.     }
  7343. else
  7344.     {
  7345.     Save_Palette(save_palette);
  7346.     Screen_Transitions(SCREEN_DARKNESS, primary_buffer, primary_lpitch);
  7347.  
  7348.     // clear out primary surface
  7349.     DD_Fill_Surface(lpddsprimary, 0);
  7350.  
  7351.     Set_Palette(save_palette);
  7352.     } // end if
  7353.  
  7354. // play sound
  7355. Play_Sound(game_over_snd_id);
  7356.  
  7357. // draw in game over screen
  7358. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDOVER8.BMP");
  7359.  
  7360. // copy the bitmap to primary buffer
  7361. DD_Lock_Primary_Surface();
  7362. Copy_Screen(bitmap8bit.buffer,primary_buffer, primary_lpitch, 0);
  7363. DD_Unlock_Primary_Surface();
  7364.  
  7365. // unload the bitmap
  7366. Unload_Bitmap_File(&bitmap8bit);
  7367.  
  7368. // wait a sec
  7369. Sleep(4000);
  7370.  
  7371. // fade away
  7372. Save_Palette(save_palette);
  7373. Screen_Transitions(SCREEN_DARKNESS, primary_buffer, primary_lpitch);
  7374. // clear out primary surface
  7375. DD_Fill_Surface(lpddsprimary, 0);
  7376. Set_Palette(save_palette);
  7377.  
  7378.  
  7379. // set state to menu
  7380. game_state = GAME_STATE_INIT;
  7381.  
  7382. } // end if
  7383.  
  7384. else
  7385. if (game_state == GAME_STATE_EXIT)
  7386. {
  7387. // this is the exit state, runs exactly once
  7388.  
  7389. // play the ending music
  7390. Play_Sound(credits_snd_id);
  7391.  
  7392. // clear out back surface
  7393. DD_Fill_Surface(lpddsback, 0);
  7394.  
  7395. // perform screen transition
  7396. DD_Lock_Primary_Surface();
  7397. Screen_Transitions(SCREEN_DISOLVE, primary_buffer, primary_lpitch);
  7398. DD_Unlock_Primary_Surface();
  7399.  
  7400. //mono.print("\nin exit");
  7401.  
  7402. // draw in credits screen
  7403. Load_Bitmap_File(&bitmap8bit, "UNDART/UNDCRED8.BMP");
  7404.  
  7405. // copy the bitmap to primary buffer
  7406. DD_Lock_Primary_Surface();
  7407. Copy_Screen(bitmap8bit.buffer,primary_buffer, primary_lpitch, 0);
  7408. DD_Unlock_Primary_Surface();
  7409.  
  7410. // unload bitmap file
  7411. Unload_Bitmap_File(&bitmap8bit);
  7412.  
  7413. // wait for key board hit
  7414. while(1)
  7415.      {
  7416.      // read the keyboard
  7417.      DI_Read_Keyboard();
  7418.  
  7419.      // the game is paused, wait for player to hit pause key again
  7420.      if (keyboard_state[DIK_RETURN] || keyboard_state[DIK_SPACE] || keyboard_state[DIK_ESCAPE])    
  7421.         break;
  7422.  
  7423.      // is music done yet
  7424.      ULONG status;
  7425.      sound_fx[credits_snd_id].dsbuffer->GetStatus(&status);
  7426.  
  7427.      if (status==0)
  7428.          break;
  7429.  
  7430.      } // end if
  7431.  
  7432. // wait a sec
  7433. //Sleep(7500);
  7434.  
  7435. // fade away
  7436. Save_Palette(save_palette);
  7437. Screen_Transitions(SCREEN_DARKNESS, primary_buffer, primary_lpitch);
  7438. // clear out primary surface
  7439. DD_Fill_Surface(lpddsprimary, 0);
  7440. Set_Palette(save_palette);
  7441.  
  7442. // turn off credits sound
  7443. Stop_Sound(credits_snd_id);
  7444.  
  7445. // exit windows
  7446. PostMessage(main_window_handle, WM_DESTROY,0,0);
  7447.  
  7448. // set terminal wait state
  7449. game_state = GAME_STATE_WAIT_FOR_TERMINATION;
  7450.  
  7451. } // end if
  7452. else
  7453. if (game_state == GAME_STATE_WAIT_FOR_TERMINATION)
  7454. {
  7455. // just chill, there are a few messages in the queue...
  7456. //mono.print("\nterminal state");
  7457.  
  7458. } // end 
  7459.  
  7460.  
  7461. // return success
  7462. return(1);
  7463.  
  7464. } // end Game_Main
  7465.  
  7466. //////////////////////////////////////////////////////////
  7467.