home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / SLOWRUNS.ZIP / SLOWSRC.ZIP / NEWGAME5.C < prev    next >
C/C++ Source or Header  |  1997-12-07  |  169KB  |  6,543 lines

  1. // COPYRIGHT 1997 - by James McCue
  2.  
  3. // This is SOME of the main module to the source code of
  4. // the game "Slow Runnings 1.11".
  5.  
  6. // It's stupid to dump all the code into one source module...
  7.  
  8. // I just ripped most of it out!
  9.  
  10. // This code was such a pigsty - it was embarrassing!
  11.  
  12.  
  13. // ...it still is!
  14.  
  15. // I'M REFINING THE CODE - AND BEGINNING WORK ON SOMETHING ELSE
  16. // 3D!!!
  17.  
  18. // THIS SOURCE CODE AND IT'S ASSOCIATED FILES ARE DISTRIBUTED AS IS,
  19. // AND WITHOUT WARRANTY OF ANY KIND!
  20.  
  21. // JAMES MCCUE MAKES NO CLAIMS AS TO THE MARKETABLITY OF THIS
  22. // SOURCE CODE, OR ANYTHING MADE WITH IT.
  23.  
  24. // NOR DOES JAMES MCCUE MAKE ANY CLAIMS ABOUT THIS SOFTWARE'S
  25. // USEFULNESS FOR ANY PURPOSE.
  26.  
  27. // JAMES MCCUE IS NOT RESPONSIBLE FOR ANY DAMAGE (SOFTWARE OR
  28. // HARDWARE) THAT ARISES FROM THE USE OF THIS CODE - NOR ANY
  29. // EXECUTABLES MADE WITH/FROM IT...
  30.  
  31. // I hope you can learn something from this...
  32.  
  33. #include <io.h>
  34. #include <conio.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <dos.h>
  38. #include <bios.h>
  39. #include <fcntl.h>
  40. #include <memory.h>
  41. #include <malloc.h>
  42. #include <math.h>
  43. #include <errno.h>
  44. #include <string.h>
  45. #include <search.h>             // this one is needed for qsort()
  46.  
  47. #include "magic3.h"
  48. #include "magic4.h"
  49. #include "magic5.h"
  50. #include "magic6.h"
  51. #include "magic8.h"
  52. //#include <time.h>
  53.  
  54.  
  55. // D E F I N E S /////////////////////////////////////////////////////////////
  56.  
  57. // #define DEBUG 1
  58.  
  59. #define OVERBOARD          44 // the absolute closest a player can get to a wall
  60.  
  61. #define INTERSECTION_FOUND 1
  62.  
  63. // enemy states...
  64.  
  65. #define PURSUING            0
  66. #define WAITING                1
  67. #define FIRING                2
  68. #define DEAD                3
  69. #define EVADING                4
  70. #define DYING                5
  71. #define STANDING_AND_FIRING 6
  72. #define HIT                    7
  73.  
  74. // PLAYER STATES..... //////////////////////////////////////////////
  75.  
  76. #define PLAYER_NOT_FIRING  0
  77. #define PLAYER_FIRING       1
  78.  
  79. // SOUNDS //////////////////////////////////////////////
  80.  
  81. #define door_sound            0
  82. #define firing_sound        1
  83. #define enemy_death_sound    2
  84. #define enemy_shoot_sound   3
  85. #define map_warp_sound        4
  86.  
  87. // for Math stuff..../////////////////////////////
  88.  
  89. #define Pi                    (float)3.1415926
  90. #define DEG_TO_RAD         ((float)3.1415926/(float)180)
  91.  
  92. #define WORLD_ROWS    32
  93. #define WORLD_COLUMNS 32
  94. #define CELL_X_SIZE   64
  95. #define CELL_Y_SIZE   64
  96.  
  97. #define SWATCH_WIDTH  64
  98.  
  99. #define CELL_X_SIZE_FP 6   // <- used for bit-wize shifting
  100. #define CELL_Y_SIZE_FP 6   // because it is faster than
  101.                            // multiplication and division
  102.  
  103. // size of overall game world
  104.  
  105. #define WORLD_X_SIZE  (WORLD_COLUMNS * CELL_X_SIZE)
  106. #define WORLD_Y_SIZE  (WORLD_ROWS    * CELL_Y_SIZE)
  107.  
  108. #define MAX_SCALE             235 // maximum size and wall "sliver" can be
  109.  
  110.  
  111. #define WALL_MIDDLE_OFFSET   (32<<6)
  112. #define WALL_MIDDLE_MINUS_OFFSET (31<<6)
  113.  
  114. #define WOIK_OFFSET_1(y_off)     (WALL_MIDDLE_OFFSET - scale_row[y_off])
  115. #define WOIK_OFFSET_2(y_off)     (WALL_MIDDLE_OFFSET + scale_row[y_off])
  116.  
  117. #define BORDER_COLOR_1           42
  118. #define BORDER_COLOR_2           48
  119. #define BORDER_COLOR_3           54
  120. #define BORDER_COLOR_4           48
  121.  
  122. #define OPENING                    1
  123. #define CLOSING                    2
  124. #define OPEN                    3
  125. #define CLOSED                    4
  126.  
  127. #define DOSALLOC 0
  128.  
  129. #define MAX_OBJECTS                55
  130.  
  131. #define MAX_ENEMIES                20
  132.  
  133. // GLOBALS /////////////////////////////////////////////
  134.  
  135. // constants used to represent angles
  136.  
  137. int my_size = 1216; // for a 90 degree view cone
  138.  
  139. int my_v_scale = 9500;    // for 90 big-ass degrees of view coneage carnage!
  140.  
  141. int my_height = 148;
  142. int my_right = 312;
  143. int my_left = 8;
  144.  
  145. int COLUMN_OFFSET=           311;
  146.  
  147. int ANGLE_360;
  148.  
  149. int ANGLE_180;
  150. int ANGLE_90;
  151. int ANGLE_75;
  152. int ANGLE_60;
  153. int ANGLE_45;
  154. int ANGLE_30;
  155. int ANGLE_15;
  156. int ANGLE_6;
  157. int ANGLE_5;
  158. int ANGLE_4;
  159. int ANGLE_2;
  160. int ANGLE_1;
  161. int ANGLE_0;
  162.  
  163. // some ODDBALL angles
  164.  
  165. int ANGLE_315;
  166. int ANGLE_270;
  167. int ANGLE_225;
  168. int ANGLE_135;
  169. int ANGLE_10;
  170. int ANGLE_9;
  171. int ANGLE_8;
  172. int ANGLE_7;
  173.                  // ... and some possible view cone values
  174. int ANGLE_80;
  175. int ANGLE_70;
  176. // for 'shifting the parachute' (?!)
  177.  
  178. int ANGLE_23;
  179.  
  180. int VIEW_CONE;
  181.  
  182. int HALF_VIEW_CONE;
  183.  
  184. // conversion constants from radians to degrees and vice-versa
  185.  
  186. float ANGULAR_INCREMENT;
  187.  
  188.  
  189. float RAD_TO_DEG;
  190.  
  191. // conversion constants from radians to degrees and vicversa
  192.  
  193. // MORE GLOBALS //////////////////////////////
  194.  
  195. int WINDOW_HEIGHT;
  196.  
  197. int WINDOW_HALF_HEIGHT;
  198.  
  199. int WINDOW_MIDDLE;
  200.  
  201. int WINDOW_MIDDLE_MINUS;
  202.  
  203. int WINDOW_TOP;
  204. int WINDOW_BOTTOM;
  205. int WINDOW_LEFT;
  206. int WINDOW_RIGHT;
  207.  
  208. int VERTICAL_SCALE;     // used to scale the "slivers" to get proper
  209.  
  210. int total_world_doors = 0;
  211.  
  212. typedef long fixed;
  213.  
  214. int toggle = 0;
  215.  
  216. // SOUND ////////////////
  217.  
  218. sound global_sounds[7];
  219.  
  220. // MUSIC //////////////////////////////////////////////
  221.  
  222. music song;
  223.  
  224.  
  225. typedef struct object_type
  226. {
  227.     int kind_of_object;
  228.     long x;
  229.     long y;
  230.     long dist;
  231.     long angle;
  232.     int id_number;
  233. } objects, objects_ptr;
  234.  
  235. typedef struct statist_typ
  236. {
  237.     float width_factor;
  238.     long Scale_Factor;
  239.     int Is_Multi_View;
  240.     int Is_Half_Height;
  241. } stats, stats_ptr;
  242.  
  243. typedef struct Enemy_type
  244. {
  245.     objects vitals;
  246.     int enem_num;
  247.     int state;
  248.     int threshold;
  249.     int hit_points;
  250.     int pat_num;
  251. } enemy_objects, enemy_objects_ptr;
  252.  
  253.  
  254. typedef struct door_type
  255. {
  256.     int door_y;
  257.     int door_x;
  258.     int door_state;
  259.     int door_block_type;
  260.     int locked;
  261.     int door_speed;
  262.     int door_increment;
  263.     int door_wait_to_close;
  264. } door, door_ptr;
  265.  
  266. typedef struct wall_type
  267. {
  268.      char block_type;
  269.      short door_id;
  270. } wall, wall_ptr;
  271.  
  272. typedef struct save_game
  273. {
  274.     int cur_strength;
  275.     int cur_ammo;
  276.     int cur_map;
  277.     int cur_level;
  278. } savestr, savestr_ptr;
  279.  
  280. typedef struct name_typ
  281. {
  282.     unsigned char name[13];
  283. } name_obj, name_obj_ptr;
  284.  
  285. name_obj names[5];
  286.  
  287. door doors[20];
  288.  
  289. int objects_found = 0;
  290.  
  291. int OVERBOARD_FOR_ENEMIES = 52; // absolute closest enemies can get to a wall
  292.  
  293. int got_key = 0;
  294.  
  295.  
  296. // look up tables! ////////////////////////////////////////////////////////
  297.  
  298. wall world[WORLD_ROWS][WORLD_COLUMNS];       // pointer to matrix of cells that make up
  299.                                    // world
  300. char far *Block_Map[WORLD_ROWS];   // pointer to block map...
  301.  
  302. float far *tan_table;              // tangent tables used to compute initial
  303. float far *inv_tan_table;          // intersections with rays
  304.  
  305.  
  306. float far *y_step;                 // x and y steps, used to find intersections
  307. float far *x_step;                 // after initial one is found
  308.  
  309.  
  310. float far *cos_table;              // used to cancel out fishbowl effect
  311.  
  312. float far *inv_cos_table;          // used to compute distances by calculating
  313. float far *inv_sin_table;          // the hypontenuse
  314.  
  315. int *scale_table[MAX_SCALE+1];     // table with pre-computed scale indices
  316.  
  317. // parmeter block used by assembly language sliver engine
  318.  
  319. char far *sliver_texture; // pointer to texture being rendered
  320. int sliver_column;        // index into texture i.e. which column of texture
  321. int sliver_top;           // starting Y position to render at
  322. int sliver_bottom;
  323. int sliver_scale;         // overall height of sliver
  324. int sliver_ray;           // current ray being cast
  325. int sliver_clip;          // index into texture after clipping
  326. int *scale_row;           // row of scale value look up table to use
  327.  
  328. // OBJECT LISTS
  329.  
  330. objects *object_list;
  331.  
  332. stats obj_statistic_list[7];
  333.  
  334.  
  335. objects *initial_object_list;
  336.  
  337. enemy_objects *enemies;
  338.  
  339.  
  340. // G L O B A L S ////////////////////////////////////////////////////////////
  341.  
  342. pcx_picture back_pcx,
  343.             image_pcx;
  344.  
  345. sprite wall_frames;
  346.  
  347. sprite duck_frames;
  348. sprite duck_death;
  349. sprite ob_frames;
  350. sprite the_gun;
  351.  
  352. int is_multi = 0;     // for multiview sprites!
  353. int Player_Strength = 63;
  354. int just_grabbed_something = 0;
  355.  
  356. long  x, y,view_angle;
  357.  
  358. int index1,
  359.     counter,
  360.     counter2;
  361.  
  362. int duck_pattern[24] = {0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,1,1,1,1,1,1};
  363.  
  364. int PAT_LIMIT = 24;
  365.  
  366. int increment=0;   // used to determine how far a door is open
  367. int color;
  368. int what_obj = 0;
  369.  
  370. int gun_top = 108;
  371.  
  372. int Got_Rapid_Fire = 0;
  373.  
  374. long vz_buffer[320+1];  // vertical scanline Zbuffer for determining
  375.                               // sprite_visibility
  376.  
  377. int Ammo_Color = 14;
  378. int Vitality_Color = 119;
  379.  
  380. int Player_Ammo = 28;
  381.  
  382. int beat_it = 0;
  383.  
  384. // structure for slivers, used in order to interleave the ray casting
  385. // with the time spent waiting for the PAGE FLIP to take hold!
  386. //       The elements of this structure are set in the function RAY_CASTER
  387. // and used by DRAW_WALLS in it's subsequent calls to RENDER_SLIVER!
  388.  
  389. typedef struct buffer_typ
  390. {
  391.     char far *sliv_texture; // pointer to texture being rendered
  392.     char sliv_hit_type;
  393.     unsigned short sliv_column;        // index into texture i.e. which column of texture
  394.     unsigned short sliv_top;           // starting Y position to render at
  395.     unsigned short sliv_bottom;
  396.     int sliv_scale;         // overall height of sliver
  397.     int sliv_ray;           // current ray being cast
  398.     int sliv_clip;          // index into texture after clipping
  399.     int scale_r;           // row of scale value look up table to use
  400. } sliv_buff, sliv_ptr;
  401.  
  402. sliv_buff sliver_buffer[320+1];  // one structure for all columns drawn
  403.  
  404.  
  405. int v_320[200];      // lookups to speed up the math for drawing pixels
  406. int v_80[200];
  407. int h_320[320];
  408.  
  409. int Number_Of_Fixed_Objects = 0;
  410. int Number_Of_Enemies = 0;
  411.  
  412. int player_state = PLAYER_NOT_FIRING;
  413.  
  414. int AIMED = 0;
  415.  
  416. int digital_enabled = 0;
  417.  
  418. int music_enabled = 0;
  419.  
  420. long color_1, color_ceil, color_floor;
  421.  
  422. unsigned char far *back_up = (unsigned char far *)0xA000C000L;
  423.  
  424. RGB_color global_color;
  425.  
  426. RGB_color color_all;
  427. RGB_color old_all[256];
  428.  
  429. int which_map = 0;
  430. int Red_Factor = 16;
  431. int at_end = 0, really_at_end = 0;
  432. int aimed_sort_of = 0;
  433.  
  434. int in_view = 0;
  435. int New_Lease_On_Life = 0;
  436.  
  437. int pal_reg, id_number;
  438. int Restore_Black = 0;
  439.  
  440. int Damage = 0;
  441.  
  442. int pat_start = 0;
  443. int rotate_em = 1;
  444. char where_am_i[80];
  445. // F U N C T I O N   P R O T O T Y P E S /////////////////////////////
  446.  
  447. void (*rend_func_ptr) ();
  448.  
  449.  
  450. int Object_Sort_Function(objects *arg1, objects *arg2);
  451.  
  452. // creates the scale table
  453.  
  454. void Create_Scale_Data(int scale, int *row);
  455. void Create_Scale_Data2(int scale, int *row);
  456.  
  457.  
  458. // Blits...
  459.  
  460. int Parse_Commands(int argc, char **argv);
  461.  
  462. void Draw_Walls(void);
  463.  
  464. // allocates/initializes tables
  465.  
  466. void Build_Tables(void);
  467.  
  468. void Load_64x64_Sprites(sprite_ptr sprite_set, char *filename, int num_cells);
  469.  
  470. // World Initialization functions...
  471.  
  472. void Allocate_World(void);
  473.  
  474. int Load_World(int lev_numb);
  475.  
  476. // the RAY CASTER!
  477.  
  478. void Ray_Caster(void);
  479.  
  480. void Draw_ReDraw_Frame(void);
  481.  
  482. // self explanatory...
  483.  
  484. // again, self explanatory...
  485.  
  486. void Translate_Player(long dx, long dy);
  487.  
  488. void Process_Doors(void);
  489.  
  490.  
  491. void Render_Sliver(void);
  492.  
  493. void Render_Sliver_Mask(void);
  494.  
  495. void Render_Sliver_Mask_Special(void);
  496.  
  497. void Render_Sliver_Mask_Just_Bottom(void);
  498.  
  499. void Render_UpsideDwn_Mask_Bottom(void);
  500.  
  501. void Level_Select(int well);
  502.  
  503. int Slot_Selection(void);
  504.  
  505. void Refresh_Name_List(int what_shade);
  506.  
  507. int Load_Game(void);
  508.  
  509. void New_Game(void);
  510.  
  511. void Save_Game(void);
  512.  
  513. void Make_Light_Metallic_Blue_Palette(void);
  514.  
  515. void Make_Gold_Palette(void);
  516.  
  517. void Make_Gray_Palette(void);
  518.  
  519. void Make_Blue_Palette(void);
  520.  
  521. void Make_Blue_Palette_OAAT(int delta, int erase_trail);
  522.  
  523. void Make_Cyan_Palette_OAAT(int delta, int erase_trail);
  524.  
  525. void Make_Gold_Palette_OAAT(int delta, int erase_trail);
  526.  
  527. void Make_Gray_Palette_OAAT(int delta, int erase_trail);
  528.  
  529. void Rotate_Em(int well);
  530.  
  531. // BEGINNING OF CODE //////////////////////////////////////////////////////
  532.  
  533.  
  534. void Render_Sliver(void)
  535. {
  536.     // this is yet another version of the sliver scaler, however it uses look up
  537.     // tables with pre-computed scale indices.
  538.  
  539.     // this draws vertical slivers from the middle of the strip to the top,
  540.     // and from the middle of the strip to the bottom.
  541.  
  542.     register char far *work_sprite;
  543.     int far *row;
  544.  
  545.     register int work_offset=0,offset,temp_offset,y_off,scale_off;
  546.  
  547.     // alias a pointer to sprite for ease of access
  548.  
  549.     work_sprite = sliver_texture;
  550.  
  551.     // compute offset of sprite in video buffer
  552.  
  553.     temp_offset = v_80[WINDOW_MIDDLE_MINUS] + h_320[sliver_ray];
  554.  
  555.     // render top half of wall sliver
  556.  
  557.     offset = temp_offset;
  558.  
  559.     work_offset = WALL_MIDDLE_OFFSET - scale_row[0];
  560.  
  561.     video_buffer[offset] = work_sprite[work_offset+sliver_column];
  562.  
  563.     for (y_off=1; y_off<sliver_scale; y_off++)
  564.     {
  565.  
  566.         offset      -= 80;
  567.         work_offset =  WALL_MIDDLE_OFFSET - scale_row[y_off];
  568.  
  569.         video_buffer[offset] = work_sprite[work_offset+sliver_column];
  570.  
  571.     } // end for y
  572.  
  573.     // render bottom half of wall sliver
  574.  
  575.     offset = temp_offset + 80;
  576.  
  577.     work_offset = WALL_MIDDLE_OFFSET;
  578.  
  579.     video_buffer[offset] = work_sprite[work_offset+sliver_column];
  580.  
  581.     for (y_off=0; y_off<(sliver_scale-1); y_off++)
  582.     {
  583.  
  584.  
  585.         offset      += 80;
  586.         work_offset =  WALL_MIDDLE_OFFSET + scale_row[y_off];
  587.  
  588.         video_buffer[offset] = work_sprite[work_offset+sliver_column];
  589.     } // end for y
  590.  
  591. } // end Render_Sliver
  592.  
  593. void Render_Sliver_Mask(void)
  594. {
  595. // this is yet another version of the sliver scaler, however it uses look up
  596. // tables with pre-computed scale indices.  in the end I converted this to
  597. // assembly for speed
  598.  
  599. register char far *work_sprite;
  600. int far *row;
  601.  
  602. register int work_offset=0,offset,y_off,scale_off;
  603.  
  604. // alias proper data row
  605.  
  606. scale_off = sliver_clip;
  607.  
  608. // alias a pointer to sprite for ease of access
  609.  
  610. work_sprite = sliver_texture;
  611.  
  612. // compute offset of sprite in video buffer
  613.  
  614. offset = v_80[WINDOW_MIDDLE_MINUS] + h_320[sliver_ray];
  615.  
  616. work_offset = WALL_MIDDLE_OFFSET - scale_row[0];
  617.  
  618. if (work_sprite[work_offset+sliver_column]!=0)
  619.     video_buffer[offset] = work_sprite[work_offset+sliver_column];
  620.  
  621. for (y_off=1; y_off<sliver_scale; y_off++)
  622.     {
  623.  
  624.     offset      -= 80;
  625.     work_offset =  WALL_MIDDLE_OFFSET - scale_row[y_off];
  626.  
  627.     if (work_sprite[work_offset+sliver_column]!=0)
  628.         video_buffer[offset] = work_sprite[work_offset+sliver_column];
  629.  
  630.     } // end for y
  631.  
  632. offset = v_80[WINDOW_MIDDLE] + h_320[sliver_ray];
  633.  
  634. work_offset = WALL_MIDDLE_OFFSET;
  635.  
  636. if (work_sprite[work_offset+sliver_column]!=0)
  637.     video_buffer[offset] = work_sprite[work_offset+sliver_column];
  638.  
  639. for (y_off=0; y_off<(sliver_scale-1); y_off++)
  640.     {
  641.  
  642.  
  643.     offset      += 80;
  644.     work_offset =  WALL_MIDDLE_OFFSET + scale_row[y_off];
  645.  
  646.     if (work_sprite[work_offset+sliver_column]!=0)
  647.         video_buffer[offset] = work_sprite[work_offset+sliver_column];
  648.     } // end for y
  649.  
  650. } // end Render_Sliver_Mask
  651.  
  652. void Render_Sliver_Mask_Special(void)
  653. {
  654. // this is yet another version of the sliver scaler, however it uses look up
  655. // tables with pre-computed scale indices.  in the end I converted this to
  656. // assembly for speed
  657.  
  658. register char far *work_sprite;
  659. int far *row;
  660.  
  661. register int work_offset=0,offset,y_off,scale_off;
  662. register int Special_Offset;
  663.  
  664. // alias proper data row
  665.  
  666. scale_off = sliver_clip;
  667.  
  668. // alias a pointer to sprite for ease of access
  669.  
  670. work_sprite = sliver_texture;
  671.  
  672. // compute offset of sprite in video buffer
  673.  
  674. Special_Offset = sliver_scale-(sliver_scale/3);
  675.  
  676. offset = v_80[WINDOW_MIDDLE_MINUS-(Special_Offset-1)] + h_320[sliver_ray];
  677.  
  678. work_offset = WALL_MIDDLE_OFFSET - scale_row[0];
  679.  
  680. if (work_sprite[work_offset+sliver_column]!=0)
  681.     video_buffer[offset] = work_sprite[work_offset+sliver_column];
  682.  
  683. for (y_off=Special_Offset; y_off<sliver_scale; y_off++)
  684.     {
  685.  
  686.     offset      -= 80;
  687.     work_offset =  WALL_MIDDLE_OFFSET - scale_row[y_off];
  688.  
  689.     if (work_sprite[work_offset+sliver_column]!=0)
  690.         video_buffer[offset] = work_sprite[work_offset+sliver_column];
  691.  
  692.     } // end for y
  693.  
  694. offset = v_80[WINDOW_MIDDLE+(Special_Offset)] + h_320[sliver_ray];
  695.  
  696. work_offset = WALL_MIDDLE_OFFSET;
  697.  
  698. if (work_sprite[work_offset+sliver_column]!=0)
  699.     video_buffer[offset] = work_sprite[work_offset+sliver_column];
  700.  
  701. for (y_off=Special_Offset; y_off<(sliver_scale-1); y_off++)
  702.     {
  703.  
  704.  
  705.     offset      += 80;
  706.     work_offset =  WALL_MIDDLE_OFFSET + scale_row[y_off];
  707.  
  708.     if (work_sprite[work_offset+sliver_column]!=0)
  709.         video_buffer[offset] = work_sprite[work_offset+sliver_column];
  710.     } // end for y
  711.  
  712. } // end Render_Sliver_Mask_Special
  713.  
  714. void Render_Sliver_Mask_Just_Bottom(void)
  715. {
  716. // this is yet another version of the sliver scaler, however it uses look up
  717. // tables with pre-computed scale indices.  in the end I converted this to
  718. // assembly for speed
  719.  
  720. register char far *work_sprite;
  721. int far *row;
  722.  
  723. register int work_offset=0,offset,y_off,scale_off;
  724.  
  725. // alias proper data row
  726.  
  727.  
  728. // alias a pointer to sprite for ease of access
  729.  
  730. work_sprite = sliver_texture;
  731.  
  732. // compute offset of sprite in video buffer
  733.  
  734.  
  735. offset = v_80[WINDOW_MIDDLE] + h_320[sliver_ray];
  736.  
  737. work_offset = WALL_MIDDLE_OFFSET;
  738.  
  739. if (work_sprite[work_offset+sliver_column]!=0)
  740.     video_buffer[offset] = work_sprite[work_offset+sliver_column];
  741.  
  742. for (y_off=0; y_off<(sliver_scale-1); y_off++)
  743.     {
  744.  
  745.  
  746.     offset      += 80;
  747.     work_offset =  WALL_MIDDLE_OFFSET + scale_row[y_off];
  748.  
  749.     if (work_sprite[work_offset+sliver_column]!=0)
  750.         video_buffer[offset] = work_sprite[work_offset+sliver_column];
  751.     } // end for y
  752.  
  753. } // end Render_Sliver_Mask_Just_Bottom
  754.  
  755. void Render_UpsideDwn_Mask_Bottom(void)
  756. {
  757. // this is yet another version of the sliver scaler, however it uses look up
  758. // tables with pre-computed scale indices.  in the end I converted this to
  759. // assembly for speed
  760.  
  761. register char far *work_sprite;
  762. int far *row;
  763.  
  764. register int work_offset=0,offset,y_off,scale_off;
  765.  
  766. // alias proper data row
  767.  
  768.  
  769. // alias a pointer to sprite for ease of access
  770.  
  771. work_sprite = sliver_texture;
  772.  
  773. // compute offset of sprite in video buffer
  774.  
  775.  
  776. offset = v_80[WINDOW_MIDDLE] + h_320[sliver_ray];
  777.  
  778. work_offset = WALL_MIDDLE_OFFSET;
  779.  
  780. if (work_sprite[work_offset+sliver_column]!=0)
  781.     video_buffer[offset] = work_sprite[work_offset+sliver_column];
  782.  
  783. for (y_off=0; y_off<(sliver_scale-1); y_off++)
  784.     {
  785.  
  786.  
  787.     offset      -= 80;
  788.     work_offset =  WALL_MIDDLE_OFFSET + scale_row[y_off];
  789.  
  790.     if (work_sprite[work_offset+sliver_column]!=0)
  791.         video_buffer[offset] = work_sprite[work_offset+sliver_column];
  792.     } // end for y
  793.  
  794. } // end Render_UpsideDwn_Mask_Bottom
  795.  
  796.  
  797. int Build_Object_Tables(char *file)
  798. {
  799.     // this function opens the input file and loads the OBJECT data from it
  800.  
  801.     FILE  *fp, *fopen();
  802.     int index,row,column,ob_num,gunner_num;
  803.     char buffer[WORLD_COLUMNS+2],ch;
  804.  
  805.     // allocate space for object lists...
  806.  
  807.     // init ob counter
  808.  
  809.     ob_num = 0;
  810.     gunner_num = 0;
  811.     // open the file
  812.  
  813.     if (!(fp = fopen(file,"r")))
  814.            return(0);
  815.  
  816.     // load in the data
  817.  
  818.     for (row=0; row<WORLD_ROWS; row++)
  819.     {
  820.         // load in the next row
  821.  
  822.         for (column=0; column<WORLD_COLUMNS; column++)
  823.         {
  824.  
  825.             while((ch = getc(fp))==10){} // filter out CR
  826.  
  827.             // translate character to integer
  828.  
  829.             if ((ch == '0') || (ch == '1') || (ch == '6'))
  830.             {
  831.                    ch = ch - '0';
  832.  
  833.                 initial_object_list[ob_num].x = (column<<CELL_X_SIZE_FP)+32;
  834.                 initial_object_list[ob_num].y = (((WORLD_ROWS-1) - row)<<CELL_Y_SIZE_FP)+32;
  835.                 initial_object_list[ob_num].angle = ANGLE_0;
  836.                 initial_object_list[ob_num].kind_of_object = ch;
  837.                 initial_object_list[ob_num].dist = 0;
  838.  
  839.                 ob_num++;
  840.             }
  841.  
  842.  
  843.         } // end for column
  844.  
  845.         // process the row
  846.  
  847.     } // end for row
  848.  
  849.     // close the file
  850.  
  851.     fclose(fp);
  852.  
  853.     if (!(fp = fopen(file,"r")))
  854.            return(0);
  855.  
  856.     // load in the data
  857.  
  858.     for (row=0; row<WORLD_ROWS; row++)
  859.     {
  860.         // load in the next row
  861.  
  862.         for (column=0; column<WORLD_COLUMNS; column++)
  863.         {
  864.  
  865.             while((ch = getc(fp))==10){} // filter out CR
  866.  
  867.             // translate character to integer
  868.  
  869.             if ((ch == '4') || (ch == '5'))
  870.             {
  871.                    ch = ch - '0';
  872.  
  873.                 initial_object_list[ob_num].x = (column<<CELL_X_SIZE_FP)+32;
  874.                 initial_object_list[ob_num].y = (((WORLD_ROWS-1) - row)<<CELL_Y_SIZE_FP)+32;
  875.                 initial_object_list[ob_num].angle = ANGLE_0;
  876.                 initial_object_list[ob_num].kind_of_object = ch;
  877.                 initial_object_list[ob_num].dist = 0;
  878.  
  879.                 ob_num++;
  880.             }
  881.  
  882.  
  883.         } // end for column
  884.  
  885.         // process the row
  886.  
  887.     } // end for row
  888.  
  889.     // close the file
  890.  
  891.     fclose(fp);
  892.  
  893.     Number_Of_Fixed_Objects = ob_num;
  894.  
  895.     ob_num = 0;
  896.  
  897.     if (!(fp = fopen(file,"r")))
  898.            return(0);
  899.  
  900.     // load in the data
  901.  
  902.     for (row=0; row<WORLD_ROWS; row++)
  903.     {
  904.         // load in the next row
  905.  
  906.         for (column=0; column<WORLD_COLUMNS; column++)
  907.         {
  908.  
  909.             while((ch = getc(fp))==10){} // filter out CR
  910.  
  911.             // translate character to integer
  912.  
  913.             if ((ch == '2') || (ch == '3'))
  914.             {
  915.                    ch = ch - '0';
  916.  
  917.                 enemies[ob_num].vitals.x = (column<<CELL_X_SIZE_FP)+32;
  918.                 enemies[ob_num].vitals.y = (((WORLD_ROWS-1) - row)<<CELL_Y_SIZE_FP)+32;
  919.                 enemies[ob_num].vitals.angle = ANGLE_0;
  920.                 enemies[ob_num].vitals.kind_of_object = ch;
  921.                 enemies[ob_num].vitals.dist = 0;
  922.                 enemies[ob_num].enem_num = ob_num;
  923.  
  924.                 enemies[ob_num].state = WAITING;
  925.                 enemies[ob_num].threshold = 0;
  926.                 enemies[ob_num].hit_points = 5;
  927.                 enemies[ob_num].pat_num = 0;
  928.  
  929.                 ob_num++;
  930.             }
  931.  
  932.  
  933.         } // end for column
  934.  
  935.         // process the row
  936.  
  937.     } // end for row
  938.  
  939.     // close the file
  940.  
  941.     fclose(fp);
  942.  
  943.     Number_Of_Enemies = ob_num;
  944.  
  945.     //return(1);
  946.  
  947. } // end Build_Object_Tables
  948.  
  949.  
  950. void Find_and_Maybe_Plot_Objects(objects any_object, int ID_Number, int threshold)
  951. {
  952.     long sub_view_left,sub_view_right;
  953.     long sub2_view_right;
  954.  
  955.     long relative_angle;
  956.      float diff_x,diff_y;
  957.      long temp_buffer_check;
  958.  
  959.      long buffer_check;
  960.  
  961.     int *scale_column;
  962.  
  963.     int i;
  964.     int indice;
  965.     int scale;
  966.  
  967.     long object_x, object_y, object_dist, object_angle;
  968.  
  969.      fixed scale_factor;
  970.      fixed planar_scale_factor;
  971.     fixed sprite_dist;
  972.     fixed adjusted_index;
  973.     int sprite_width,sprite_index,left,x_location;
  974.     int sprite_left,sprite_right;
  975.     int which_object;
  976.  
  977.     int sides_per_object = 8;
  978.     int angles_per_side = ANGLE_45;
  979.     static int temp_what_half = 0;
  980.  
  981.     int what_half;
  982.  
  983.     int pquad;
  984.     int oquad;
  985.     int j;
  986.  
  987. // beginning of function code
  988.  
  989.     object_x = any_object.x;
  990.     object_y = any_object.y;
  991.     object_dist = any_object.dist;
  992.     object_angle = any_object.angle;
  993.     which_object = any_object.kind_of_object;
  994.  
  995.     what_half = 0;
  996.  
  997.     diff_x = (x - object_x);
  998.     diff_y = (y - object_y);
  999.  
  1000.     if ((diff_x>1000) || (diff_x < -1000)) return;
  1001.  
  1002.     if ((diff_y>1000) || (diff_y < -1000)) return;
  1003.  
  1004.     sprite_dist = object_dist;
  1005.  
  1006.     if ((sprite_dist<(30)) || (sprite_dist>(1000))) return;
  1007.  
  1008.  
  1009.     if (diff_y == 0)
  1010.     {
  1011.         if (diff_x < 0)
  1012.             relative_angle = ANGLE_0;
  1013.         else
  1014.             relative_angle = ANGLE_180;
  1015.        }
  1016.     else
  1017.     if (diff_x == 0)
  1018.     {
  1019.         if (diff_y < 0)
  1020.             relative_angle = ANGLE_90;
  1021.         else
  1022.             relative_angle = ANGLE_270;
  1023.     }
  1024.     else
  1025.     {
  1026.         if (diff_x < 0) diff_x = diff_x *-1;
  1027.         if (diff_y < 0) diff_y = diff_y *-1;
  1028.  
  1029.         relative_angle = (long)((atan((double)diff_y/(double)diff_x))*(RAD_TO_DEG));
  1030.  
  1031.         diff_x = (x - object_x);
  1032.         diff_y = (y - object_y);
  1033.  
  1034.         if (diff_x > 0)
  1035.         {
  1036.             if(diff_y > 0)
  1037.                 relative_angle = ANGLE_180 + relative_angle;
  1038.             else
  1039.             if(diff_y < 0)
  1040.                 relative_angle = ANGLE_180 - relative_angle;
  1041.         }
  1042.         else
  1043.         if (diff_x < 0)
  1044.         {
  1045.             if(diff_y > 0)
  1046.                 relative_angle = ANGLE_360 - relative_angle;
  1047.  
  1048.         }
  1049.     }
  1050.  
  1051.     sub_view_left = view_angle + HALF_VIEW_CONE + ANGLE_5;
  1052.     sub_view_right = view_angle - HALF_VIEW_CONE - ANGLE_5;
  1053.     sub2_view_right = view_angle - HALF_VIEW_CONE;
  1054.  
  1055.        // Adjust angles, because around view_angle 0 things
  1056.        // get tricky...
  1057.  
  1058.     if (sub2_view_right<ANGLE_5)
  1059.     {
  1060.         sub2_view_right += ANGLE_360;
  1061.     }
  1062.  
  1063.     if (sub_view_left>ANGLE_360) sub_view_left -= ANGLE_360;
  1064.  
  1065.     if (sub_view_right<ANGLE_0)
  1066.     {
  1067.         sub_view_right += ANGLE_360;
  1068.     }
  1069.     if (sub_view_left>ANGLE_360) sub_view_left -= ANGLE_360;
  1070.  
  1071.     if (sub_view_right<ANGLE_0)
  1072.     {
  1073.         sub_view_right += ANGLE_360;
  1074.     }
  1075.     if (sub_view_right > sub_view_left)    // If looking towards the right
  1076.     {
  1077.         if (relative_angle >= sub_view_right)  // Cal. view column of object
  1078.             buffer_check = relative_angle - sub2_view_right;
  1079.         else
  1080.             buffer_check = (relative_angle+ANGLE_360) - sub2_view_right;
  1081.     }
  1082.     else
  1083.     {
  1084.         buffer_check = relative_angle - sub2_view_right; // Calc. view column of object
  1085.     }
  1086.  
  1087.  
  1088. //    if ((buffer_check < ANGLE_0) || (buffer_check > ANGLE_60)) return;
  1089.     if (buffer_check < ANGLE_0)
  1090.         scale=(int)(cos_table[ANGLE_0]/(sprite_dist))>>1;
  1091.     else
  1092.     if (buffer_check > VIEW_CONE)
  1093.         scale=(int)(cos_table[VIEW_CONE]/(sprite_dist))>>1;
  1094.     else
  1095.         scale=(int)(cos_table[buffer_check]/(sprite_dist))>>1;
  1096.  
  1097.  
  1098.     sprite_width = scale*obj_statistic_list[which_object].width_factor;
  1099.  
  1100.     scale_factor = (obj_statistic_list[which_object].Scale_Factor)/((fixed)sprite_width);
  1101.     planar_scale_factor = scale_factor<<2;
  1102.  
  1103.     left = COLUMN_OFFSET-(buffer_check);
  1104.  
  1105.     if (scale>(MAX_SCALE-1))
  1106.         scale=(MAX_SCALE-1);
  1107.  
  1108.     scale_row      = scale_table[scale-1];
  1109.     scale_column   = scale_table[sprite_width-1];
  1110.  
  1111.     if (scale>(WINDOW_HALF_HEIGHT))
  1112.     {
  1113.         scale=(WINDOW_HALF_HEIGHT);
  1114.     }
  1115.  
  1116.     sliver_scale   = scale-1;
  1117.  
  1118.     // set up parameters for assembly language
  1119.  
  1120.     switch(which_object)
  1121.     {
  1122.         case 0:
  1123.         {
  1124.             sliver_texture = ob_frames.frames[0];
  1125.             rend_func_ptr = Render_Sliver_Mask;
  1126.         }
  1127.         break;
  1128.  
  1129.         case 1:
  1130.         {
  1131.             sliver_texture = ob_frames.frames[1];
  1132.             rend_func_ptr = Render_Sliver_Mask_Special;
  1133.         }
  1134.         break;
  1135.  
  1136.         case 2:
  1137.         {
  1138.             if (enemies[ID_Number].state == FIRING)
  1139.             {
  1140.                 sliver_texture = duck_frames.frames[8];
  1141.             }
  1142.             else
  1143.             if (enemies[ID_Number].state == HIT)
  1144.             {
  1145.                 sliver_texture = duck_frames.frames[10];
  1146.             }
  1147.             else
  1148.             if (enemies[ID_Number].state == DEAD)
  1149.             {
  1150.                 sliver_texture = duck_frames.frames[9];
  1151.             }
  1152.             else
  1153.             if (enemies[ID_Number].state == DYING)
  1154.             {
  1155.                    sliver_texture = duck_death.frames[(7-threshold)/2];
  1156.  
  1157.                 what_half = (7-threshold) % 2;
  1158.             }
  1159.             else
  1160.             {
  1161.                 pquad = (relative_angle+ANGLE_23)/angles_per_side;
  1162.                 oquad = (object_angle+ANGLE_23)/angles_per_side;
  1163.                 j = (pquad - oquad)+(sides_per_object>>1);
  1164.  
  1165.                 if (j >= sides_per_object)
  1166.                     j -= sides_per_object;
  1167.  
  1168.                 if (j < 0)
  1169.                     j += sides_per_object;
  1170.  
  1171.                 sliver_texture = duck_frames.frames[j];
  1172.  
  1173.             }
  1174.  
  1175.             rend_func_ptr = Render_Sliver_Mask_Just_Bottom;
  1176.  
  1177.         }
  1178.         break;
  1179.  
  1180.         case 3:
  1181.         {
  1182.             if (enemies[ID_Number].state == FIRING)
  1183.             {
  1184.                 sliver_texture = duck_frames.frames[8];
  1185.             }
  1186.             else
  1187.             if (enemies[ID_Number].state == HIT)
  1188.             {
  1189.                 sliver_texture = duck_frames.frames[10];
  1190.             }
  1191.             else
  1192.             if (enemies[ID_Number].state == DEAD)
  1193.             {
  1194.                 sliver_texture = duck_frames.frames[9];
  1195.             }
  1196.             else
  1197.             if (enemies[ID_Number].state == DYING)
  1198.             {
  1199.                    sliver_texture = duck_death.frames[(7-threshold)/2];
  1200.  
  1201.                 what_half = (7-threshold) % 2;
  1202.             }
  1203.             else
  1204.             {
  1205.                 pquad = (relative_angle+ANGLE_23)/angles_per_side;
  1206.                 oquad = (object_angle+ANGLE_23)/angles_per_side;
  1207.                 j = (pquad - oquad)+(sides_per_object>>1);
  1208.  
  1209.                 if (j >= sides_per_object)
  1210.                     j -= sides_per_object;
  1211.  
  1212.                 if (j < 0)
  1213.                     j += sides_per_object;
  1214.  
  1215.                 sliver_texture = duck_frames.frames[j];
  1216.  
  1217.             }
  1218.  
  1219.             rend_func_ptr = Render_UpsideDwn_Mask_Bottom;
  1220.         }
  1221.         break;
  1222.  
  1223.  
  1224.         case 4:
  1225.         {
  1226.             sliver_texture = ob_frames.frames[2];
  1227.             rend_func_ptr = Render_Sliver_Mask_Just_Bottom;
  1228.         }
  1229.         break;
  1230.  
  1231.         case 5:
  1232.         {
  1233.             sliver_texture = ob_frames.frames[3];
  1234.             rend_func_ptr = Render_Sliver_Mask_Just_Bottom;
  1235.         }
  1236.         break;
  1237.  
  1238.         case 6:
  1239.         {
  1240.              sliver_texture = ob_frames.frames[4];
  1241.             rend_func_ptr = Render_Sliver_Mask_Just_Bottom;
  1242.         }
  1243.         break;
  1244.  
  1245.     }
  1246.  
  1247.     sprite_left = left+(sprite_width>>1);
  1248.     sprite_right = sprite_left-sprite_width;
  1249.  
  1250.     sliver_column = 0;
  1251.  
  1252.     adjusted_index = 0;
  1253.     sliver_top     = WINDOW_MIDDLE - (scale >> 1);
  1254.  
  1255.     buffer_check = buffer_check - (sprite_width>>1);
  1256.  
  1257.     temp_buffer_check = buffer_check;
  1258.  
  1259.     _asm
  1260.     {
  1261.         mov dx,SEQUENCER          // address the sequencer
  1262.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  1263.         mov cl,BYTE PTR sprite_left // extract lower byte from x
  1264.         and cl,03h                // extract the plane number = x MOD 4
  1265.         mov ah,1                  // a "1" selects the plane in the plane enable
  1266.         shl ah,cl                 // shift the "1" bit proper number of times
  1267.         out dx,ax                 // do it baby!
  1268.     }
  1269.  
  1270.     for (sprite_index = sprite_left; sprite_index > sprite_right; sprite_index-=4)
  1271.     {
  1272.         if ((temp_buffer_check >= ANGLE_0) && (temp_buffer_check < VIEW_CONE))
  1273.         {
  1274.             if (sprite_dist < vz_buffer[temp_buffer_check])
  1275.             {
  1276.  
  1277.                 sliver_column = (what_half<<5) + adjusted_index>>16;
  1278.  
  1279.                 sliver_ray     = sprite_index;
  1280.  
  1281.                                 // render the sliver in assembly
  1282.  
  1283.                 (*rend_func_ptr) ();
  1284.             }
  1285.         }
  1286.  
  1287.         temp_buffer_check+=4;
  1288.         adjusted_index+=planar_scale_factor;
  1289.     }
  1290.  
  1291.     temp_buffer_check = buffer_check+1;
  1292.     sprite_left -= 1;
  1293.     adjusted_index = scale_factor;
  1294.  
  1295.     _asm
  1296.     {
  1297.         mov dx,SEQUENCER          // address the sequencer
  1298.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  1299.         mov cl,BYTE PTR sprite_left // extract lower byte from x
  1300.         and cl,03h                // extract the plane number = x MOD 4
  1301.         mov ah,1                  // a "1" selects the plane in the plane enable
  1302.         shl ah,cl                 // shift the "1" bit proper number of times
  1303.         out dx,ax                 // do it baby!
  1304.     }
  1305.  
  1306.     for (sprite_index = sprite_left; sprite_index > sprite_right; sprite_index-=4)
  1307.     {
  1308.         if ((temp_buffer_check >= ANGLE_0) && (temp_buffer_check < VIEW_CONE))
  1309.         {
  1310.             if (sprite_dist < vz_buffer[temp_buffer_check])
  1311.             {
  1312.  
  1313.                 sliver_column = (what_half<<5) + adjusted_index>>16;
  1314.  
  1315.                 sliver_ray     = sprite_index;
  1316.  
  1317.                                 // render the sliver in assembly
  1318.  
  1319.                 (*rend_func_ptr) ();
  1320.             }
  1321.         }
  1322.  
  1323.         temp_buffer_check+=4;
  1324.         adjusted_index+=planar_scale_factor;
  1325.     }
  1326.  
  1327.     temp_buffer_check = buffer_check+2;
  1328.     sprite_left -= 1;
  1329.     adjusted_index = scale_factor<<1;
  1330.  
  1331.     _asm
  1332.     {
  1333.         mov dx,SEQUENCER          // address the sequencer
  1334.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  1335.         mov cl,BYTE PTR sprite_left // extract lower byte from x
  1336.         and cl,03h                // extract the plane number = x MOD 4
  1337.         mov ah,1                  // a "1" selects the plane in the plane enable
  1338.         shl ah,cl                 // shift the "1" bit proper number of times
  1339.         out dx,ax                 // do it baby!
  1340.     }
  1341.  
  1342.     for (sprite_index = sprite_left; sprite_index > sprite_right; sprite_index-=4)
  1343.     {
  1344.         if ((temp_buffer_check >= ANGLE_0) && (temp_buffer_check < VIEW_CONE))
  1345.         {
  1346.             if (sprite_dist < vz_buffer[temp_buffer_check])
  1347.             {
  1348.  
  1349.                 sliver_column = (what_half<<5) + adjusted_index>>16;
  1350.  
  1351.                 sliver_ray     = sprite_index;
  1352.  
  1353.                                 // render the sliver in assembly
  1354.  
  1355.                 (*rend_func_ptr) ();
  1356.             }
  1357.         }
  1358.  
  1359.         temp_buffer_check+=4;
  1360.         adjusted_index+=planar_scale_factor;
  1361.     }
  1362.  
  1363.     temp_buffer_check = buffer_check+3;
  1364.     sprite_left -= 1;
  1365.     adjusted_index = scale_factor<<1;
  1366.     adjusted_index += scale_factor;
  1367.  
  1368.     _asm
  1369.     {
  1370.         mov dx,SEQUENCER          // address the sequencer
  1371.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  1372.         mov cl,BYTE PTR sprite_left // extract lower byte from x
  1373.         and cl,03h                // extract the plane number = x MOD 4
  1374.         mov ah,1                  // a "1" selects the plane in the plane enable
  1375.         shl ah,cl                 // shift the "1" bit proper number of times
  1376.         out dx,ax                 // do it baby!
  1377.     }
  1378.  
  1379.     for (sprite_index = sprite_left; sprite_index > sprite_right; sprite_index-=4)
  1380.     {
  1381.         if ((temp_buffer_check >= ANGLE_0) && (temp_buffer_check < VIEW_CONE))
  1382.         {
  1383.             if (sprite_dist < vz_buffer[temp_buffer_check])
  1384.             {
  1385.  
  1386.                 sliver_column = (what_half<<5) + adjusted_index>>16;
  1387.  
  1388.                 sliver_ray     = sprite_index;
  1389.  
  1390.                                 // render the sliver in assembly
  1391.  
  1392.                 (*rend_func_ptr) ();
  1393.             }
  1394.         }
  1395.  
  1396.         temp_buffer_check+=4;
  1397.         adjusted_index+=planar_scale_factor;
  1398.     }
  1399.  
  1400.  
  1401. }  // END FIND AND MAYBE PLOT OBJECTS
  1402.  
  1403. void Make_Light_Metallic_Blue_Palette(void)
  1404. {
  1405.     // this function generates 64 shades of Light_Metallic_Blue and places them in the palette
  1406.     // at locations 16 to 80
  1407.  
  1408.     int index;
  1409.  
  1410.     RGB_color color;
  1411.  
  1412.     // generate 64 shades of Light_Metallic_Blue
  1413.  
  1414.     for (index = 0; index < 40; index++)
  1415.     {
  1416.         color.red   = 0;
  1417.         color.green = index;
  1418.         color.blue  = index;
  1419.  
  1420.         old_all[16+index] = color;
  1421.  
  1422.         // write the color in the palette starting at location 16, so as not to
  1423.         // fry the EGA palette
  1424.  
  1425.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1426.     }
  1427. } // end Make_Light_Metallic_Blue_Palette
  1428.  
  1429. void Make_Gold_Palette(void)
  1430. {
  1431.     // this function generates 64 shades of gold and places them in the palette
  1432.     // at locations 16 to 80
  1433.  
  1434.     int index;
  1435.  
  1436.     RGB_color color;
  1437.  
  1438.     // generate 64 shades of gold
  1439.  
  1440.     for (index = 0; index < 40; index++)
  1441.     {
  1442.         color.red   = index;
  1443.         color.green = index;
  1444.         color.blue  = 0;
  1445.  
  1446.         old_all[16+index] = color;
  1447.  
  1448.         // write the color in the palette starting at location 16, so as not to
  1449.         // fry the EGA palette
  1450.  
  1451.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1452.     }
  1453. } // end Make_Gold_Palette
  1454.  
  1455. void Make_Gray_Palette(void)
  1456. {
  1457.     // this function generates 64 shades of gray and places them in the palette
  1458.     // at locations 16 to 80
  1459.  
  1460.     int index;
  1461.  
  1462.     RGB_color color;
  1463.  
  1464.     // generate 64 shades of gray
  1465.  
  1466.     for (index = 0; index < 40; index++)
  1467.     {
  1468.         color.red   = index;
  1469.         color.green = index;
  1470.         color.blue  = index;
  1471.  
  1472.         old_all[16+index] = color;
  1473.  
  1474.         // write the color in the palette starting at location 16, so as not to
  1475.         // fry the EGA palette
  1476.  
  1477.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1478.     }
  1479. } // end Make_Gold_Palette
  1480.  
  1481. void Make_Blue_Palette(void)
  1482. {
  1483.     // this function generates 64 shades of gray and places them in the palette
  1484.     // at locations 16 to 80
  1485.  
  1486.     int index;
  1487.  
  1488.     RGB_color color;
  1489.  
  1490.     // generate 64 shades of gray
  1491.  
  1492.     for (index = 0; index < 64; index++)
  1493.     {
  1494.         color.red   = 0;
  1495.         color.green = 0;
  1496.         color.blue  = index;
  1497.  
  1498.         old_all[16+index] = color;
  1499.  
  1500.         // write the color in the palette starting at location 16, so as not to
  1501.         // fry the EGA palette
  1502.  
  1503.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1504.     }
  1505. } // end Make_Gold_Palette
  1506.  
  1507. void Make_Gray_Palette_OAAT(int delta, int erase_trail)
  1508. {
  1509.     // this function generates 64 shades of gray and places them in the palette
  1510.     // at locations 16 to 80
  1511.  
  1512.     int index;
  1513.  
  1514.     RGB_color color;
  1515.  
  1516.     // generate 64 shades of gray
  1517.  
  1518.     index = delta;
  1519.  
  1520.     color.red   = index;
  1521.     color.green = index;
  1522.     color.blue  = index;
  1523.  
  1524.     old_all[16+index] = color;
  1525.  
  1526.     // write the color in the palette starting at location 16, so as not to
  1527.     // fry the EGA palette
  1528.  
  1529.     Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1530.  
  1531. } // end Make_Gray_Palette_OAAT
  1532.  
  1533. void Make_Blue_Palette_OAAT(int delta, int erase_trail)
  1534. {
  1535.     // this function generates 64 shades of gray and places them in the palette
  1536.     // at locations 16 to 80
  1537.  
  1538.     int index;
  1539.  
  1540.     RGB_color color;
  1541.  
  1542.     // generate 64 shades of gray
  1543.  
  1544.     index = delta;
  1545.  
  1546.     // gray equals equal percentage of Red, Green and Blue
  1547.  
  1548.     if (index!=39)
  1549.     {
  1550.         color.red   = 0;
  1551.         color.green = 0;
  1552.         color.blue  = index;
  1553.  
  1554.         old_all[16+index] = color;
  1555.  
  1556.         // write the color in the palette starting at location 16, so as not to
  1557.         // fry the EGA palette
  1558.  
  1559.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1560.     }
  1561.  
  1562.     if ((index!=0) && (erase_trail))
  1563.     {
  1564.         --index;
  1565.  
  1566.         color.red   = index;
  1567.         color.green = index;
  1568.         color.blue  = index;
  1569.  
  1570.         old_all[16+index] = color;
  1571.  
  1572.         // write the color in the palette starting at location 16, so as not to
  1573.         // fry the EGA palette
  1574.  
  1575.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1576.  
  1577.     }
  1578.  
  1579. } // end Make_Blue_Palette_OAAT
  1580.  
  1581. void Make_Gold_Palette_OAAT(int delta, int erase_trail)
  1582. {
  1583.     // this function generates 64 shades of gray and places them in the palette
  1584.     // at locations 16 to 80
  1585.  
  1586.     int index;
  1587.  
  1588.     RGB_color color;
  1589.  
  1590.     // generate 64 shades of gray
  1591.  
  1592.     index = delta;
  1593.  
  1594.     if (index!=39)
  1595.     {
  1596.         // gray equals equal percentage of Red, Green and Blue
  1597.  
  1598.         color.red   = 0;
  1599.         color.green = index;
  1600.         color.blue  = index;
  1601.  
  1602.         old_all[16+index] = color;
  1603.  
  1604.         // write the color in the palette starting at location 16, so as not to
  1605.         // fry the EGA palette
  1606.  
  1607.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1608.     }
  1609.  
  1610.     if ((index!=0) && (erase_trail))
  1611.     {
  1612.         --index;
  1613.  
  1614.         color.red   = index;
  1615.         color.green = index;
  1616.         color.blue  = index;
  1617.  
  1618.         old_all[16+index] = color;
  1619.  
  1620.         // write the color in the palette starting at location 16, so as not to
  1621.         // fry the EGA palette
  1622.  
  1623.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1624.  
  1625.     }
  1626.  
  1627. } // end Make_Gold_Palette_OAAT
  1628.  
  1629. void Make_Cyan_Palette_OAAT(int delta, int erase_trail)
  1630. {
  1631.     // this function generates 64 shades of gray and places them in the palette
  1632.     // at locations 16 to 80
  1633.  
  1634.     int index;
  1635.  
  1636.     RGB_color color;
  1637.  
  1638.     index = delta;
  1639.     // generate 64 shades of gray
  1640.     if (index!=39)
  1641.     {
  1642.  
  1643.         // gray equals equal percentage of Red, Green and Blue
  1644.  
  1645.         color.red   = index;
  1646.         color.green = index;
  1647.         color.blue  = 0;
  1648.  
  1649.         old_all[16+index] = color;
  1650.  
  1651.         // write the color in the palette starting at location 16, so as not to
  1652.         // fry the EGA palette
  1653.  
  1654.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1655.     }
  1656.  
  1657.     if ((index!=0) && (erase_trail))
  1658.     {
  1659.         --index;
  1660.  
  1661.         color.red   = index;
  1662.         color.green = index;
  1663.         color.blue  = index;
  1664.  
  1665.         old_all[16+index] = color;
  1666.  
  1667.         // write the color in the palette starting at location 16, so as not to
  1668.         // fry the EGA palette
  1669.  
  1670.         Write_Color_Reg(16+index,(RGB_color_ptr)&color);
  1671.  
  1672.     }
  1673.  
  1674. } // end Make_Cyan_Palette_OAAT
  1675.  
  1676.  
  1677. void Process_Doors(void)
  1678. {
  1679.     // Checks the list of doors, and processes them if they are
  1680.     // OPENING, OPEN, OR CLOSING
  1681.  
  1682.     int cells_x,cells_y,row,column;
  1683.     int index = total_world_doors;
  1684.     int enem_index;
  1685.     int in_the_doorway = 0;
  1686.     int x_player,y_player;
  1687.     int x_cell_d,y_cell_d;
  1688.     int processed_doors;
  1689.  
  1690.     // you might want to put the active doors in a linked list...
  1691.     // but I did it this way, because there aren't many doors per map
  1692.     // ALOT OF THE THINGS I DO HERE ARE DOPEY!
  1693.  
  1694.     for (index = 0; index < total_world_doors; index++)
  1695.     {
  1696.         // get the x & y map coordinates for the door
  1697.  
  1698.         x_cell_d = doors[index].door_x;
  1699.         y_cell_d = doors[index].door_y;
  1700.  
  1701.         if (doors[index].door_state != CLOSED)
  1702.         {
  1703.             if (doors[index].door_state == OPENING)
  1704.             {
  1705.                   // open the door some more...
  1706.  
  1707.                   doors[index].door_increment+=6;
  1708.  
  1709.                 // when the door is all the way open - STOP OPENING IT!
  1710.  
  1711.                   if (doors[index].door_increment > 64)
  1712.                   {
  1713.                        // this holds the door open a little while...
  1714.  
  1715.                        doors[index].door_wait_to_close = 80;
  1716.  
  1717.                        // this simply ensures the door is set open
  1718.  
  1719.                        doors[index].door_increment = 64;
  1720.  
  1721.                        // Take the door out of the world map... so that
  1722.                        // the rendering engine can ignore it completely
  1723.                        // (not the smartest way...)
  1724.  
  1725.                       world[y_cell_d][x_cell_d].block_type = 0;
  1726.  
  1727.                       // Allow the player to pass through the vacant doorway
  1728.  
  1729.                     Block_Map[y_cell_d][x_cell_d] = 0;
  1730.  
  1731.                     // set door state to OPEN
  1732.  
  1733.                        doors[index].door_state = OPEN;
  1734.                   }
  1735.                }
  1736.             else
  1737.             if (doors[index].door_state == CLOSING)
  1738.             {
  1739.                 // close the door some more...
  1740.  
  1741.                   doors[index].door_increment-=6;
  1742.  
  1743.                   if (doors[index].door_increment < 0)  // is it all the way
  1744.                   {                                     // closed?
  1745.                       doors[index].door_state = CLOSED;
  1746.                       doors[index].door_increment = 0;
  1747.                   }
  1748.                }
  1749.             else
  1750.             if (doors[index].door_state == OPEN)
  1751.             {
  1752.                   doors[index].door_wait_to_close--; // countdown to closing...
  1753.  
  1754.                   if (doors[index].door_wait_to_close < 0)
  1755.                   {
  1756.                       in_the_doorway = 0;
  1757.  
  1758.                       x_player = x / CELL_X_SIZE;
  1759.                       y_player = y / CELL_Y_SIZE;
  1760.  
  1761.                     // is the player in the doorway?
  1762.  
  1763.                       if ((y_player == (y_cell_d)) &&   // NOPE!
  1764.                           (x_player == x_cell_d))
  1765.                           in_the_doorway = 1;
  1766.  
  1767.                       if (!in_the_doorway)
  1768.                       {
  1769.                           for (enem_index=0; enem_index <= Number_Of_Enemies; enem_index++)
  1770.                           {
  1771.                             if(!in_the_doorway)
  1772.                             {
  1773.                                 x_player = enemies[enem_index].vitals.x / CELL_X_SIZE;
  1774.                                 y_player = enemies[enem_index].vitals.y / CELL_Y_SIZE;
  1775.  
  1776.                                   if ((y_player == (y_cell_d)) &&   // NOPE!
  1777.                                       (x_player == x_cell_d))
  1778.                                       in_the_doorway = 1;
  1779.                               }
  1780.                           }
  1781.                       }
  1782.  
  1783.                       if (!in_the_doorway)
  1784.                       {
  1785.                           // put door back into the world map
  1786.  
  1787.                           world[y_cell_d][x_cell_d].block_type=
  1788.                               doors[index].door_block_type;
  1789.  
  1790.                         // make block impassable
  1791.  
  1792.                         Block_Map[y_cell_d][x_cell_d] = 1;
  1793.  
  1794.                         // the door is closing
  1795.  
  1796.                           doors[index].door_state = CLOSING;
  1797.                           doors[index].door_wait_to_close = 0;
  1798.                       }
  1799.                       else
  1800.                       {
  1801.                           doors[index].door_state = OPEN;
  1802.                           doors[index].door_wait_to_close = 10;
  1803.                       }
  1804.                   }
  1805.                }
  1806.         }
  1807.     } // end while
  1808.  
  1809. } // end Process_Doors
  1810.  
  1811.  
  1812. void Create_Scale_Data(int scaler, int *row)
  1813. {
  1814.  
  1815. // this function synthesizes the scaling of a texture sliver to all possible
  1816. // sizes and creates a huge look up table of the data.
  1817.  
  1818. int y_off;
  1819.  
  1820. float y_scale_index=0,
  1821.       y_scale_step;
  1822.  
  1823. // compute scale step or number of source pixels to map to destination/cycle
  1824.  
  1825. y_scale_step = (float)32/(float)scaler;
  1826.  
  1827. y_scale_index+=y_scale_step;
  1828.  
  1829. for (y_off=0; y_off<scaler; y_off++)
  1830.     {
  1831.     // place data into proper array position for later use
  1832.  
  1833.     row[y_off] = ((int)(y_scale_index+.4)) * SWATCH_WIDTH;
  1834.  
  1835.     // test if we slightly went overboard
  1836.  
  1837.     if  (row[y_off] > WALL_MIDDLE_OFFSET) row[y_off] = WALL_MIDDLE_OFFSET;
  1838.  
  1839.     // next index please
  1840.  
  1841.     y_scale_index+=y_scale_step;
  1842.  
  1843.     } // end for y_off
  1844.  
  1845. } // end Create_Scale_Data
  1846.  
  1847. void Create_Scale_Data2(int scaler, int *row)
  1848. {
  1849.  
  1850. // this function synthesizes the scaling of a texture sliver to all possible
  1851. // sizes and creates a huge look up table of the data.
  1852.  
  1853. // this adds data for cases where the vertical extents of the "sliver" are
  1854. // beyond the vertical extents of the viewport
  1855.  
  1856. int y_off;
  1857.  
  1858. float y_scale_index=0,
  1859.       y_scale_step;
  1860.  
  1861. // compute scale step or number of source pixels to map to destination/cycle
  1862.  
  1863. y_scale_step = (float)32/(float)scaler;
  1864.  
  1865. y_scale_index+=y_scale_step;
  1866.  
  1867. for (y_off=0; y_off<WINDOW_HALF_HEIGHT+1; y_off++)
  1868.     {
  1869.     // place data into proper array position for later use
  1870.  
  1871.     row[y_off] = ((int)(y_scale_index+.4)) * SWATCH_WIDTH;
  1872.  
  1873.     // test if we slightly went overboard
  1874.  
  1875.     if  (row[y_off] > WALL_MIDDLE_OFFSET) row[y_off] = WALL_MIDDLE_OFFSET;
  1876.  
  1877.     // next index please
  1878.  
  1879.     y_scale_index+=y_scale_step;
  1880.  
  1881.     } // end for y_off
  1882.  
  1883. } // end Create_Scale_Data2
  1884.  
  1885. void Build_Tables(void)
  1886. {
  1887.  
  1888.     // this function builds all the look up tables for the system
  1889.  
  1890.     // the ANGLE_?s are assigned values here because I wanted to make the
  1891.     // viewport resizable(!?) (probably not the best way)
  1892.  
  1893.     int ang,scale;
  1894.     float rad_angle;
  1895.  
  1896.     ANGLE_360=    my_size;
  1897.  
  1898.     ANGLE_180=    (ANGLE_360>>1);
  1899.     ANGLE_90=    (ANGLE_360>>2);
  1900.     ANGLE_75=   (ANGLE_360/4.8);
  1901.     ANGLE_60=    (ANGLE_360/6);
  1902.     ANGLE_45=    (ANGLE_360/8);
  1903.     ANGLE_30=    (ANGLE_360/12);
  1904.     ANGLE_15=    (ANGLE_360/24);
  1905.     ANGLE_6=    (ANGLE_360/60);
  1906.     ANGLE_5=    (ANGLE_360/72);
  1907.     ANGLE_4=    (ANGLE_360/90);
  1908.     ANGLE_2=    (ANGLE_360/180);
  1909.     ANGLE_1=    (ANGLE_360/360);
  1910.     ANGLE_0=    0;
  1911.  
  1912. // some ODDBALL angles
  1913.  
  1914.     ANGLE_315=    (ANGLE_360-ANGLE_45);
  1915.     ANGLE_270=    (ANGLE_360-ANGLE_90);
  1916.     ANGLE_225=    (ANGLE_270-ANGLE_45);
  1917.     ANGLE_135=    (ANGLE_180-ANGLE_45);
  1918.     ANGLE_10= (ANGLE_5+ANGLE_5);
  1919.     ANGLE_9= (ANGLE_5+ANGLE_4);
  1920.     ANGLE_8= (ANGLE_4+ANGLE_4);
  1921.     ANGLE_7= (ANGLE_8-ANGLE_1);
  1922.                                   //... and some possible 'view cones'...
  1923.     ANGLE_80 = (ANGLE_90-ANGLE_10);
  1924.     ANGLE_70 = (ANGLE_60+ANGLE_10);
  1925.  
  1926. // for 'shifting the parachute' (?!)
  1927.  
  1928.     ANGLE_23=    (ANGLE_15 + ANGLE_5 + ANGLE_2 + ANGLE_1);
  1929.  
  1930. // VIEW CONE VALUES...
  1931.  
  1932.     VIEW_CONE = ANGLE_90;
  1933.     HALF_VIEW_CONE = (VIEW_CONE>>1);
  1934.  
  1935. // conversion constants from radians to degrees and vice-versa
  1936.  
  1937.     ANGULAR_INCREMENT =((float)360/(float)ANGLE_360);
  1938.     RAD_TO_DEG = (((float)180/(float)ANGULAR_INCREMENT)/(float)3.1415926);
  1939.  
  1940.      WINDOW_HEIGHT=         my_height;
  1941.  
  1942.     WINDOW_HALF_HEIGHT=    (WINDOW_HEIGHT>>1);
  1943.  
  1944.     WINDOW_MIDDLE=         79;
  1945.  
  1946.     WINDOW_MIDDLE_MINUS=   78;
  1947.  
  1948.     WINDOW_TOP=              WINDOW_MIDDLE-WINDOW_HALF_HEIGHT+1;
  1949.     WINDOW_BOTTOM=         WINDOW_MIDDLE+WINDOW_HALF_HEIGHT-1;
  1950.     WINDOW_LEFT=              my_left;
  1951.     WINDOW_RIGHT=          my_right;
  1952.  
  1953.     VERTICAL_SCALE=        my_v_scale;     // used to scale the "slivers" to get proper
  1954.  
  1955. // allocate memory for all look up tables
  1956.  
  1957.     // tangent tables equivalent to slopes
  1958.  
  1959.     tan_table     = (float far *)_fmalloc(sizeof(float) * (ANGLE_360+1) );
  1960.     inv_tan_table = (float far *)_fmalloc(sizeof(float) * (ANGLE_360+1) );
  1961.  
  1962.     // step tables used to find next intersections, equivalent to slopes
  1963.     // times width and height of cell
  1964.  
  1965.     y_step        = (float far *)_fmalloc(sizeof(float) * (ANGLE_360+1) );
  1966.     x_step        = (float far *)_fmalloc(sizeof(float) * (ANGLE_360+1) );
  1967.  
  1968.  
  1969.     // cos table used to fix view distortion caused by caused by radial projection
  1970.  
  1971.     cos_table     = (float far *)_fmalloc(sizeof(float) * (VIEW_CONE+1) );
  1972.  
  1973.  
  1974.     // 1/cos and 1/sin tables used to compute distance of intersection very
  1975.     // quickly
  1976.  
  1977.     inv_cos_table = (float far *)_fmalloc(sizeof(float) * (ANGLE_360+1) );
  1978.     inv_sin_table = (float far *)_fmalloc(sizeof(float) * (ANGLE_360+1) );
  1979.  
  1980. // create the lookup tables for the scaler
  1981. // there have the form of an array of pointers, where each pointer points
  1982. // another another array of data where the 'data' are the scale indices
  1983.  
  1984.     for (scale=0; scale<=WINDOW_HALF_HEIGHT; scale++)
  1985.     {
  1986.  
  1987.     scale_table[scale] = (int *)malloc(scale*sizeof(int)+1);
  1988.  
  1989.     } // end for scale
  1990.     for (scale=WINDOW_HALF_HEIGHT+1; scale<=MAX_SCALE; scale++)
  1991.     {
  1992.  
  1993.     scale_table[scale] = (int *)malloc((WINDOW_HALF_HEIGHT+1)*sizeof(int)+1);
  1994.  
  1995.     } // end for scale
  1996.  
  1997.     // create tables, sit back for a sec!
  1998.  
  1999.     for (ang=ANGLE_0; ang<=ANGLE_360; ang++)
  2000.     {
  2001.  
  2002.         rad_angle = (float)((3.272e-4) + ang * 2*3.141592654/ANGLE_360);
  2003.  
  2004.         tan_table[ang]     = (float)tan(rad_angle);
  2005.         inv_tan_table[ang] = (float)(1/tan_table[ang]);
  2006.  
  2007.  
  2008.         // tangent has the incorrect signs in all quadrants except 1, so
  2009.         // manually fix the signs of each quadrant since the tangent is
  2010.         // equivalent to the slope of a line and if the tangent is wrong
  2011.         // then the ray that is case will be wrong
  2012.  
  2013.         if (ang>=ANGLE_0 && ang<ANGLE_180)
  2014.            {
  2015.                y_step[ang]        = (float)(fabs(tan_table[ang]  * CELL_Y_SIZE));
  2016.            }
  2017.         else
  2018.                y_step[ang]        = (float)(-fabs(tan_table[ang] * CELL_Y_SIZE));
  2019.  
  2020.         if (ang>=ANGLE_90 && ang<ANGLE_270)
  2021.            {
  2022.                x_step[ang]        = (float)(-fabs(inv_tan_table[ang] * CELL_X_SIZE));
  2023.            }
  2024.         else
  2025.            {
  2026.                x_step[ang]        = (float)(fabs(inv_tan_table[ang]  * CELL_X_SIZE));
  2027.            }
  2028.  
  2029.  
  2030.         // create the sin and cosine tables to copute distances
  2031.  
  2032.         inv_cos_table[ang] = (float)(1/cos(rad_angle));
  2033.         inv_sin_table[ang] = (float)(1/sin(rad_angle));
  2034.  
  2035.     } // end for ang
  2036.  
  2037. ///////////////////////////////////////////////////////
  2038.  
  2039. // THE FOLLOWING LINES ARE THE FOSSILIZED REMAINS OF WHAT I NEED TO
  2040. // DO WHEN I IMPLEMENTED FIXED POINT MATH, W/ LONG INTEGERS FOR VALUES
  2041. // IN THE LOOKUP TABLES
  2042.  
  2043. ///////////////////////////////////////////////////////
  2044.  
  2045.     tan_table[ANGLE_0]     = tan_table[ANGLE_0+1];
  2046.     inv_tan_table[ANGLE_0] = inv_tan_table[ANGLE_0+1];
  2047.     tan_table[ANGLE_90]     = tan_table[ANGLE_90+1];
  2048.     inv_tan_table[ANGLE_90] = inv_tan_table[ANGLE_90+1];
  2049.     tan_table[ANGLE_180]     = tan_table[ANGLE_180+1];
  2050.     inv_tan_table[ANGLE_180] = inv_tan_table[ANGLE_180+1];
  2051.     tan_table[ANGLE_270]     = tan_table[ANGLE_270+1];
  2052.     inv_tan_table[ANGLE_270] = inv_tan_table[ANGLE_270+1];
  2053.  
  2054.     y_step[ANGLE_0]        = y_step[ANGLE_0+1];
  2055.     x_step[ANGLE_0]        = x_step[ANGLE_0+1];
  2056.     y_step[ANGLE_90]        = y_step[ANGLE_90+1];
  2057.     x_step[ANGLE_90]        = x_step[ANGLE_90+1];
  2058.     y_step[ANGLE_180]        = y_step[ANGLE_180+1];
  2059.     x_step[ANGLE_180]        = x_step[ANGLE_180+1];
  2060.     y_step[ANGLE_270]        = y_step[ANGLE_270+1];
  2061.     x_step[ANGLE_270]        = x_step[ANGLE_270+1];
  2062.  
  2063.     // create the sin and cosine tables to copute distances
  2064.  
  2065.     inv_cos_table[ANGLE_0] = inv_cos_table[ANGLE_0+1];
  2066.     inv_sin_table[ANGLE_0] = inv_sin_table[ANGLE_0+1];
  2067.     inv_cos_table[ANGLE_90] = inv_cos_table[ANGLE_90+1];
  2068.     inv_sin_table[ANGLE_90] = inv_sin_table[ANGLE_90+1];
  2069.     inv_cos_table[ANGLE_180] = inv_cos_table[ANGLE_180+1];
  2070.     inv_sin_table[ANGLE_180] = inv_sin_table[ANGLE_180+1];
  2071.     inv_cos_table[ANGLE_270] = inv_cos_table[ANGLE_270+1];
  2072.     inv_sin_table[ANGLE_270] = inv_sin_table[ANGLE_270+1];
  2073.  
  2074. // create view filter table.  There is a cosine wave modulated on top of
  2075. // the view distance as a side effect of casting from a fixed point.
  2076. // to cancel this effect out, we multiple by the inverse of the cosine
  2077. // and the result is the proper scale.  Without this we would see a
  2078. // fishbowl effect, which might be desired in some cases?
  2079.  
  2080.     for (ang=(-HALF_VIEW_CONE); ang<=(HALF_VIEW_CONE); ang++)
  2081.     {
  2082.  
  2083.         rad_angle = (float)((3.272e-4) + ang * 2*3.141592654/ANGLE_360);
  2084.  
  2085.         cos_table[ang+HALF_VIEW_CONE] = (float)(VERTICAL_SCALE/cos(rad_angle));
  2086.  
  2087.     } // end for
  2088.  
  2089. // build the scaler table.  This table holds MAX_SCALE different arrays.  Each
  2090. // array consists of the pre-computed indices for an object to be scaled
  2091.  
  2092.     for (scale=1; scale<=WINDOW_HALF_HEIGHT; scale++)
  2093.     {
  2094.  
  2095.         // create the indices for this scale
  2096.  
  2097.         Create_Scale_Data(scale, (int *)scale_table[scale]);
  2098.  
  2099.     } // end for scale
  2100.  
  2101.     // THE SECOND Create_Scale_Data FUNCTION REFERED TO HERE IS USED
  2102.     // TO COMPUTE SCALES FOR CASES WHERE THE BOTTOM AND THE TOP OF A WALL
  2103.     // SLIVER ARE BEYOND THE VERTICAL EXTENTS OF THE VIEWPORT!
  2104.  
  2105.     for (scale=WINDOW_HALF_HEIGHT+1; scale<=MAX_SCALE; scale++)
  2106.     {
  2107.  
  2108.         // create the indices for this scale
  2109.  
  2110.         Create_Scale_Data2(scale, (int *)scale_table[scale]);
  2111.  
  2112.     } // end for scale
  2113.  
  2114.  // I saved a few multiplies with these...
  2115.  
  2116.     for (ang = 0; ang<200; ang++)
  2117.         v_320[ang] = ang*320;
  2118.  
  2119.     for (ang = 0; ang<200; ang++)
  2120.         v_80[ang] = ang*80;
  2121.  
  2122.     for (ang = 0; ang<320; ang++)
  2123.         h_320[ang] = ang>>2;
  2124.  
  2125. } // end Build_Tables
  2126.  
  2127. /////////////////////////////////////////////////////////////////////////////
  2128.  
  2129. void Allocate_World(void)
  2130. {
  2131. // this function allocates the memory for the world
  2132.  
  2133. // I had initially allocated the world[][] array here...
  2134. //   ... and believe it or not... even though there are always fewer
  2135. // than say, 15 doors to a map - I allocated a doors[][] array here too.
  2136. // NEEDLESS TO SAY - I WAS VERY WASTEFUL OF RESOURCES
  2137.  
  2138. int index;
  2139.  
  2140. // allocate each row
  2141.  
  2142. for (index=0; index<WORLD_ROWS; index++)
  2143.     {
  2144.         Block_Map[index] = (char far *)_fmalloc(WORLD_COLUMNS+1);
  2145.     } // end for index
  2146.  
  2147. } // end Allocate_World
  2148.  
  2149.  
  2150. ////////////////////////////////////////////////////////////////////////////////
  2151.  
  2152. int Load_World(int lev_number)
  2153. {
  2154.     // this function opens the input file and loads the world data from it
  2155.  
  2156.     // the maps for this 'game' are 32x32 text files (you can makem' with
  2157.     // notepad). 2s and 3s make doors.
  2158.  
  2159.     // 4s were used to make impassable, invisible walls (for objects)
  2160.  
  2161.     FILE  *fp, *fopen();
  2162.     int ob_num,gunner_num;
  2163.  
  2164.     int index,row,column;
  2165.     char buffer[WORLD_COLUMNS+2],ch;
  2166.     int door_num = 0;
  2167.     int result;
  2168.     long pos;
  2169.  
  2170.     // open the file
  2171.  
  2172.     if (!(fp = fopen("world.dat","r")))
  2173.            return(0);
  2174.  
  2175.     pos = (1088L*(long)(lev_number<<1));
  2176.     result = fseek( fp, pos, SEEK_SET);
  2177.     if( result )
  2178.          Print_String_Mode_Y(10,10,79,"Fseek failure",0);
  2179.  
  2180.     // load in the data
  2181.  
  2182.     for (row=0; row<WORLD_ROWS; row++)
  2183.     {
  2184.         // load in the next row
  2185.  
  2186.         for (column=0; column<WORLD_COLUMNS; column++)
  2187.         {
  2188.  
  2189.             while((ch = getc(fp))==10){} // filter out CR
  2190.  
  2191.             // translate character to integer
  2192.  
  2193.             if (ch == ' ')
  2194.                    ch=0;
  2195.             else
  2196.                    ch = ch - '0';
  2197.  
  2198.             // insert data into world
  2199.  
  2200.             if (ch==4)
  2201.                 world[(WORLD_ROWS-1) - row][column].block_type = 0;
  2202.             else
  2203.                 world[(WORLD_ROWS-1) - row][column].block_type = ch;
  2204.  
  2205.             Block_Map[(WORLD_ROWS-1) - row][column] = ch;
  2206.  
  2207.  
  2208.             if ((ch == 2) || (ch == 3)) // if it's a door
  2209.             {
  2210.                 world[(WORLD_ROWS-1) - row][column].door_id = door_num;
  2211.  
  2212.  
  2213.                 doors[door_num].door_y = (WORLD_ROWS-1) - row;
  2214.                 doors[door_num].door_x = column;
  2215.                 doors[door_num].door_state = CLOSED;
  2216.                 doors[door_num].door_block_type = ch;
  2217.                 doors[door_num].locked=0;
  2218.                 doors[door_num].door_speed=5;
  2219.                 doors[door_num].door_increment=0;
  2220.                 doors[door_num].door_wait_to_close=0;
  2221.  
  2222.                 door_num++;
  2223.             }
  2224.         } // end for column
  2225.  
  2226.         // process the row
  2227.  
  2228.     } // end for row
  2229.  
  2230.     total_world_doors = door_num;  // used by Process_Doors
  2231.  
  2232.     // allocate space for object lists...
  2233.  
  2234.     // init ob counter
  2235.  
  2236.     ob_num = 0;
  2237.     gunner_num = 0;
  2238.  
  2239.     // load in the data
  2240.  
  2241.     for (row=0; row<WORLD_ROWS; row++)
  2242.     {
  2243.         // load in the next row
  2244.  
  2245.         for (column=0; column<WORLD_COLUMNS; column++)
  2246.         {
  2247.  
  2248.             while((ch = getc(fp))==10){} // filter out CR
  2249.  
  2250.             // translate character to integer
  2251.  
  2252.             if ((ch == '0') || (ch == '1') || (ch == '6'))
  2253.             {
  2254.                    ch = ch - '0';
  2255.  
  2256.                 initial_object_list[ob_num].x = (column<<CELL_X_SIZE_FP)+32;
  2257.                 initial_object_list[ob_num].y = (((WORLD_ROWS-1) - row)<<CELL_Y_SIZE_FP)+32;
  2258.                 initial_object_list[ob_num].angle = ANGLE_0;
  2259.                 initial_object_list[ob_num].kind_of_object = ch;
  2260.                 initial_object_list[ob_num].dist = 0;
  2261.  
  2262.                 ob_num++;
  2263.             }
  2264.  
  2265.  
  2266.         } // end for column
  2267.  
  2268.         // process the row
  2269.  
  2270.     } // end for row
  2271.  
  2272.     // close the file
  2273.  
  2274.     result = fseek( fp, pos+1088L, SEEK_SET);
  2275.     if( result )
  2276.          Print_String_Mode_Y(10,10,79,"Fseek failure",0);
  2277.  
  2278.     // load in the data
  2279.  
  2280.     for (row=0; row<WORLD_ROWS; row++)
  2281.     {
  2282.         // load in the next row
  2283.  
  2284.         for (column=0; column<WORLD_COLUMNS; column++)
  2285.         {
  2286.  
  2287.             while((ch = getc(fp))==10){} // filter out CR
  2288.  
  2289.             // translate character to integer
  2290.  
  2291.             if ((ch == '4') || (ch == '5'))
  2292.             {
  2293.                    ch = ch - '0';
  2294.  
  2295.                 initial_object_list[ob_num].x = (column<<CELL_X_SIZE_FP)+32;
  2296.                 initial_object_list[ob_num].y = (((WORLD_ROWS-1) - row)<<CELL_Y_SIZE_FP)+32;
  2297.                 initial_object_list[ob_num].angle = ANGLE_0;
  2298.                 initial_object_list[ob_num].kind_of_object = ch;
  2299.                 initial_object_list[ob_num].dist = 0;
  2300.  
  2301.                 ob_num++;
  2302.             }
  2303.  
  2304.  
  2305.         } // end for column
  2306.  
  2307.         // process the row
  2308.  
  2309.     } // end for row
  2310.  
  2311.     // close the file
  2312.  
  2313.     Number_Of_Fixed_Objects = ob_num;
  2314.  
  2315.     ob_num = 0;
  2316.  
  2317.     result = fseek( fp, pos+1088L, SEEK_SET);
  2318.     if( result )
  2319.          Print_String_Mode_Y(10,10,79,"Fseek failure",0);
  2320.  
  2321.  
  2322.     // load in the data
  2323.  
  2324.     for (row=0; row<WORLD_ROWS; row++)
  2325.     {
  2326.         // load in the next row
  2327.  
  2328.         for (column=0; column<WORLD_COLUMNS; column++)
  2329.         {
  2330.  
  2331.             while((ch = getc(fp))==10){} // filter out CR
  2332.  
  2333.             // translate character to integer
  2334.  
  2335.             if ((ch == '2') || (ch == '3'))
  2336.             {
  2337.                    ch = ch - '0';
  2338.  
  2339.                 enemies[ob_num].vitals.x = (column<<CELL_X_SIZE_FP)+32;
  2340.                 enemies[ob_num].vitals.y = (((WORLD_ROWS-1) - row)<<CELL_Y_SIZE_FP)+32;
  2341.                 enemies[ob_num].vitals.angle = ANGLE_0;
  2342.                 enemies[ob_num].vitals.kind_of_object = ch;
  2343.                 enemies[ob_num].vitals.dist = 0;
  2344.                 enemies[ob_num].enem_num = ob_num;
  2345.  
  2346.                 enemies[ob_num].state = WAITING;
  2347.                 enemies[ob_num].threshold = 0;
  2348.                 enemies[ob_num].hit_points = 5;
  2349.                 enemies[ob_num].pat_num = 0;
  2350.  
  2351.                 ob_num++;
  2352.             }
  2353.  
  2354.  
  2355.         } // end for column
  2356.  
  2357.         // process the row
  2358.  
  2359.     } // end for row
  2360.  
  2361.     // close the file
  2362.  
  2363.     fclose(fp);
  2364.  
  2365.     Number_Of_Enemies = ob_num;
  2366.  
  2367.     // close the file
  2368.  
  2369.     //return(1);
  2370.  
  2371. } // end Load_World
  2372.  
  2373. /////////////////////////////////////////////////////////////////////////////
  2374.  
  2375. void Ray_Caster(void)
  2376. {
  2377.  
  2378. // This is the heart of the system.  it casts out 320 rays and builds the
  2379. // 3-D image from their intersections with the walls.  It was derived from
  2380. // the previous version used in "RAY.C", however, it has been extremely
  2381. // optimized for speed by the use of many more lookup tables and fixed
  2382. // point math
  2383.  
  2384.     register int
  2385.     curr_ang,
  2386.     cell_x,       // the current cell that the ray is in
  2387.     cell_y,
  2388.     ray,          // the current ray being cast 0-320
  2389.     casting=2,    // tracks the progress of the X and Y component of the ray
  2390.     x_hit_type,   // records the block that was intersected, used to figure
  2391.     y_hit_type,   // out which texture to use
  2392.     x_bound,      // the next vertical and horizontal intersection point
  2393.     y_bound,
  2394.     next_y_cell,  // used to figure out the quadrant of the ray
  2395.     next_x_cell,
  2396.     xray=0,       // tracks the progress of a ray looking for Y interesctions
  2397.     yray=0,       // tracks the progress of a ray looking for X interesctions
  2398.  
  2399.     x_delta,      // the amount needed to move to get to the next cell
  2400.     y_delta,      // position
  2401.     xb_save,
  2402.     yb_save,
  2403.     xi_save,      // used to save exact x and y intersection points
  2404.     yi_save,
  2405.     scale;
  2406.  
  2407.     int x_anded,y_anded;
  2408.  
  2409.     int door_sliver;
  2410.  
  2411.     int in_bounds;
  2412.  
  2413.     register long
  2414.          cast=0,
  2415.          dist_x,  // the distance of the x and y ray intersections from
  2416.          dist_y;  // the viewpoint
  2417.  
  2418.     register float xi,     // used to track the x and y intersections
  2419.           yi;
  2420.  
  2421.     int temp_ray;
  2422.  
  2423.     int a_toggle, b_toggle;
  2424.  
  2425.     // variables to handle a door being partially open (one of many ways to do this)
  2426.  
  2427.     int dor_y_inc=0;
  2428.     int dor_x_inc=0;
  2429.  
  2430.     int doorx_num, doory_num;
  2431.  
  2432.  
  2433. // S E C T I O N  1 /////////////////////////////////////////////////////////v
  2434.  
  2435. // initialization
  2436.  
  2437. // compute starting angle from player.  Field of view is 90 degrees, so
  2438. // subtract half of that current view angle
  2439.  
  2440.     // start the current angle off -45 degrees to the left of the player's
  2441.     // current viewing direction
  2442.  
  2443.     //        The following inline assembly instructions determine which
  2444.     // plane(s) pixels will be written to.
  2445.  
  2446.     //       The value moved into AH (1-15... or 0001 - 1111{binary})
  2447.     // determines the plane enabled!
  2448.  
  2449. // P L A N E  # ? ////////////////////////////////////////////////////
  2450. /////////////////////// E N A B L E D ////////////////////////////////////
  2451.  
  2452. // NOTE: I DECIDED TO DO THIS OUTSIDE OF THE RAY-CASTER! /////////////
  2453. //    In the procedure Draw_Walls /////////////////////////////
  2454.  
  2455.     curr_ang = view_angle;
  2456.  
  2457.     if ( (curr_ang-=HALF_VIEW_CONE) < 0)
  2458.        {
  2459.            curr_ang=ANGLE_360 + curr_ang;
  2460.        } // end if
  2461.  
  2462.     // loop through all 320 rays
  2463.  
  2464.        x_anded = (int)(x & 0xffc0);
  2465.        y_anded = (int)(y & 0xffc0);
  2466.  
  2467.     for (ray=0; ray<(VIEW_CONE); ray++)
  2468.     {
  2469.  
  2470. // S E C T I O N  2 /////////////////////////////////////////////////////////
  2471.  
  2472.         dor_y_inc=0;
  2473.         dor_x_inc=0;
  2474.  
  2475.         temp_ray = ray;
  2476.  
  2477.         // compute first x intersection
  2478.  
  2479.         // need to know which half plane we are casting from relative to Y axis
  2480.  
  2481.         y_bound = y_anded;
  2482.         y_delta = -CELL_Y_SIZE;
  2483.         next_y_cell = -1;
  2484.         a_toggle = 0;
  2485.  
  2486.         if (curr_ang >= ANGLE_0 && curr_ang < ANGLE_180)
  2487.            {
  2488.  
  2489.                // compute first horizontal line that could be intersected with ray
  2490.                // note: it will be above player
  2491.  
  2492.                y_bound = (CELL_Y_SIZE + y_anded);
  2493.  
  2494.                // compute delta to get to next horizontal line
  2495.  
  2496.                y_delta = CELL_Y_SIZE;
  2497.  
  2498.                // set cell delta
  2499.  
  2500.                next_y_cell = 0;
  2501.  
  2502.                a_toggle = 1;
  2503.  
  2504.            } // end if upper half plane
  2505.  
  2506.            // based on first possible horizontal intersection line, compute X
  2507.            // intercept, so that casting can begin
  2508.  
  2509.            xi = inv_tan_table[curr_ang] * (y_bound - y) + x;
  2510.  
  2511. // S E C T I O N  3 /////////////////////////////////////////////////////////
  2512.  
  2513.         // compute first y intersection
  2514.  
  2515.         x_bound = x_anded;
  2516.         x_delta = -CELL_X_SIZE;
  2517.  
  2518.         next_x_cell = -1;
  2519.  
  2520.         b_toggle = 0;
  2521.         // need to know which half plane we are casting from relative to X axis
  2522.  
  2523.         if (curr_ang < ANGLE_90 || curr_ang >= ANGLE_270)
  2524.            {
  2525.  
  2526.                // compute first vertical line that could be intersected with ray
  2527.                // note: it will be to the right of player
  2528.  
  2529.                x_bound = (int)(CELL_X_SIZE + x_anded);
  2530.  
  2531.                // compute delta to get to next vertical line
  2532.  
  2533.                x_delta = CELL_X_SIZE;
  2534.  
  2535.                // set cell delta
  2536.  
  2537.                next_x_cell = 0;
  2538.  
  2539.             b_toggle = 1;
  2540.            } // end if right half plane
  2541.  
  2542.            // based on first possible vertical intersection line, compute Y
  2543.            // intercept, so that casting can begin
  2544.  
  2545.            yi = tan_table[curr_ang] * (x_bound - x) + y;
  2546.  
  2547.  
  2548. // begin cast
  2549.  
  2550.         xray=yray     = 0;                // reset intersection flags
  2551.  
  2552. // PREAMBLE TO S E C T I O N  4 /////////////////////////////////////////////////////////
  2553.  
  2554.         cell_x = ( (x_bound+next_x_cell) >> CELL_X_SIZE_FP);
  2555.  
  2556.         cell_y = (int)yi;
  2557.         cell_y>>=CELL_Y_SIZE_FP;
  2558.  
  2559.         // test if there is a block where the current x ray is intersecting
  2560.  
  2561.         if ((x_hit_type = world[cell_y][cell_x].block_type)!=0)
  2562.         {
  2563.             if (x_hit_type == 2) // is this an East/West door?
  2564.             {
  2565.                 // get the door's identification number
  2566.  
  2567.                 doorx_num = world[cell_y][cell_x].door_id;
  2568.  
  2569.                 // move the ray a half step forward
  2570.  
  2571.                 yi += y_step[curr_ang]/2;
  2572.  
  2573.                 // what column of the door's bitmap would we use?
  2574.  
  2575.                 door_sliver = ((int)yi & 0x003f);
  2576.  
  2577.                 if (doors[doorx_num].door_state!=CLOSED)
  2578.                 {
  2579.                     // if door isn't closed...
  2580.                     // slide the texture over to the right...
  2581.  
  2582.                     dor_x_inc = door_sliver + doors[doorx_num].door_increment;
  2583.  
  2584.                     if (dor_x_inc > 63)  // the door isn't blocking
  2585.                     {                    // this ray from a wall beyond...
  2586.                         //back the ray up a half step
  2587.  
  2588.                         yi -= y_step[curr_ang]/2;
  2589.                     }
  2590.                     else
  2591.                     {
  2592.                         // confirmed: Door hit
  2593.  
  2594.                         x_hit_type = 3;
  2595.  
  2596.                         xray = INTERSECTION_FOUND;
  2597.                     }
  2598.                 }
  2599.                 else
  2600.                 {
  2601.                     // confirmed: Door hit
  2602.  
  2603.                     x_hit_type = 3;
  2604.                     dor_x_inc = door_sliver;
  2605.                     xray = INTERSECTION_FOUND;
  2606.                 }
  2607.             }
  2608.             else
  2609.                 xray = INTERSECTION_FOUND;
  2610.         } // end if a hit
  2611.  
  2612. // S E C T I O N  4 /////////////////////////////////////////////////////////
  2613.  
  2614.         while(xray!=INTERSECTION_FOUND)
  2615.         {
  2616.  
  2617.             // continue casting each ray in parallel
  2618.  
  2619.             yi += y_step[curr_ang];
  2620.  
  2621.             // find next possible x intercept point
  2622.  
  2623.             x_bound += x_delta;
  2624.  
  2625.             // compute current map position to inspect
  2626.  
  2627.             cell_x = ( (x_bound+next_x_cell) >> CELL_X_SIZE_FP);
  2628.  
  2629.             cell_y = (int)yi;
  2630.             cell_y>>=CELL_Y_SIZE_FP;
  2631.  
  2632.             // test if there is a block where the current x ray is intersecting
  2633.  
  2634.             if ((x_hit_type = world[cell_y][cell_x].block_type)!=0)
  2635.             {
  2636.                 if (x_hit_type == 2) // is this an East/West door?
  2637.                 {
  2638.                     // get the door's identification number
  2639.  
  2640.                     doorx_num = world[cell_y][cell_x].door_id;
  2641.  
  2642.                     // move the ray a half step forward
  2643.  
  2644.                     yi += y_step[curr_ang]/2;
  2645.  
  2646.                     // what column of the door's bitmap would we use?
  2647.  
  2648.                     door_sliver = ((int)yi & 0x003f);
  2649.  
  2650.                     if (doors[doorx_num].door_state!=CLOSED)
  2651.                     {
  2652.                         // if door isn't closed...
  2653.                         // slide the texture over to the right...
  2654.  
  2655.                         dor_x_inc = door_sliver + doors[doorx_num].door_increment;
  2656.  
  2657.                         if (dor_x_inc > 63)  // the door isn't blocking
  2658.                         {                    // this ray from a wall beyond...
  2659.                             //back the ray up a half step
  2660.  
  2661.                             yi -= y_step[curr_ang]/2;
  2662.                         }
  2663.                         else
  2664.                         {
  2665.                             // confirmed: Door hit
  2666.  
  2667.                             x_hit_type = 3;
  2668.  
  2669.                             xray = INTERSECTION_FOUND;
  2670.                         }
  2671.                     }
  2672.                     else
  2673.                     {
  2674.                         // confirmed: Door hit
  2675.  
  2676.                         x_hit_type = 3;
  2677.                         dor_x_inc = door_sliver;
  2678.                         xray = INTERSECTION_FOUND;
  2679.                     }
  2680.                 }
  2681.                 else
  2682.                     xray = INTERSECTION_FOUND;
  2683.             } // end if a hit
  2684.  
  2685.         } // end if x ray has intersected
  2686.  
  2687.         dist_x  = (long)((yi - y) * inv_sin_table[curr_ang]);
  2688.         yi_save = (int)yi;    // what column of the wall (or door's) bitmap
  2689.                               // do we use.
  2690.  
  2691.         xb_save = x_bound;
  2692.  
  2693. // PREAMBLE TO S E C T I O N  5 /////////////////////////////////////////////////////////
  2694.  
  2695.         cell_x = xi;
  2696.         cell_x>>=CELL_X_SIZE_FP;
  2697.  
  2698.         cell_y = ( (y_bound + next_y_cell) >> CELL_Y_SIZE_FP);
  2699.  
  2700.         // test if there is a block where the current y ray is intersecting
  2701.  
  2702.         if ((y_hit_type = world[cell_y][cell_x].block_type)!=0)
  2703.         {
  2704.             if (y_hit_type == 3)  // is this a north/south doorway?
  2705.             {
  2706.                 // extract door identification #
  2707.  
  2708.                 doory_num = world[cell_y][cell_x].door_id;
  2709.  
  2710.                 // move forward a half step
  2711.  
  2712.                 xi += x_step[curr_ang]/2;
  2713.  
  2714.                 // what column of the door are we looking at?
  2715.  
  2716.                 door_sliver = ((int)xi & 0x003f);
  2717.  
  2718.                 if (doors[doory_num].door_state!=CLOSED)
  2719.                 {
  2720.                     // slide door over...
  2721.  
  2722.                     dor_y_inc = door_sliver + doors[doory_num].door_increment;
  2723.  
  2724.                     // does this ray miss the partially opened door?
  2725.  
  2726.                     if (dor_y_inc > 63)     // yep!
  2727.                     {
  2728.                         // backup half a step
  2729.  
  2730.                         xi -= x_step[curr_ang]/2;
  2731.                     }
  2732.                     else
  2733.                     {
  2734.                         // it's a hit!
  2735.  
  2736.                         y_hit_type = 3;
  2737.                         yray = INTERSECTION_FOUND;
  2738.                     }
  2739.                 }
  2740.                 else
  2741.                 {
  2742.                     // it's a hit!
  2743.  
  2744.                     dor_y_inc = door_sliver;
  2745.                     yray = INTERSECTION_FOUND;
  2746.                 }
  2747.             }
  2748.             else        // not a door... it's a hit!
  2749.                 yray = INTERSECTION_FOUND;
  2750.         }
  2751.  
  2752. // S E C T I O N  5 /////////////////////////////////////////////////////////
  2753.  
  2754.         while (yray!=INTERSECTION_FOUND)
  2755.         {
  2756.  
  2757.             xi += x_step[curr_ang];
  2758.  
  2759.             // compute next possible y intercept
  2760.  
  2761.             y_bound += y_delta;
  2762.             // compute current map position to inspect
  2763.  
  2764.             cell_x = xi;
  2765.             cell_x>>=CELL_X_SIZE_FP;
  2766.  
  2767.             cell_y = ( (y_bound + next_y_cell) >> CELL_Y_SIZE_FP);
  2768.  
  2769.             // test if there is a block where the current y ray is intersecting
  2770.  
  2771.             if ((y_hit_type = world[cell_y][cell_x].block_type)!=0)
  2772.             {
  2773.                 if (y_hit_type == 3)  // is this a north/south doorway?
  2774.                 {
  2775.                     // extract door identification #
  2776.  
  2777.                     doory_num = world[cell_y][cell_x].door_id;
  2778.  
  2779.                     // move forward a half step
  2780.  
  2781.                     xi += x_step[curr_ang]/2;
  2782.  
  2783.                     // what column of the door are we looking at?
  2784.  
  2785.                     door_sliver = ((int)xi & 0x003f);
  2786.  
  2787.                     if (doors[doory_num].door_state!=CLOSED)
  2788.                     {
  2789.                         // slide door over...
  2790.  
  2791.                         dor_y_inc = door_sliver + doors[doory_num].door_increment;
  2792.  
  2793.                         // does this ray miss the partially opened door?
  2794.  
  2795.                         if (dor_y_inc > 63)     // yep!
  2796.                         {
  2797.                             // backup half a step
  2798.  
  2799.                             xi -= x_step[curr_ang]/2;
  2800.                         }
  2801.                         else
  2802.                         {
  2803.                             // it's a hit!
  2804.  
  2805.                             y_hit_type = 3;
  2806.                             yray = INTERSECTION_FOUND;
  2807.                         }
  2808.                     }
  2809.                     else
  2810.                     {
  2811.                         // it's a hit!
  2812.  
  2813.                         dor_y_inc = door_sliver;
  2814.                         yray = INTERSECTION_FOUND;
  2815.                     }
  2816.                 }
  2817.                 else        // not a door... it's a hit!
  2818.                     yray = INTERSECTION_FOUND;
  2819.             }
  2820.  
  2821.         } // end while not done
  2822.  
  2823.         dist_y  = (long)((xi - x) * inv_cos_table[curr_ang]);
  2824.         xi_save = (int)xi;
  2825.         yb_save = y_bound;
  2826.  
  2827. // S E C T I O N  6 /////////////////////////////////////////////////////////
  2828.  
  2829.         // at this point, we know that the ray has succesfully hit both a
  2830.         // vertical wall and a horizontal wall, so we need to see which one
  2831.         // was closer and then render it
  2832.  
  2833.         if (dist_x < dist_y)
  2834.            {
  2835.  
  2836.                // there was a vertical wall closer than the horizontal
  2837.  
  2838.                // compute actual scale and multiply by view filter so that spherical
  2839.                // distortion is cancelled
  2840.  
  2841.                scale = (int)(cos_table[temp_ray]/(dist_x))>>1;
  2842.  
  2843.             vz_buffer[ray] = dist_x;
  2844.  
  2845.             sliver_buffer[ray].sliv_hit_type = 0+(2*b_toggle);
  2846.  
  2847.                // clip wall sliver against view port
  2848.  
  2849.                if (scale>(MAX_SCALE-1)) scale=(MAX_SCALE-1);
  2850.  
  2851.                sliver_buffer[ray].scale_r      = scale-1;
  2852.  
  2853.                if (scale>(WINDOW_HALF_HEIGHT))
  2854.               {
  2855.                   scale=(WINDOW_HALF_HEIGHT);
  2856.               }
  2857.  
  2858.                sliver_buffer[ray].sliv_scale   = scale-1;
  2859.  
  2860.                // set up parameters for assembly language
  2861.  
  2862.                sliver_buffer[ray].sliv_texture = wall_frames.frames[x_hit_type-1];
  2863.  
  2864.                if (x_hit_type != 3)
  2865.                    sliver_buffer[ray].sliv_column  = (yi_save & 0x003f);
  2866.                else
  2867.                    sliver_buffer[ray].sliv_column = dor_x_inc;
  2868.  
  2869.                sliver_buffer[ray].sliv_top     = WINDOW_MIDDLE - (scale >> 1);
  2870.                sliver_buffer[ray].sliv_ray     = COLUMN_OFFSET-ray;
  2871.  
  2872.            } // end if
  2873.         else // must of hit a horizontal wall first
  2874.            {
  2875.  
  2876.                // there was a vertical wall closer than the horizontal
  2877.  
  2878.                // compute actual scale and multiply by view filter so that spherical
  2879.                // distortion is cancelled
  2880.  
  2881.                scale = (int)(cos_table[temp_ray]/(dist_y))>>1;
  2882.  
  2883.             vz_buffer[ray] = dist_y;
  2884.  
  2885.             sliver_buffer[ray].sliv_hit_type = 1+(2*a_toggle);
  2886.  
  2887.                // do clipping again
  2888.  
  2889.                if (scale>(MAX_SCALE-1)) scale=(MAX_SCALE-1);
  2890.  
  2891.                sliver_buffer[ray].scale_r      = scale-1;
  2892.  
  2893.                if (scale>(WINDOW_HALF_HEIGHT))
  2894.               {
  2895.                   scale=(WINDOW_HALF_HEIGHT);
  2896.               }
  2897.  
  2898.                sliver_buffer[ray].sliv_scale  = scale-1;
  2899.  
  2900.                // set up parameters for assembly language
  2901.  
  2902.                sliver_buffer[ray].sliv_texture = wall_frames.frames[y_hit_type];
  2903.  
  2904.  
  2905.                if (y_hit_type != 3)
  2906.                    sliver_buffer[ray].sliv_column  = (xi_save & 0x003f);
  2907.                else
  2908.                    sliver_buffer[ray].sliv_column = dor_y_inc;
  2909.  
  2910.                sliver_buffer[ray].sliv_top    = WINDOW_MIDDLE - (scale >> 1);
  2911.                sliver_buffer[ray].sliv_ray     = COLUMN_OFFSET-ray;
  2912.  
  2913.            } // end else
  2914.  
  2915. // S E C T I O N  7 /////////////////////////////////////////////////////////
  2916.  
  2917.         // cast next ray
  2918.  
  2919.         // test if view angle need to wrap around
  2920.  
  2921.         if ((++curr_ang)>=ANGLE_360)
  2922.            {
  2923.             curr_ang-=ANGLE_360;
  2924.                //curr_ang=0;
  2925.  
  2926.            } // end if
  2927.  
  2928.        } // end for ray
  2929.  
  2930. } // end Ray_Caster
  2931.  
  2932. void Weak_Attempt(void)
  2933. {
  2934.     // This is a weak attempt at applying some linear interpolation in the ray casting
  2935.     // It does speed up things a little bit... but it definitely has it's flaws...
  2936.  
  2937.     // essential... since the ray caster casts rays FOR EVERY OTHER COLUMN of the screen...
  2938.     // ...this procedure fills in the blanks... (i.e. puts data into the sliver_buffer at
  2939.     //                                            IN BETWEEN points in the array)
  2940.  
  2941.     int index,temp1,temp2;
  2942.  
  2943.  
  2944.     for (index = 1 ; index < (VIEW_CONE); index+=2)
  2945.     {
  2946.         sliver_buffer[index].sliv_ray=COLUMN_OFFSET-index;
  2947.  
  2948.         if ((index)==(VIEW_CONE-1))                   //index-1
  2949.         {
  2950.              sliver_buffer[index].sliv_hit_type=sliver_buffer[index-1].sliv_hit_type;
  2951.              sliver_buffer[index].sliv_column=sliver_buffer[index-1].sliv_column;
  2952.              sliver_buffer[index].sliv_top=sliver_buffer[index-1].sliv_column;
  2953.              vz_buffer[index] = vz_buffer[index-1];
  2954.              sliver_buffer[index].sliv_scale=sliver_buffer[index-1].sliv_scale;
  2955.              sliver_buffer[index].scale_r=sliver_buffer[index-1].scale_r;
  2956.              sliver_buffer[index].sliv_texture=sliver_buffer[index-1].sliv_texture;
  2957.         }
  2958.         else
  2959.         if (sliver_buffer[index-1].sliv_hit_type!=sliver_buffer[index+1].sliv_hit_type)
  2960.         {
  2961.             sliver_buffer[index].sliv_hit_type=sliver_buffer[index+1].sliv_hit_type;
  2962.             sliver_buffer[index].sliv_column = sliver_buffer[index+1].sliv_column;
  2963.             sliver_buffer[index].sliv_top = sliver_buffer[index+1].sliv_top;
  2964.  
  2965.             vz_buffer[index] = vz_buffer[index+1];
  2966.  
  2967.                // clip wall sliver against view port
  2968.  
  2969.                sliver_buffer[index].sliv_scale   = sliver_buffer[index+1].sliv_scale;
  2970.  
  2971.                sliver_buffer[index].scale_r      = sliver_buffer[index+1].scale_r;
  2972.  
  2973.                sliver_buffer[index].sliv_texture = sliver_buffer[index+1].sliv_texture;
  2974.         }
  2975.         else
  2976.         if ((sliver_buffer[index-1].sliv_hit_type==sliver_buffer[index+1].sliv_hit_type) &&
  2977.             (((vz_buffer[index-1] - vz_buffer[index+1]) > 64) ||
  2978.              ((vz_buffer[index-1] - vz_buffer[index+1]) < -64)))
  2979.         {
  2980.             sliver_buffer[index].sliv_hit_type=sliver_buffer[index+1].sliv_hit_type;
  2981.             sliver_buffer[index].sliv_column = sliver_buffer[index+1].sliv_column;
  2982.             sliver_buffer[index].sliv_top = sliver_buffer[index+1].sliv_top;
  2983.  
  2984.             vz_buffer[index] = vz_buffer[index+1];
  2985.  
  2986.                sliver_buffer[index].sliv_scale   = sliver_buffer[index+1].sliv_scale;
  2987.  
  2988.                sliver_buffer[index].scale_r      = sliver_buffer[index+1].scale_r;
  2989.  
  2990.                sliver_buffer[index].sliv_texture = sliver_buffer[index+1].sliv_texture;
  2991.         }
  2992.         else
  2993.         {
  2994.             sliver_buffer[index].sliv_hit_type=sliver_buffer[index+1].sliv_hit_type;
  2995.             vz_buffer[index] = (vz_buffer[index-1]+vz_buffer[index+1])>>1;
  2996.  
  2997.                sliver_buffer[index].sliv_scale   = (sliver_buffer[index-1].sliv_scale+sliver_buffer[index+1].sliv_scale)>>1;
  2998.  
  2999.                sliver_buffer[index].scale_r      = (sliver_buffer[index-1].scale_r+sliver_buffer[index+1].scale_r)>>1;
  3000.  
  3001.                sliver_buffer[index].sliv_texture = sliver_buffer[index-1].sliv_texture;
  3002.  
  3003.             temp2 = sliver_buffer[index+1].sliv_column;
  3004.             temp1 = sliver_buffer[index-1].sliv_column;
  3005.  
  3006.             if (sliver_buffer[index-1].sliv_hit_type==0)
  3007.             {
  3008.                 if (sliver_buffer[index-1].sliv_column < sliver_buffer[index+1].sliv_column)
  3009.                     temp1 = sliver_buffer[index-1].sliv_column + 64;
  3010.  
  3011.             }
  3012.             else
  3013.             if (sliver_buffer[index-1].sliv_hit_type==1)
  3014.             {
  3015.                 if (sliver_buffer[index-1].sliv_column > sliver_buffer[index+1].sliv_column)
  3016.                     temp2 = sliver_buffer[index+1].sliv_column + 64;
  3017.  
  3018.             }
  3019.             else
  3020.             if (sliver_buffer[index-1].sliv_hit_type==2)
  3021.             {
  3022.                 if (sliver_buffer[index-1].sliv_column > sliver_buffer[index+1].sliv_column)
  3023.                     temp2 = sliver_buffer[index+1].sliv_column + 64;
  3024.  
  3025.             }
  3026.             else
  3027.             if (sliver_buffer[index-1].sliv_hit_type==3)
  3028.             {
  3029.                 if (sliver_buffer[index-1].sliv_column < sliver_buffer[index+1].sliv_column)
  3030.                     temp1 = sliver_buffer[index-1].sliv_column + 64;
  3031.  
  3032.             }
  3033.  
  3034.  
  3035.             sliver_buffer[index].sliv_column  = ((temp1+temp2)>>1)&0x003f;
  3036.  
  3037.  
  3038.                sliver_buffer[index].sliv_top     = WINDOW_MIDDLE - (sliver_buffer[index].sliv_scale-1);
  3039.            }
  3040.     }
  3041. } // end Weak_Attempt
  3042.  
  3043. /////////////////////////////////////////////////////////////////////////////
  3044.  
  3045. void Draw_Walls(void)
  3046. {
  3047.     // This function draws each plane of the final screen image separately
  3048.  
  3049.     int ray;
  3050.     unsigned short temp_column_offset;
  3051.  
  3052.     _asm
  3053.     {
  3054.         mov dx,SEQUENCER          // address the sequencer
  3055.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  3056.         mov ah,08h                  // select plane 3
  3057.         out dx,ax                 // do it baby!
  3058.     } // end asm
  3059.  
  3060.     for (ray = 0; ray < VIEW_CONE; ray+=4)
  3061.     {
  3062.         scale_row      = scale_table[sliver_buffer[ray].scale_r];
  3063.  
  3064.         sliver_scale = sliver_buffer[ray].sliv_scale;
  3065.  
  3066.         // set up parameters for assembly language
  3067.  
  3068.         sliver_texture = sliver_buffer[ray].sliv_texture;
  3069.         sliver_column  = sliver_buffer[ray].sliv_column;
  3070.         sliver_top     = sliver_buffer[ray].sliv_top;
  3071.         sliver_ray     = sliver_buffer[ray].sliv_ray;
  3072.  
  3073.         // render the sliver
  3074.  
  3075.         Render_Sliver();
  3076.      }
  3077.  
  3078.     _asm
  3079.     {
  3080.         mov dx,SEQUENCER          // address the sequencer
  3081.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  3082.         mov ah,04h                 // select plane 2
  3083.         out dx,ax                 // do it baby!
  3084.     } // end asm
  3085.  
  3086.     for (ray = 1; ray < VIEW_CONE; ray+=4)
  3087.     {
  3088.         scale_row      = scale_table[sliver_buffer[ray].scale_r];
  3089.  
  3090.  
  3091.         sliver_scale = sliver_buffer[ray].sliv_scale;
  3092.  
  3093.         // set up parameters for assembly language
  3094.  
  3095.         sliver_texture = sliver_buffer[ray].sliv_texture;
  3096.         sliver_column  = sliver_buffer[ray].sliv_column;
  3097.         sliver_top     = sliver_buffer[ray].sliv_top;
  3098.         sliver_ray     = sliver_buffer[ray].sliv_ray;
  3099.  
  3100.         // render the sliver
  3101.  
  3102.         Render_Sliver();
  3103.      }
  3104.  
  3105.     _asm
  3106.     {
  3107.         mov dx,SEQUENCER          // address the sequencer
  3108.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  3109.         mov ah,02h                  // select plane 1
  3110.         out dx,ax                 // do it baby!
  3111.     } // end asm
  3112.  
  3113.     for (ray = 2; ray < VIEW_CONE; ray+=4)
  3114.     {
  3115.         scale_row      = scale_table[sliver_buffer[ray].scale_r];
  3116.  
  3117.         sliver_scale = sliver_buffer[ray].sliv_scale;
  3118.  
  3119.         // set up parameters for assembly language
  3120.  
  3121.         sliver_texture = sliver_buffer[ray].sliv_texture;
  3122.         sliver_column  = sliver_buffer[ray].sliv_column;
  3123.         sliver_top     = sliver_buffer[ray].sliv_top;
  3124.         sliver_ray     = sliver_buffer[ray].sliv_ray;
  3125.  
  3126.         // render the sliver
  3127.  
  3128.         Render_Sliver();
  3129.       }
  3130.  
  3131.     _asm
  3132.     {
  3133.         mov dx,SEQUENCER          // address the sequencer
  3134.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  3135.         mov ah,01h                  // select plane 0
  3136.         out dx,ax                 // do it baby!
  3137.     } // end asm
  3138.  
  3139.     for (ray = 3; ray < VIEW_CONE; ray+=4)
  3140.     {
  3141.         scale_row      = scale_table[sliver_buffer[ray].scale_r];
  3142.  
  3143.         sliver_scale = sliver_buffer[ray].sliv_scale;
  3144.  
  3145.         // set up parameters for assembly language
  3146.  
  3147.         sliver_texture = sliver_buffer[ray].sliv_texture;
  3148.         sliver_column  = sliver_buffer[ray].sliv_column;
  3149.         sliver_top     = sliver_buffer[ray].sliv_top;
  3150.         sliver_ray     = sliver_buffer[ray].sliv_ray;
  3151.  
  3152.         // render the sliver
  3153.  
  3154.         Render_Sliver();
  3155.       }
  3156.  
  3157. } // end Draw_Walls
  3158.  
  3159. int Enemy_Line_Of_Sight(long en_x, long en_y, long en_ang, long en_dist)
  3160. {
  3161.      // This function is like a completely stripped Ray Caster...
  3162.      // it casts rays out along only one vector...
  3163.  
  3164.      // ... to "see" if a wall sliver is in between the player and the enemy!
  3165.  
  3166. register int
  3167. curr_ang,
  3168. cell_x,       // the current cell that the ray is in
  3169. cell_y,
  3170. ray,          // the current ray being cast 0-320
  3171. x_hit_type,   // records the block that was intersected, used to figure
  3172. y_hit_type,   // out which texture to use
  3173. x_bound,      // the next vertical and horizontal intersection point
  3174. y_bound,
  3175. next_y_cell,  // used to figure out the quadrant of the ray
  3176. next_x_cell,
  3177. xray=0,       // tracks the progress of a ray looking for Y interesctions
  3178. yray=0,       // tracks the progress of a ray looking for X interesctions
  3179.  
  3180. x_delta,      // the amount needed to move to get to the next cell
  3181. y_delta,      // position
  3182. xb_save,
  3183. yb_save,
  3184. xi_save,      // used to save exact x and y intersection points
  3185. yi_save;
  3186.  
  3187. int x_anded,y_anded;
  3188.  
  3189. register long
  3190.      dist_x,  // the distance of the x and y ray intersections from
  3191.      dist_y;  // the viewpoint
  3192.  
  3193. register float xi,     // used to track the x and y intersections
  3194.       yi;
  3195.  
  3196. int temp_ray;
  3197.  
  3198.     curr_ang = en_ang;
  3199.  
  3200.        x_anded = (int)(en_x & 0xffc0);
  3201.        y_anded = (int)(en_y & 0xffc0);
  3202.  
  3203.  
  3204. // S E C T I O N  2 /////////////////////////////////////////////////////////
  3205.  
  3206.  
  3207.     // compute first x intersection
  3208.  
  3209.     // need to know which half plane we are casting from relative to Y axis
  3210.  
  3211.     if (curr_ang >= ANGLE_0 && curr_ang < ANGLE_180)
  3212.        {
  3213.  
  3214.            // compute first horizontal line that could be intersected with ray
  3215.            // note: it will be above player
  3216.  
  3217.            y_bound = (CELL_Y_SIZE + y_anded);
  3218.  
  3219.            // compute delta to get to next horizontal line
  3220.  
  3221.            y_delta = CELL_Y_SIZE;
  3222.  
  3223.            // based on first possible horizontal intersection line, compute X
  3224.            // intercept, so that casting can begin
  3225.  
  3226.            xi = inv_tan_table[curr_ang] * (y_bound - en_y) + en_x;
  3227.  
  3228.            // set cell delta
  3229.  
  3230.            next_y_cell = 0;
  3231.  
  3232.        } // end if upper half plane
  3233.     else
  3234.        {
  3235.            // compute first horizontal line that could be intersected with ray
  3236.            // note: it will be below player
  3237.  
  3238.            y_bound = y_anded;
  3239.  
  3240.            // compute delta to get to next horizontal line
  3241.  
  3242.            y_delta = -CELL_Y_SIZE;
  3243.  
  3244.            // based on first possible horizontal intersection line, compute X
  3245.            // intercept, so that casting can begin
  3246.  
  3247.            xi = inv_tan_table[curr_ang] * (y_bound - en_y) + en_x;
  3248.  
  3249.            // set cell delta
  3250.  
  3251.            next_y_cell = -1;
  3252.  
  3253.        } // end else lower half plane
  3254.  
  3255. // S E C T I O N  3 /////////////////////////////////////////////////////////
  3256.  
  3257.     // compute first y intersection
  3258.  
  3259.     // need to know which half plane we are casting from relative to X axis
  3260.  
  3261.     if (curr_ang < ANGLE_90 || curr_ang >= ANGLE_270)
  3262.        {
  3263.  
  3264.            // compute first vertical line that could be intersected with ray
  3265.            // note: it will be to the right of player
  3266.  
  3267.            x_bound = (int)(CELL_X_SIZE + x_anded);
  3268.  
  3269.            // compute delta to get to next vertical line
  3270.  
  3271.            x_delta = CELL_X_SIZE;
  3272.  
  3273.            // based on first possible vertical intersection line, compute Y
  3274.            // intercept, so that casting can begin
  3275.  
  3276.            yi = tan_table[curr_ang] * (x_bound - en_x) + en_y;
  3277.  
  3278.            // set cell delta
  3279.  
  3280.            next_x_cell = 0;
  3281.  
  3282.        } // end if right half plane
  3283.     else
  3284.        {
  3285.  
  3286.            // compute first vertical line that could be intersected with ray
  3287.            // note: it will be to the left of player
  3288.  
  3289.            x_bound = x_anded;
  3290.  
  3291.            // compute delta to get to next vertical line
  3292.  
  3293.            x_delta = -CELL_X_SIZE;
  3294.  
  3295.            // based on first possible vertical intersection line, compute Y
  3296.            // intercept, so that casting can begin
  3297.  
  3298.            yi = tan_table[curr_ang] * (x_bound - en_x) + en_y;
  3299.  
  3300.            // set cell delta
  3301.  
  3302.            next_x_cell = -1;
  3303.  
  3304.        } // end else right half plane
  3305.  
  3306.  
  3307. // begin cast
  3308.  
  3309. //        casting       = 2;                // two rays to cast simultaneously
  3310.     xray=yray     = 0;                // reset intersection flags
  3311.  
  3312.     cell_x = ( (x_bound+next_x_cell) >> CELL_X_SIZE_FP);
  3313.  
  3314.     cell_y = (int)yi;
  3315.     cell_y>>=CELL_Y_SIZE_FP;
  3316.  
  3317.     // test if there is a block where the current x ray is intersecting
  3318.  
  3319.     if (world[cell_y][cell_x].block_type!=0)
  3320.     {
  3321.             xray = INTERSECTION_FOUND;
  3322.     }
  3323. // S E C T I O N  4 /////////////////////////////////////////////////////////
  3324.  
  3325.     while(xray!=INTERSECTION_FOUND)
  3326.     {
  3327.  
  3328.         // continue casting each ray in parallel
  3329.  
  3330.         yi += y_step[curr_ang];
  3331.  
  3332.         // find next possible x intercept point
  3333.  
  3334.         x_bound += x_delta;
  3335.  
  3336.         // compute current map position to inspect
  3337.  
  3338.         cell_x = ( (x_bound+next_x_cell) >> CELL_X_SIZE_FP);
  3339.  
  3340.         cell_y = (int)yi;
  3341.         cell_y>>=CELL_Y_SIZE_FP;
  3342.  
  3343.         // test if there is a block where the current x ray is intersecting
  3344.  
  3345.         if (world[cell_y][cell_x].block_type!=0)
  3346.         {
  3347.                 xray = INTERSECTION_FOUND;
  3348.         } // end if a hit
  3349.  
  3350.     } // end if x ray has intersected
  3351.  
  3352.     dist_x  = (long)((yi - en_y) * inv_sin_table[curr_ang]);
  3353.     yi_save = (int)yi;
  3354.     xb_save = x_bound;
  3355.  
  3356. // S E C T I O N  5 /////////////////////////////////////////////////////////
  3357.  
  3358.     cell_x = xi;
  3359.     cell_x>>=CELL_X_SIZE_FP;
  3360.  
  3361.     cell_y = ( (y_bound + next_y_cell) >> CELL_Y_SIZE_FP);
  3362.  
  3363.     // test if there is a block where the current y ray is intersecting
  3364.  
  3365.     if (world[cell_y][cell_x].block_type!=0)
  3366.     {
  3367.             yray = INTERSECTION_FOUND;
  3368.     }
  3369.  
  3370.     while (yray!=INTERSECTION_FOUND)
  3371.     {
  3372.  
  3373.         xi += x_step[curr_ang];
  3374.  
  3375.         // compute next possible y intercept
  3376.  
  3377.         y_bound += y_delta;
  3378.         // compute current map position to inspect
  3379.  
  3380.         cell_x = xi;
  3381.         cell_x>>=CELL_X_SIZE_FP;
  3382.  
  3383.         cell_y = ( (y_bound + next_y_cell) >> CELL_Y_SIZE_FP);
  3384.  
  3385.         // test if there is a block where the current y ray is intersecting
  3386.  
  3387.         if (world[cell_y][cell_x].block_type!=0)
  3388.         {
  3389.                 yray = INTERSECTION_FOUND;
  3390.         } // end if a hit
  3391.  
  3392.     } // end while not done
  3393.  
  3394.     dist_y  = (long)((xi - en_x) * inv_cos_table[curr_ang]);
  3395.     xi_save = (int)xi;
  3396.     yb_save = y_bound;
  3397.  
  3398. // S E C T I O N  6 /////////////////////////////////////////////////////////
  3399.  
  3400.     // at this point, we know that the ray has succesfully hit both a
  3401.     // vertical wall and a horizontal wall, so we need to see which one
  3402.     // was closer and then render it
  3403.  
  3404.     if ((dist_x < en_dist) || (dist_y < en_dist))
  3405.            return(0);
  3406.        else
  3407.            return(1);
  3408.  
  3409. } // end Enemy_Line_Of_Sight
  3410.  
  3411.  
  3412. void Translate_Player(long dx, long dy)
  3413. {
  3414.     long x_cell,y_cell,x_sub_cell,y_sub_cell;
  3415.  
  3416.     // test if user has bumped into a wall i.e. test if there
  3417.     // is a cell within the direction of motion, if so back up !
  3418.  
  3419.     // compute cell position
  3420.  
  3421.     x_cell = x/CELL_X_SIZE;
  3422.     y_cell = y/CELL_Y_SIZE;
  3423.  
  3424.     // compute position relative to cell
  3425.  
  3426.     x_sub_cell = x % CELL_X_SIZE;
  3427.     y_sub_cell = y % CELL_Y_SIZE;
  3428.  
  3429.  
  3430.     // test if player is bumping into a wall
  3431.      // resolve motion into it's x and y components
  3432.  
  3433.     if (dx>0 )
  3434.     {
  3435.         // moving right
  3436.  
  3437.         if ((Block_Map[y_cell][x_cell+1] != 0)   &&
  3438.             (x_sub_cell > (OVERBOARD ) ) )
  3439.         {
  3440.             // back player up amount he steped over the line
  3441.  
  3442.             x = ((x_cell)<<CELL_X_SIZE_FP) + OVERBOARD;
  3443.  
  3444.         } // end if need to back up
  3445.         else
  3446.         if ((Block_Map[y_cell+1][x_cell+1] != 0)   &&
  3447.             (x_sub_cell > (OVERBOARD ) )            &&
  3448.             (y_sub_cell > (OVERBOARD ) )            &&
  3449.             (Block_Map[y_cell+1][x_cell] == 0) )
  3450.         {
  3451.                 x = ((x_cell)<<CELL_X_SIZE_FP) + OVERBOARD;
  3452.         }
  3453.         else
  3454.         if ((Block_Map[y_cell-1][x_cell+1] != 0)   &&
  3455.             (x_sub_cell > (OVERBOARD ) )            &&
  3456.             (y_sub_cell < (CELL_Y_SIZE-OVERBOARD ) ) &&
  3457.             (Block_Map[y_cell-1][x_cell] == 0) )
  3458.         {
  3459.                 x = ((x_cell)<<CELL_X_SIZE_FP) + OVERBOARD;
  3460.         }
  3461.  
  3462.     }
  3463.     else
  3464.     {
  3465.         // moving left
  3466.  
  3467.         if ((Block_Map[y_cell][x_cell-1] != 0)  &&
  3468.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD) ) )
  3469.         {
  3470.             // back player up amount he steped over the line
  3471.  
  3472.             x = ((x_cell)<<CELL_X_SIZE_FP) + (CELL_X_SIZE-OVERBOARD);
  3473.  
  3474.         } // end if need to back up
  3475.         else
  3476.         if ((Block_Map[y_cell+1][x_cell-1] != 0)   &&
  3477.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD) )   &&
  3478.             (y_sub_cell > (OVERBOARD ) )            &&
  3479.             (Block_Map[y_cell+1][x_cell] == 0) )
  3480.         {
  3481.                x = ((x_cell)<<CELL_X_SIZE_FP) + (CELL_X_SIZE-OVERBOARD);
  3482.         }
  3483.         else
  3484.         if ((Block_Map[y_cell-1][x_cell-1] != 0)   &&
  3485.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD) )   &&
  3486.             (y_sub_cell < (CELL_Y_SIZE-OVERBOARD ) ) &&
  3487.             (Block_Map[y_cell-1][x_cell] == 0) )
  3488.         {
  3489.             x = ((x_cell)<<CELL_X_SIZE_FP) + (CELL_X_SIZE-OVERBOARD);
  3490.         }
  3491.  
  3492.  
  3493.     } // end else
  3494.  
  3495.     // compute cell position
  3496.  
  3497.     x_cell = x/CELL_X_SIZE;
  3498.     y_cell = y/CELL_Y_SIZE;
  3499.  
  3500.     // compute position relative to cell
  3501.  
  3502.     x_sub_cell = x % CELL_X_SIZE;
  3503.     y_sub_cell = y % CELL_Y_SIZE;
  3504.  
  3505.     if (dy>0 )
  3506.     {
  3507.         // moving up
  3508.  
  3509.         if ((Block_Map[(y_cell+1)][x_cell] != 0)  &&
  3510.             (y_sub_cell > ( OVERBOARD ) ) )
  3511.         {
  3512.             // back player up amount he steped over the line
  3513.  
  3514.             y = ((y_cell)<<CELL_Y_SIZE_FP) + OVERBOARD;
  3515.  
  3516.         } // end if need to back up
  3517.         else
  3518.         if ((Block_Map[(y_cell+1)][x_cell+1] != 0)  &&
  3519.             (y_sub_cell > ( OVERBOARD ) )             &&
  3520.             (x_sub_cell > (OVERBOARD) )   &&
  3521.             (Block_Map[y_cell][x_cell+1] == 0) )
  3522.         {
  3523.             // back player up amount he steped over the line
  3524.  
  3525.             y = ((y_cell)<<CELL_Y_SIZE_FP) + OVERBOARD;
  3526.  
  3527.         } // end if need to back up
  3528.         else
  3529.         if ((Block_Map[(y_cell+1)][x_cell-1] != 0)  &&
  3530.             (y_sub_cell > (OVERBOARD ) )             &&
  3531.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD ) )   &&
  3532.             (Block_Map[y_cell][x_cell-1] == 0) )
  3533.         {
  3534.             // back player up amount he steped over the line
  3535.  
  3536.             y = ((y_cell)<<CELL_Y_SIZE_FP) + OVERBOARD;
  3537.  
  3538.         } // end if need to back up
  3539.  
  3540.     }
  3541.     else
  3542.     {
  3543.         // moving down
  3544.  
  3545.         if ((Block_Map[(y_cell-1)][x_cell] != 0)  &&
  3546.             (y_sub_cell < (CELL_X_SIZE-OVERBOARD) ) )
  3547.         {
  3548.             // back player up amount he steped over the line
  3549.  
  3550.             y = ((y_cell)<<CELL_Y_SIZE_FP) + (CELL_Y_SIZE-OVERBOARD);
  3551.  
  3552.         } // end if need to back up
  3553.         else
  3554.         if ((Block_Map[(y_cell-1)][x_cell+1] != 0)  &&
  3555.             (y_sub_cell < (CELL_Y_SIZE-OVERBOARD ) ) &&
  3556.             (x_sub_cell > (OVERBOARD) )   &&
  3557.             (Block_Map[y_cell][x_cell+1] == 0) )
  3558.         {
  3559.             // back player up amount he steped over the line
  3560.  
  3561.             y = ((y_cell)<<CELL_Y_SIZE_FP) + (CELL_Y_SIZE-OVERBOARD);
  3562.  
  3563.         } // end if need to back up
  3564.         else
  3565.         if ((Block_Map[(y_cell-1)][x_cell-1] != 0)  &&
  3566.             (y_sub_cell < (CELL_Y_SIZE-OVERBOARD ) )             &&
  3567.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD ) )   &&
  3568.             (Block_Map[y_cell][x_cell-1] == 0) )
  3569.         {
  3570.             // back player up amount he steped over the line
  3571.  
  3572.             y = ((y_cell)<<CELL_Y_SIZE_FP) + (CELL_Y_SIZE-OVERBOARD);
  3573.  
  3574.         } // end if need to back up
  3575.  
  3576.     } // end else
  3577. }
  3578.  
  3579. void Translate_Enemy(int enem_num, long dx, long dy)
  3580. {
  3581.     long x_cell,y_cell,x_sub_cell,y_sub_cell;
  3582.  
  3583.     // test if user has bumped into a wall i.e. test if there
  3584.     // is a cell within the direction of motion, if so back up !
  3585.  
  3586.     // compute cell position
  3587.  
  3588.     x_cell = enemies[enem_num].vitals.x/CELL_X_SIZE;
  3589.     y_cell = enemies[enem_num].vitals.y/CELL_Y_SIZE;
  3590.  
  3591.     // compute position relative to cell
  3592.  
  3593.     x_sub_cell = enemies[enem_num].vitals.x % CELL_X_SIZE;
  3594.     y_sub_cell = enemies[enem_num].vitals.y % CELL_Y_SIZE;
  3595.  
  3596.  
  3597.     // test if player is bumping into a wall
  3598.      // resolve motion into it's x and y components
  3599.  
  3600.     if (dx>0 )
  3601.     {
  3602.         // moving right
  3603.  
  3604.         if ((Block_Map[y_cell][x_cell+1] != 0)   &&
  3605.             (x_sub_cell > (OVERBOARD_FOR_ENEMIES ) ) )
  3606.         {
  3607.             // back player up amount he steped over the line
  3608.  
  3609.             enemies[enem_num].vitals.x = ((x_cell)<<CELL_X_SIZE_FP) + OVERBOARD_FOR_ENEMIES;
  3610.  
  3611.             if (((world[y_cell][x_cell+1].block_type == 2) || (world[y_cell][x_cell+1].block_type == 3)) &&
  3612.                 ((doors[world[y_cell][x_cell+1].door_id].door_state == CLOSED) ||
  3613.                  (doors[world[y_cell][x_cell+1].door_id].door_state == CLOSING)))
  3614.             {
  3615.  
  3616.                 // make door disappear by starting process
  3617.  
  3618.                 doors[world[y_cell][x_cell+1].door_id].door_state = OPENING;
  3619.                 doors[world[y_cell][x_cell+1].door_id].door_increment += 6;
  3620.  
  3621.             }
  3622.         } // end if need to back up
  3623.         else
  3624.         if ((Block_Map[y_cell+1][x_cell+1] != 0)   &&
  3625.             (x_sub_cell > (OVERBOARD_FOR_ENEMIES ) )            &&
  3626.             (y_sub_cell > (OVERBOARD_FOR_ENEMIES ) )            &&
  3627.             (Block_Map[y_cell+1][x_cell] == 0) )
  3628.         {
  3629.                 enemies[enem_num].vitals.x = ((x_cell)<<CELL_X_SIZE_FP) + OVERBOARD_FOR_ENEMIES;
  3630.         }
  3631.         else
  3632.         if ((Block_Map[y_cell-1][x_cell+1] != 0)   &&
  3633.             (x_sub_cell > (OVERBOARD_FOR_ENEMIES ) )            &&
  3634.             (y_sub_cell < (CELL_Y_SIZE-OVERBOARD_FOR_ENEMIES ) ) &&
  3635.             (Block_Map[y_cell-1][x_cell] == 0) )
  3636.         {
  3637.                 enemies[enem_num].vitals.x = ((x_cell)<<CELL_X_SIZE_FP) + OVERBOARD_FOR_ENEMIES;
  3638.         }
  3639.  
  3640.     }
  3641.     else
  3642.     {
  3643.         // moving left
  3644.  
  3645.         if ((Block_Map[y_cell][x_cell-1] != 0)  &&
  3646.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD_FOR_ENEMIES) ) )
  3647.         {
  3648.             // back player up amount he steped over the line
  3649.  
  3650.             enemies[enem_num].vitals.x = ((x_cell)<<CELL_X_SIZE_FP) + (CELL_X_SIZE-OVERBOARD_FOR_ENEMIES);
  3651.  
  3652.             if (((world[y_cell][x_cell-1].block_type == 2) || (world[y_cell][x_cell-1].block_type == 3)) &&
  3653.                 ((doors[world[y_cell][x_cell-1].door_id].door_state == CLOSED) ||
  3654.                  (doors[world[y_cell][x_cell-1].door_id].door_state == CLOSING)))
  3655.             {
  3656.  
  3657.                 // make door disappear by starting process
  3658.  
  3659.                 doors[world[y_cell][x_cell-1].door_id].door_state = OPENING;
  3660.                 doors[world[y_cell][x_cell-1].door_id].door_increment += 6;
  3661.  
  3662.             }
  3663.         } // end if need to back up
  3664.         else
  3665.         if ((Block_Map[y_cell+1][x_cell-1] != 0)   &&
  3666.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD_FOR_ENEMIES) )   &&
  3667.             (y_sub_cell > (OVERBOARD_FOR_ENEMIES ) )            &&
  3668.             (Block_Map[y_cell+1][x_cell] == 0) )
  3669.         {
  3670.                enemies[enem_num].vitals.x = ((x_cell)<<CELL_X_SIZE_FP) + (CELL_X_SIZE-OVERBOARD_FOR_ENEMIES);
  3671.         }
  3672.         else
  3673.         if ((Block_Map[y_cell-1][x_cell-1] != 0)   &&
  3674.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD_FOR_ENEMIES) )   &&
  3675.             (y_sub_cell < (CELL_Y_SIZE-OVERBOARD_FOR_ENEMIES ) ) &&
  3676.             (Block_Map[y_cell-1][x_cell] == 0) )
  3677.         {
  3678.             enemies[enem_num].vitals.x = ((x_cell)<<CELL_X_SIZE_FP) + (CELL_X_SIZE-OVERBOARD_FOR_ENEMIES);
  3679.         }
  3680.  
  3681.  
  3682.     } // end else
  3683.  
  3684.     // compute cell position
  3685.  
  3686.     x_cell = enemies[enem_num].vitals.x/CELL_X_SIZE;
  3687.     y_cell = enemies[enem_num].vitals.y/CELL_Y_SIZE;
  3688.  
  3689.     // compute position relative to cell
  3690.  
  3691.     x_sub_cell = enemies[enem_num].vitals.x % CELL_X_SIZE;
  3692.     y_sub_cell = enemies[enem_num].vitals.y % CELL_Y_SIZE;
  3693.  
  3694.     if (dy>0 )
  3695.     {
  3696.         // moving up
  3697.  
  3698.         if ((Block_Map[(y_cell+1)][x_cell] != 0)  &&
  3699.             (y_sub_cell > ( OVERBOARD_FOR_ENEMIES ) ) )
  3700.         {
  3701.             // back player up amount he steped over the line
  3702.  
  3703.             enemies[enem_num].vitals.y = ((y_cell)<<CELL_Y_SIZE_FP) + OVERBOARD_FOR_ENEMIES;
  3704.  
  3705.             if (((world[y_cell+1][x_cell].block_type == 2) || (world[y_cell+1][x_cell].block_type == 3)) &&
  3706.                 ((doors[world[y_cell+1][x_cell].door_id].door_state == CLOSED) ||
  3707.                  (doors[world[y_cell+1][x_cell].door_id].door_state == CLOSING)))
  3708.             {
  3709.  
  3710.                 // make door disappear by starting process
  3711.  
  3712.                 doors[world[y_cell+1][x_cell].door_id].door_state = OPENING;
  3713.                 doors[world[y_cell+1][x_cell].door_id].door_increment += 6;
  3714.  
  3715.             }
  3716.         } // end if need to back up
  3717.         else
  3718.         if ((Block_Map[(y_cell+1)][x_cell+1] != 0)  &&
  3719.             (y_sub_cell > ( OVERBOARD_FOR_ENEMIES ) )             &&
  3720.             (x_sub_cell > (OVERBOARD_FOR_ENEMIES) )   &&
  3721.             (Block_Map[y_cell][x_cell+1] == 0) )
  3722.         {
  3723.             // back player up amount he steped over the line
  3724.  
  3725.             enemies[enem_num].vitals.y = ((y_cell)<<CELL_Y_SIZE_FP) + OVERBOARD_FOR_ENEMIES;
  3726.  
  3727.         } // end if need to back up
  3728.         else
  3729.         if ((Block_Map[(y_cell+1)][x_cell-1] != 0)  &&
  3730.             (y_sub_cell > (OVERBOARD_FOR_ENEMIES ) )             &&
  3731.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD_FOR_ENEMIES ) )   &&
  3732.             (Block_Map[y_cell][x_cell-1] == 0) )
  3733.         {
  3734.             // back player up amount he steped over the line
  3735.  
  3736.             enemies[enem_num].vitals.y = ((y_cell)<<CELL_Y_SIZE_FP) + OVERBOARD_FOR_ENEMIES;
  3737.  
  3738.         } // end if need to back up
  3739.  
  3740.     }
  3741.     else
  3742.     {
  3743.         // moving down
  3744.  
  3745.         if ((Block_Map[(y_cell-1)][x_cell] != 0)  &&
  3746.             (y_sub_cell < (CELL_X_SIZE-OVERBOARD_FOR_ENEMIES) ) )
  3747.         {
  3748.             // back player up amount he steped over the line
  3749.  
  3750.             enemies[enem_num].vitals.y = ((y_cell)<<CELL_Y_SIZE_FP) + (CELL_Y_SIZE-OVERBOARD_FOR_ENEMIES);
  3751.  
  3752.             if (((world[y_cell-1][x_cell].block_type == 2) || (world[y_cell-1][x_cell].block_type == 3)) &&
  3753.                 ((doors[world[y_cell-1][x_cell].door_id].door_state == CLOSED) ||
  3754.                  (doors[world[y_cell-1][x_cell].door_id].door_state == CLOSING)))
  3755.             {
  3756.  
  3757.                 // make door disappear by starting process
  3758.  
  3759.                 doors[world[y_cell-1][x_cell].door_id].door_state = OPENING;
  3760.                 doors[world[y_cell-1][x_cell].door_id].door_increment += 6;
  3761.  
  3762.             }
  3763.         } // end if need to back up
  3764.         else
  3765.         if ((Block_Map[(y_cell-1)][x_cell+1] != 0)  &&
  3766.             (y_sub_cell < (CELL_Y_SIZE-OVERBOARD_FOR_ENEMIES ) ) &&
  3767.             (x_sub_cell > (OVERBOARD_FOR_ENEMIES) )   &&
  3768.             (Block_Map[y_cell][x_cell+1] == 0) )
  3769.         {
  3770.             // back player up amount he steped over the line
  3771.  
  3772.             enemies[enem_num].vitals.y = ((y_cell)<<CELL_Y_SIZE_FP) + (CELL_Y_SIZE-OVERBOARD_FOR_ENEMIES);
  3773.  
  3774.         } // end if need to back up
  3775.         else
  3776.         if ((Block_Map[(y_cell-1)][x_cell-1] != 0)  &&
  3777.             (y_sub_cell < (CELL_Y_SIZE-OVERBOARD_FOR_ENEMIES ) )             &&
  3778.             (x_sub_cell < (CELL_X_SIZE-OVERBOARD_FOR_ENEMIES ) )   &&
  3779.             (Block_Map[y_cell][x_cell-1] == 0) )
  3780.         {
  3781.             // back player up amount he steped over the line
  3782.  
  3783.             enemies[enem_num].vitals.y = ((y_cell)<<CELL_Y_SIZE_FP) + (CELL_Y_SIZE-OVERBOARD_FOR_ENEMIES);
  3784.  
  3785.         } // end if need to back up
  3786.  
  3787.     } // end else
  3788. }
  3789.  
  3790.  
  3791. void Draw_ReDraw_Frame(void)
  3792. {
  3793.     // DRAW LINES FOR TOP OF VIEWPORT
  3794.  
  3795.     Line_H_Mode_Y(WINDOW_LEFT-4,WINDOW_RIGHT+3,WINDOW_TOP-4,BORDER_COLOR_1);
  3796.     Line_H_Mode_Y(WINDOW_LEFT-3,WINDOW_RIGHT+2,WINDOW_TOP-3,BORDER_COLOR_2);
  3797.     Line_H_Mode_Y(WINDOW_LEFT-2,WINDOW_RIGHT+1,WINDOW_TOP-2,BORDER_COLOR_3);
  3798.     Line_H_Mode_Y(WINDOW_LEFT-1,WINDOW_RIGHT,WINDOW_TOP-1,BORDER_COLOR_4);
  3799.  
  3800.     // DRAW LINES FOR BOTTOM OF VIEWPORT
  3801.  
  3802.     Line_H_Mode_Y(WINDOW_LEFT-4,WINDOW_RIGHT+3,WINDOW_BOTTOM+3,BORDER_COLOR_1);
  3803.     Line_H_Mode_Y(WINDOW_LEFT-3,WINDOW_RIGHT+2,WINDOW_BOTTOM+2,BORDER_COLOR_2);
  3804.     Line_H_Mode_Y(WINDOW_LEFT-2,WINDOW_RIGHT+1,WINDOW_BOTTOM+1,BORDER_COLOR_3);
  3805.     Line_H_Mode_Y(WINDOW_LEFT-1,WINDOW_RIGHT,WINDOW_BOTTOM,BORDER_COLOR_4);
  3806.  
  3807.     // DRAW LINES FOR LEFT OF VIEWPORT
  3808.  
  3809.     Line_V_Mode_Y(WINDOW_TOP-4,WINDOW_BOTTOM+3,WINDOW_LEFT-4,BORDER_COLOR_1);
  3810.     Line_V_Mode_Y(WINDOW_TOP-3,WINDOW_BOTTOM+2,WINDOW_LEFT-3,BORDER_COLOR_2);
  3811.     Line_V_Mode_Y(WINDOW_TOP-2,WINDOW_BOTTOM+1,WINDOW_LEFT-2,BORDER_COLOR_3);
  3812.     Line_V_Mode_Y(WINDOW_TOP-1,WINDOW_BOTTOM,WINDOW_LEFT-1,BORDER_COLOR_4);
  3813.  
  3814.     // DRAW LINES FOR RIGHT OF VIEWPORT
  3815.  
  3816.     Line_V_Mode_Y(WINDOW_TOP-4,WINDOW_BOTTOM+3,WINDOW_RIGHT+3,BORDER_COLOR_1);
  3817.     Line_V_Mode_Y(WINDOW_TOP-3,WINDOW_BOTTOM+2,WINDOW_RIGHT+2,BORDER_COLOR_2);
  3818.     Line_V_Mode_Y(WINDOW_TOP-2,WINDOW_BOTTOM+1,WINDOW_RIGHT+1,BORDER_COLOR_3);
  3819.     Line_V_Mode_Y(WINDOW_TOP-1,WINDOW_BOTTOM,WINDOW_RIGHT,BORDER_COLOR_4);
  3820. } // end Draw_ReDraw_Frame
  3821.  
  3822. int Parse_Commands(int argc, char **argv)
  3823. {
  3824. // this function is used to parse the commands line parameters that are to be
  3825. // used as switched to enable different modes of operation
  3826.  
  3827. int index;  // looping variable
  3828. int a_flag = 1;
  3829.  
  3830. for (index=1; index<argc; index++)
  3831.     {
  3832.     // get the first character from the string
  3833.  
  3834.     switch(argv[index][0])
  3835.           {
  3836.  
  3837.           case 's': // enable sound effects
  3838.           case 'S':
  3839.                {
  3840.                digital_enabled=1;
  3841.                } break;
  3842.  
  3843.           case 'm': // enable nusic
  3844.           case 'M':
  3845.                {
  3846.                music_enabled=1;
  3847.  
  3848.                } break;
  3849.  
  3850.           // more commands would go here...
  3851.  
  3852.           case 'a': // enable nusic
  3853.           case 'A':
  3854.                {
  3855.                a_flag=0;
  3856.  
  3857.                } break;
  3858.  
  3859.           default:break;
  3860.  
  3861.           } // end switch
  3862.  
  3863.     } // end for index
  3864.  
  3865.     return(a_flag);
  3866. } // end Parse_Commands
  3867.  
  3868. void Update_Weapon_Statis_Display(int nw_wp_stat)
  3869. {
  3870.     unsigned char far *buffer;
  3871.  
  3872.     int x_index, y_index;
  3873.  
  3874.     _asm
  3875.     {
  3876.         mov dx,SEQUENCER          // address the sequencer
  3877.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  3878.         mov ah,0eh                // enable last three planes
  3879.         out dx,ax                 // do it baby!
  3880.     } // end inline asm
  3881.  
  3882.  
  3883.     for (x_index = 0; x_index < 56; x_index+=4)
  3884.     {
  3885.         for (y_index = 0; y_index<3; y_index++)
  3886.         {
  3887.             buffer = pagey_0_buffer + ((169+y_index)<<6) +
  3888.                         ((169+y_index)<<4) + ((216+x_index)>>2);
  3889.  
  3890.             if ((x_index>>2) < nw_wp_stat)
  3891.                 *buffer = Ammo_Color;
  3892.             else
  3893.                 *buffer = 0;
  3894.         }
  3895.     }
  3896.  
  3897.     for (x_index = 0; x_index < 56; x_index+=4)
  3898.     {
  3899.         for (y_index = 0; y_index<3; y_index++)
  3900.         {
  3901.             buffer = pagey_1_buffer + ((169+y_index)<<6) +
  3902.                         ((169+y_index)<<4) + ((216+x_index)>>2);
  3903.  
  3904.             if ((x_index>>2) < nw_wp_stat)
  3905.                 *buffer = Ammo_Color;
  3906.             else
  3907.                 *buffer = 0;
  3908.         }
  3909.     }
  3910.  
  3911. } // end Update_Weapon_Statis_Display
  3912.  
  3913. void Update_Life_Statis_Display(int nw_life_stat)
  3914. {
  3915.     unsigned char far *buffer;
  3916.  
  3917.     int x_index, y_index;
  3918.  
  3919.     _asm
  3920.     {
  3921.         mov dx,SEQUENCER          // address the sequencer
  3922.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  3923.         mov ah,0eh                // enable last three planes
  3924.         out dx,ax                 // do it baby!
  3925.     } // end inline asm
  3926.  
  3927.  
  3928.     for (x_index = 0; x_index < 120; x_index+=4)
  3929.     {
  3930.         for (y_index = 0; y_index<3; y_index++)
  3931.         {
  3932.             buffer = pagey_0_buffer + ((185+y_index)<<6) +
  3933.                         ((185+y_index)<<4) + ((184+x_index)>>2);
  3934.  
  3935.             if ((x_index>>2) < nw_life_stat)
  3936.                 *buffer = Vitality_Color;
  3937.             else
  3938.                 *buffer = 0;
  3939.         }
  3940.     }
  3941.  
  3942.     for (x_index = 0; x_index < 120; x_index+=4)
  3943.     {
  3944.         for (y_index = 0; y_index<3; y_index++)
  3945.         {
  3946.             buffer = pagey_1_buffer + ((185+y_index)<<6) +
  3947.                         ((185+y_index)<<4) + ((184+x_index)>>2);
  3948.  
  3949.             if ((x_index>>2) < nw_life_stat)
  3950.                 *buffer = Vitality_Color;
  3951.             else
  3952.                 *buffer = 0;
  3953.         }
  3954.     }
  3955.  
  3956. } // end Update_Life_Statis_Display
  3957.  
  3958. void Load_PCX_and_Page_Flip(char *filename, int load_palette_or_not)
  3959. {
  3960.     Wait_Retrace_Mode();
  3961.  
  3962.     Set_Working_Page_Mode_Y(mode_y_page);
  3963.  
  3964.     PCX_Init((pcx_picture_ptr)&image_pcx);
  3965.  
  3966.     // load in the textures
  3967.  
  3968.     PCX_Load((char *)filename, (pcx_picture_ptr)&image_pcx,load_palette_or_not);
  3969.  
  3970.     PCX_Copy_To_Buffer_XYZ_Mode((pcx_picture_ptr)&image_pcx, video_buffer);
  3971.  
  3972.     PCX_Delete((pcx_picture_ptr)&image_pcx);
  3973.  
  3974.     Wait_Display_Mode();
  3975.  
  3976.     Set_Visual_Page_Mode_Y_Half(mode_y_page);
  3977.  
  3978.     mode_y_page = !mode_y_page;
  3979. } // end Load_PCX_and_Page_Flip
  3980.  
  3981. void Fade_to_Black_and_Paint_Both(int effect)
  3982. {
  3983.     if (effect == SCREEN_DARKNESS)
  3984.         Screen_Transition(SCREEN_DARKNESS);
  3985.     else
  3986.         Screen_Transition(FULL_SCREEN_DARKNESS);
  3987.  
  3988.     Wait_Retrace_Mode();
  3989.  
  3990.     Set_Working_Page_Mode_Y(mode_y_page);
  3991.  
  3992.     outp(SEQUENCER,SEQ_PLANE_ENABLE);
  3993.     outp(SEQUENCER+1,0x0f);
  3994.  
  3995.     // clear the screen, remember it is 320x200, but that is divided into four
  3996.     // planes, hence we need only to clear 16k out since there will be four planes
  3997.     // each being cleared in parallel for a total of 4*16k or 64 = 320x200
  3998.     // note: "k" in this example means 1000 not 1024
  3999.  
  4000.     _asm
  4001.     {
  4002.  
  4003.         les di,video_buffer   // point es:di to video buffer, same addre for mode Y
  4004.         xor ax,ax             // move a zero into al and ah
  4005.         mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  4006.         rep stosw             // move the color into the video buffer really fast!
  4007.  
  4008.     } // end inline asm
  4009.  
  4010.     Wait_Display_Mode();
  4011.  
  4012.     Set_Visual_Page_Mode_Y_Half(mode_y_page);
  4013.  
  4014.     mode_y_page = !mode_y_page;
  4015.  
  4016.     Wait_Retrace_Mode();
  4017.  
  4018.     Set_Working_Page_Mode_Y(mode_y_page);
  4019.  
  4020.     outp(SEQUENCER,SEQ_PLANE_ENABLE);
  4021.     outp(SEQUENCER+1,0x0f);
  4022.  
  4023.     // clear the screen, remember it is 320x200, but that is divided into four
  4024.     // planes, hence we need only to clear 16k out since there will be four planes
  4025.     // each being cleared in parallel for a total of 4*16k or 64 = 320x200
  4026.     // note: "k" in this example means 1000 not 1024
  4027.  
  4028.     _asm
  4029.     {
  4030.  
  4031.         les di,video_buffer   // point es:di to video buffer, same addre for mode Y
  4032.         xor ax,ax             // move a zero into al and ah
  4033.         mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  4034.         rep stosw             // move the color into the video buffer really fast!
  4035.  
  4036.     } // end inline asm
  4037.  
  4038. } // end Fade_to_Black_and_Paint_Both
  4039.  
  4040. void Paint_All_Four_Black(void)
  4041. {
  4042.     Wait_Retrace_Mode();
  4043.  
  4044.     Set_Working_Page_Mode_Y(PAGE_0);
  4045.  
  4046.     outp(SEQUENCER,SEQ_PLANE_ENABLE);
  4047.     outp(SEQUENCER+1,0x0f);
  4048.  
  4049.     // clear the screen, remember it is 320x200, but that is divided into four
  4050.     // planes, hence we need only to clear 16k out since there will be four planes
  4051.     // each being cleared in parallel for a total of 4*16k or 64 = 320x200
  4052.     // note: "k" in this example means 1000 not 1024
  4053.  
  4054.     _asm
  4055.     {
  4056.  
  4057.         les di,video_buffer   // point es:di to video buffer, same addre for mode Z
  4058.         xor ax,ax             // move a zero into al and ah
  4059.         mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  4060.         rep stosw             // move the color into the video buffer really fast!
  4061.  
  4062.     } // end inline asm
  4063.  
  4064.     Wait_Retrace_Mode();
  4065.  
  4066.     Set_Working_Page_Mode_Y(PAGE_1);
  4067.  
  4068.     outp(SEQUENCER,SEQ_PLANE_ENABLE);
  4069.     outp(SEQUENCER+1,0x0f);
  4070.  
  4071.     // clear the screen, remember it is 320x200, but that is divided into four
  4072.     // planes, hence we need only to clear 16k out since there will be four planes
  4073.     // each being cleared in parallel for a total of 4*16k or 64 = 320x200
  4074.     // note: "k" in this example means 1000 not 1024
  4075.  
  4076.     _asm
  4077.     {
  4078.  
  4079.         les di,video_buffer   // point es:di to video buffer, same addre for mode Z
  4080.         xor ax,ax             // move a zero into al and ah
  4081.         mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  4082.         rep stosw             // move the color into the video buffer really fast!
  4083.  
  4084.     } // end inline asm
  4085.  
  4086.     Wait_Retrace_Mode();
  4087.  
  4088.     Set_Working_Page_Mode_Y(PAGE_2);
  4089.  
  4090.     outp(SEQUENCER,SEQ_PLANE_ENABLE);
  4091.     outp(SEQUENCER+1,0x0f);
  4092.  
  4093.     // clear the screen, remember it is 320x200, but that is divided into four
  4094.     // planes, hence we need only to clear 16k out since there will be four planes
  4095.     // each being cleared in parallel for a total of 4*16k or 64 = 320x200
  4096.     // note: "k" in this example means 1000 not 1024
  4097.  
  4098.     _asm
  4099.     {
  4100.  
  4101.         les di,video_buffer   // point es:di to video buffer, same addre for mode Y
  4102.         xor ax,ax             // move a zero into al and ah
  4103.         mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  4104.         rep stosw             // move the color into the video buffer really fast!
  4105.  
  4106.     } // end inline asm
  4107.  
  4108.     Wait_Retrace_Mode();
  4109.  
  4110.     Set_Working_Page_Mode_Y(PAGE_3);
  4111.  
  4112.     outp(SEQUENCER,SEQ_PLANE_ENABLE);
  4113.     outp(SEQUENCER+1,0x0f);
  4114.  
  4115.     // clear the screen, remember it is 320x200, but that is divided into four
  4116.     // planes, hence we need only to clear 16k out since there will be four planes
  4117.     // each being cleared in parallel for a total of 4*16k or 64 = 320x200
  4118.     // note: "k" in this example means 1000 not 1024
  4119.  
  4120.     _asm
  4121.     {
  4122.  
  4123.         les di,video_buffer   // point es:di to video buffer, same addre for mode Z
  4124.         xor ax,ax             // move a zero into al and ah
  4125.         mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  4126.         rep stosw             // move the color into the video buffer really fast!
  4127.  
  4128.     } // end inline asm
  4129.  
  4130.     Wait_Retrace_Mode();
  4131.  
  4132.     Set_Working_Page_Mode_Y(mode_y_page);
  4133.  
  4134. } // end Paint_All_Four_Black
  4135.  
  4136. void Setup_Initial_Display(void)
  4137. {
  4138.     int index;
  4139.  
  4140.     Wait_Display_Mode();
  4141.  
  4142.     Set_Visual_Page_Mode_Y_Half(mode_y_page);
  4143.  
  4144.     mode_y_page = !mode_y_page;
  4145.  
  4146.     Wait_Retrace_Mode();
  4147.  
  4148.     Set_Working_Page_Mode_Y(mode_y_page);
  4149.  
  4150.     Copy_From_Unseen_Vram_to_Page(pagey_0_buffer, video_buffer, 200);
  4151.  
  4152.     Draw_ReDraw_Frame();
  4153.  
  4154.     _asm
  4155.     {
  4156.         mov dx,SEQUENCER          // address the sequencer
  4157.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  4158.         mov ah,0fh                // enable all four planes
  4159.         out dx,ax                 // do it baby!
  4160.     } // end inline asm
  4161.  
  4162.     for (index=WINDOW_TOP; index < WINDOW_MIDDLE; index++)
  4163.     {
  4164.         fwordset(video_buffer + (index<<6) + (index<<4) + (WINDOW_LEFT>>2),
  4165.                     0,((WINDOW_RIGHT-WINDOW_LEFT)>>3));
  4166.     }
  4167.     for (index=WINDOW_MIDDLE; index < WINDOW_BOTTOM; index++)
  4168.     {
  4169.         fwordset(video_buffer + (index<<6) + (index<<4) + (WINDOW_LEFT>>2),
  4170.                     color_1,((WINDOW_RIGHT-WINDOW_LEFT)>>3));
  4171.     }
  4172. } // end Setup_Initial_Display
  4173.  
  4174. void Erase_Scene(void)
  4175. {
  4176.     int index;
  4177.  
  4178.     _asm
  4179.     {
  4180.         mov dx,SEQUENCER          // address the sequencer
  4181.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  4182.         mov ah,0fh                // enable all four planes
  4183.         out dx,ax                 // do it baby!
  4184.         les di,video_buffer
  4185.     } // end inline asm
  4186.  
  4187.     for (index=WINDOW_TOP; index < WINDOW_MIDDLE; index++)
  4188.     {
  4189.         fwordset(video_buffer + (index<<6) + (index<<4) + (WINDOW_LEFT>>2),
  4190.                     0,((WINDOW_RIGHT-WINDOW_LEFT)>>3));
  4191.     }
  4192.     for (index=WINDOW_MIDDLE; index < WINDOW_BOTTOM; index++)
  4193.     {
  4194.         fwordset(video_buffer + (index<<6) + (index<<4) + (WINDOW_LEFT>>2),
  4195.                     color_1,((WINDOW_RIGHT-WINDOW_LEFT)>>3));
  4196.     }
  4197.  
  4198. } // end Erase_Scene
  4199.  
  4200. long Angle_Between(long play_x, long play_y, long enem_x, long enem_y, int enem_num)
  4201. {
  4202.     long x_away, y_away;
  4203.     long difference_x, difference_y;
  4204.     long total_dist;
  4205.     long new_obj_angle;
  4206.  
  4207.     x_away = x-enem_x;
  4208.     y_away = y-enem_y;
  4209.  
  4210.  
  4211.     if ((x_away>1000) || (x_away < -1000)) return(ANGLE_0);
  4212.  
  4213.     if ((y_away>1000) || (y_away < -1000)) return(ANGLE_0);
  4214.  
  4215.     if ((y_away == 0) && (x_away == 0))
  4216.         return(ANGLE_0);
  4217.  
  4218.     if (y_away == 0)
  4219.     {
  4220.         if (x_away < 0)
  4221.             return(ANGLE_0);
  4222.         else
  4223.         if (x_away > 0)
  4224.             return(ANGLE_180);
  4225.        }
  4226.     else
  4227.     if (x_away == 0)
  4228.     {
  4229.         if (y_away < 0)
  4230.             return(ANGLE_90);
  4231.         else
  4232.         if (y_away > 0)
  4233.             return(ANGLE_270);
  4234.     }
  4235.     else
  4236.     {
  4237.         new_obj_angle = (long)((atan((double)abs(y_away)/(double)abs(x_away)))*(RAD_TO_DEG));
  4238.  
  4239.         if (x_away > 0)
  4240.         {
  4241.             if(y_away > 0)
  4242.                 new_obj_angle = ANGLE_180+new_obj_angle;
  4243.             else
  4244.             if(y_away < 0)
  4245.                 new_obj_angle = ANGLE_180-new_obj_angle;
  4246.         }
  4247.         else
  4248.         if (x_away < 0)
  4249.         {
  4250.             if(y_away > 0)
  4251.                 new_obj_angle = ANGLE_360-new_obj_angle;
  4252.  
  4253.         }
  4254.     }
  4255.  
  4256.     return(new_obj_angle);
  4257.  
  4258. }
  4259.  
  4260. void Find_Object_Distance(void)
  4261. {
  4262. // I packed alot of junk into this routine...
  4263.  
  4264. // finding the fixed objects' distances from the player is done at the
  4265. // very beginning of this "function"...
  4266.  
  4267. // then... if the user gets REAL CLOSE to an object that can be
  4268. // picked up (ammo, food, or gun upgrade) some other work has to be done...
  4269.  
  4270. // I suppose using a linked-list for objects would have been easier,
  4271. // but I've been out of school for a while, and even though I used to
  4272. // be a wiz at linked list related things - I need a memory refresher - badly!
  4273.  
  4274. // if an object is picked up, the entire array of object structures is rotated
  4275. // up one notch, from the item picked up, to the end of the object list
  4276. // - including enemies.
  4277.  
  4278.     long diff_x, diff_y;
  4279.     int index;
  4280.     int data_move_indice;
  4281.     int skip_it;
  4282.  
  4283.     for (index = 0; index < (Number_Of_Fixed_Objects); index++)
  4284.     {
  4285.  
  4286.         skip_it = 0;
  4287.  
  4288.         diff_x = x - object_list[index].x;
  4289.         diff_y = y - object_list[index].y;
  4290.  
  4291.         object_list[index].dist = (long)(sqrt((diff_x * diff_x) + (diff_y * diff_y)));
  4292.  
  4293.         if (object_list[index].dist < 30L)
  4294.         {
  4295.             if ((object_list[index].kind_of_object == 4) ||
  4296.                 (object_list[index].kind_of_object == 5) ||
  4297.                 (object_list[index].kind_of_object == 6))
  4298.             {
  4299.                 what_obj = object_list[index].kind_of_object;
  4300.  
  4301.                 if (object_list[index].kind_of_object == 4)
  4302.                 {
  4303.                     if (Player_Ammo == 56)
  4304.                         skip_it = 1;
  4305.  
  4306.                     Player_Ammo += 8;
  4307.  
  4308.                     if (Player_Ammo>56)
  4309.                         Player_Ammo = 56;
  4310.                 }
  4311.  
  4312.                 if (object_list[index].kind_of_object == 5)
  4313.                     Got_Rapid_Fire = 1;
  4314.  
  4315.                 if (object_list[index].kind_of_object == 6)
  4316.                 {
  4317.                     if (Player_Strength == 120)
  4318.                         skip_it = 1;
  4319.  
  4320.                     Player_Strength += 15;
  4321.                     if (Player_Strength > 120)
  4322.                         Player_Strength = 120;
  4323.                 }
  4324.  
  4325.                 if (!skip_it)
  4326.                 {
  4327.                      --Number_Of_Fixed_Objects;
  4328.  
  4329.                     for(data_move_indice = index;
  4330.                         data_move_indice < (Number_Of_Fixed_Objects);
  4331.                         data_move_indice++)
  4332.                     {
  4333.                         object_list[data_move_indice].kind_of_object = object_list[data_move_indice+1].kind_of_object;
  4334.                         object_list[data_move_indice].x = object_list[data_move_indice+1].x;
  4335.                         object_list[data_move_indice].y = object_list[data_move_indice+1].y;
  4336.                         object_list[data_move_indice].dist = object_list[data_move_indice+1].dist;
  4337.                         object_list[data_move_indice].angle = object_list[data_move_indice+1].angle;
  4338.                         object_list[data_move_indice].id_number = object_list[data_move_indice+1].id_number;
  4339.  
  4340.                         initial_object_list[data_move_indice].kind_of_object = initial_object_list[data_move_indice+1].kind_of_object;
  4341.                         initial_object_list[data_move_indice].x = initial_object_list[data_move_indice+1].x;
  4342.                         initial_object_list[data_move_indice].y = initial_object_list[data_move_indice+1].y;
  4343.                         initial_object_list[data_move_indice].dist = initial_object_list[data_move_indice+1].dist;
  4344.                         initial_object_list[data_move_indice].angle = initial_object_list[data_move_indice+1].angle;
  4345.                         initial_object_list[data_move_indice].id_number = initial_object_list[data_move_indice+1].id_number;
  4346.                      }
  4347.  
  4348.                      for (data_move_indice = Number_Of_Fixed_Objects; data_move_indice <= (Number_Of_Fixed_Objects+Number_Of_Enemies); data_move_indice++)
  4349.                      {
  4350.                         object_list[data_move_indice].x =
  4351.                                 enemies[data_move_indice-Number_Of_Fixed_Objects].vitals.x;
  4352.  
  4353.                         object_list[data_move_indice].y =
  4354.                                 enemies[data_move_indice-Number_Of_Fixed_Objects].vitals.y;
  4355.  
  4356.                         object_list[data_move_indice].angle =
  4357.                                 enemies[data_move_indice-Number_Of_Fixed_Objects].vitals.angle;
  4358.  
  4359.                         object_list[data_move_indice].kind_of_object =
  4360.                                 enemies[data_move_indice-Number_Of_Fixed_Objects].vitals.kind_of_object;
  4361.  
  4362.                         object_list[data_move_indice].dist =
  4363.                                 enemies[data_move_indice-Number_Of_Fixed_Objects].vitals.dist;
  4364.  
  4365.                         object_list[data_move_indice].id_number =
  4366.                                 enemies[data_move_indice-Number_Of_Fixed_Objects].enem_num;
  4367.  
  4368.                      }
  4369.  
  4370.                      --index;
  4371.  
  4372.                      just_grabbed_something = 1;
  4373.  
  4374.                 } // end if you grabbed an object!
  4375.  
  4376.             }
  4377.         }
  4378.     }
  4379.  
  4380.     for ( ; index<(Number_Of_Fixed_Objects+Number_Of_Enemies); index++)
  4381.     {
  4382.         diff_x = x - object_list[index].x;
  4383.         diff_y = y - object_list[index].y;
  4384.  
  4385.         object_list[index].dist = (long)(sqrt((diff_x * diff_x) + (diff_y * diff_y)));
  4386.  
  4387.     }
  4388. }
  4389.  
  4390. long Find_Object_Distance_Special(int NUMBER)
  4391. {
  4392.     long diff_x, diff_y;
  4393.     long Boogie;
  4394.  
  4395.     diff_x = x - enemies[NUMBER].vitals.x;
  4396.     diff_y = y - enemies[NUMBER].vitals.y;
  4397.  
  4398.     Boogie = (long)(sqrt((diff_x * diff_x) + (diff_y * diff_y)));
  4399.  
  4400.     return(Boogie);
  4401. }
  4402.  
  4403. int Object_Sort_Function(objects *arg1, objects *arg2)
  4404. {
  4405. // this function comapares the average z's of two object and is used by the
  4406. // depth sort surface ordering algorithm
  4407.  
  4408.     long obj_1;
  4409.     long obj_2;
  4410.  
  4411.     // dereference the poly pointers
  4412.  
  4413.     obj_1 = arg1->dist;
  4414.     obj_2 = arg2->dist;
  4415.  
  4416.     if (obj_1 > obj_2)
  4417.         return(1);
  4418.     if (obj_1 < obj_2)
  4419.         return(-1);
  4420.     else
  4421.         return(0);
  4422.  
  4423. }
  4424.  
  4425. void Sort_Object_List(void)
  4426. {
  4427.     qsort( (void *)object_list, (Number_Of_Fixed_Objects+Number_Of_Enemies), sizeof( objects ), Object_Sort_Function );
  4428. }
  4429.  
  4430. void Init_Objects(void)
  4431. {
  4432.     obj_statistic_list[0].width_factor = .66;
  4433.     obj_statistic_list[0].Is_Multi_View = 0;
  4434.     obj_statistic_list[0].Is_Half_Height = 0;
  4435.     obj_statistic_list[0].Scale_Factor = 21L<<16;
  4436.  
  4437.     obj_statistic_list[1].width_factor = 1.00;
  4438.     obj_statistic_list[1].Is_Multi_View = 0;
  4439.     obj_statistic_list[1].Is_Half_Height = 0;
  4440.     obj_statistic_list[1].Scale_Factor = 64L<<16;
  4441.  
  4442.     obj_statistic_list[2].width_factor = .75;
  4443.     obj_statistic_list[2].Is_Multi_View = 1;
  4444.     obj_statistic_list[2].Is_Half_Height = 1;
  4445.     obj_statistic_list[2].Scale_Factor = 32L<<16;
  4446.  
  4447.     obj_statistic_list[3].width_factor = .75;
  4448.     obj_statistic_list[3].Is_Multi_View = 1;
  4449.     obj_statistic_list[3].Is_Half_Height = 1;
  4450.     obj_statistic_list[3].Scale_Factor = 32L<<16;
  4451.  
  4452.     obj_statistic_list[4].width_factor = .75;
  4453.     obj_statistic_list[4].Is_Multi_View = 0;
  4454.     obj_statistic_list[4].Is_Half_Height = 1;
  4455.     obj_statistic_list[4].Scale_Factor = 32L<<16;
  4456.  
  4457.     obj_statistic_list[5].width_factor = .75;
  4458.     obj_statistic_list[5].Is_Multi_View = 0;
  4459.     obj_statistic_list[5].Is_Half_Height = 1;
  4460.     obj_statistic_list[5].Scale_Factor = 32L<<16;
  4461.  
  4462.     obj_statistic_list[6].width_factor = .75;
  4463.     obj_statistic_list[6].Is_Multi_View = 0;
  4464.     obj_statistic_list[6].Is_Half_Height = 1;
  4465.     obj_statistic_list[6].Scale_Factor = 32L<<16;
  4466.  
  4467.     object_list           = (objects *)malloc(sizeof(objects) * (MAX_OBJECTS+1) );
  4468.     initial_object_list = (objects *)malloc(sizeof(objects) * (MAX_OBJECTS+1) );
  4469.     enemies                = (enemy_objects *)malloc(sizeof(enemy_objects) * (MAX_ENEMIES+1) );
  4470.  
  4471. } // end Init_Objects
  4472.  
  4473. void Begin_Object_List(void)
  4474. {
  4475.     int looper;
  4476.  
  4477.     for (looper = 0; looper < Number_Of_Fixed_Objects; looper++)
  4478.     {
  4479.         object_list[looper].x =
  4480.                 initial_object_list[looper].x;
  4481.  
  4482.         object_list[looper].y =
  4483.                 initial_object_list[looper].y;
  4484.  
  4485.         object_list[looper].angle =
  4486.                 initial_object_list[looper].angle;
  4487.  
  4488.         object_list[looper].kind_of_object =
  4489.                 initial_object_list[looper].kind_of_object;
  4490.  
  4491.         object_list[looper].dist =
  4492.                 initial_object_list[looper].dist;
  4493.  
  4494.      }
  4495.  
  4496.      for (looper = Number_Of_Fixed_Objects; looper < (Number_Of_Fixed_Objects+Number_Of_Enemies); looper++)
  4497.      {
  4498.         object_list[looper].x =
  4499.                 enemies[looper-Number_Of_Fixed_Objects].vitals.x;
  4500.  
  4501.         object_list[looper].y =
  4502.                 enemies[looper-Number_Of_Fixed_Objects].vitals.y;
  4503.  
  4504.         object_list[looper].angle =
  4505.                 enemies[looper-Number_Of_Fixed_Objects].vitals.angle;
  4506.  
  4507.         object_list[looper].kind_of_object =
  4508.                 enemies[looper-Number_Of_Fixed_Objects].vitals.kind_of_object;
  4509.  
  4510.         object_list[looper].dist =
  4511.                 enemies[looper-Number_Of_Fixed_Objects].vitals.dist;
  4512.  
  4513.         object_list[looper].id_number =
  4514.                 enemies[looper-Number_Of_Fixed_Objects].enem_num;
  4515.  
  4516.      }
  4517. } // end Begin_Object_List
  4518.  
  4519. void Load_64x64_Sprites(sprite_ptr sprite_set, char *filename, int num_cells)
  4520. {
  4521.     int index, sprite_row, sprite_column;
  4522.     int set = 1;
  4523.  
  4524.     PCX_Init((pcx_picture_ptr)&image_pcx);
  4525.  
  4526.     PCX_Load(filename, (pcx_picture_ptr)&image_pcx,1);
  4527.  
  4528.     Sprite_Init(sprite_set,0,0,64,64,0,0,0,0,0,0);
  4529.  
  4530.     sprite_row = 0;
  4531.     sprite_column = 0;
  4532.  
  4533.     for (index = 0; index < num_cells; index++)
  4534.     {
  4535.         if ((index > 0) && ((index % 4) == 0))
  4536.         {
  4537.              sprite_row+=1;
  4538.              sprite_column=0;
  4539.         }
  4540.         PCX_Get_Sprite((pcx_picture_ptr)&image_pcx, sprite_set,
  4541.                             index,sprite_column,sprite_row);
  4542.  
  4543.         sprite_column++;
  4544.     }
  4545.  
  4546.     PCX_Delete((pcx_picture_ptr)&image_pcx);
  4547.  
  4548. } // end Load_64x64_Sprites
  4549.  
  4550. void Did_Player_Die(void)
  4551. {
  4552.     int index;
  4553.  
  4554.     if (Player_Strength <= 0)
  4555.     {
  4556.         for (index = 0; index <= 255; index++)
  4557.         {
  4558.             Read_Color_Reg(index, (RGB_color_ptr)&color_all);
  4559.  
  4560.             color_all.red += 48;
  4561.  
  4562.             if (color_all.red > 63)
  4563.                 color_all.red = 63;
  4564.  
  4565.             Write_Color_Reg(index, (RGB_color_ptr)&color_all);
  4566.  
  4567.         }
  4568.  
  4569.         for(index=0; index<20; index++)
  4570.         {
  4571.             // loop thru all palette registers
  4572.  
  4573.             for(pal_reg=0; pal_reg<=255; pal_reg++)
  4574.             {
  4575.                 // get the next color to fade
  4576.  
  4577.                 Read_Color_Reg(pal_reg,(RGB_color_ptr)&color_all);
  4578.  
  4579.                 // test if this color register is already black
  4580.                 if (color_all.red > 4) color_all.red-=3;
  4581.                 else
  4582.                     color_all.red = 0;
  4583.  
  4584.                 if (color_all.green > 4) color_all.green-=3;
  4585.                 else
  4586.                     color_all.green = 0;
  4587.  
  4588.                 if (color_all.blue > 4) color_all.blue-=3;
  4589.                 else
  4590.                     color_all.blue = 0;
  4591.  
  4592.                 // set the color to a diminshed intensity
  4593.  
  4594.                 Write_Color_Reg(pal_reg,(RGB_color_ptr)&color_all);
  4595.  
  4596.             } // end for pal reg
  4597.  
  4598.             // wait a bit
  4599.  
  4600.             Time_Delay(1);
  4601.  
  4602.         } // end for index
  4603.  
  4604.  
  4605.  
  4606.         if (digital_enabled)
  4607.         {
  4608.             Sound_Stop();
  4609.             Sound_Play((sound_ptr)&global_sounds[4]);
  4610.         }
  4611.  
  4612.         x=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  4613.         y=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  4614.         view_angle=ANGLE_60;
  4615.  
  4616.         Level_Select(which_map);
  4617.  
  4618.         New_Lease_On_Life = 1;
  4619.  
  4620.         Player_Strength = 63;
  4621.  
  4622.         Player_Ammo = 28;
  4623.  
  4624.         Got_Rapid_Fire = 0;
  4625.  
  4626.     }
  4627.  
  4628. } // end Did_Player_Die?
  4629.  
  4630. void Level_Select(int well)
  4631. {
  4632.     if (well == 4)
  4633.     {
  4634.         Load_World(4);
  4635.  
  4636.         at_end = 0;
  4637.     }
  4638.     else
  4639.     if (well == 3)
  4640.     {
  4641.         Load_World(3);
  4642.  
  4643.         at_end = 0;
  4644.     }
  4645.     else
  4646.     if (well == 2)
  4647.     {
  4648.         Load_World(2);
  4649.     }
  4650.     else
  4651.     if (well == 1)
  4652.     {
  4653.         Load_World(1);
  4654.     }
  4655.     else
  4656.     {
  4657.         Load_World(0);
  4658.     }
  4659. } // end Level_Select
  4660.  
  4661. void Process_Flashes(void)
  4662. {
  4663.     int index;
  4664.  
  4665.     if (New_Lease_On_Life)
  4666.     {
  4667.         for (index = 0; index <= 255; index++)
  4668.         {
  4669.             Write_Color_Reg(index, (RGB_color_ptr)&old_all[index]);
  4670.  
  4671.         }
  4672.  
  4673.         New_Lease_On_Life = 0;
  4674.     }
  4675.  
  4676.     if (just_grabbed_something)
  4677.     {
  4678.         for (index = 0; index <= 255; index++)
  4679.         {
  4680.             Write_Color_Reg(index, (RGB_color_ptr)&old_all[index]);
  4681.  
  4682.         }
  4683.  
  4684.         just_grabbed_something = 0;
  4685.  
  4686.     }
  4687.     if (Restore_Black)
  4688.     {
  4689.         color_all.red = 0;
  4690.         color_all.blue = 0;
  4691.         color_all.green = 0;
  4692.  
  4693.         Write_Color_Reg(0, (RGB_color_ptr)&color_all);
  4694.         Restore_Black = 0;
  4695.     }
  4696. } // end Process_Flashes
  4697.  
  4698. void Process_Enemy_Events(void)
  4699. {
  4700.     int index;
  4701.     int enemy_distance;
  4702.     int player_weapon_trajectory;
  4703.     int AIMED, aimed_sort_of;
  4704.     int hitable_arc;
  4705.  
  4706.     float enemy_dx, enemy_dy;
  4707.  
  4708.     long tempor;
  4709.  
  4710.     for (index = 0; index < (Number_Of_Enemies); index++)
  4711.     {
  4712.         if ((enemies[index].state != DYING) && (enemies[index].state != DEAD))
  4713.         {
  4714.             tempor = Angle_Between(x, y, enemies[index].vitals.x, enemies[index].vitals.y, index);
  4715.  
  4716.             if (tempor>=ANGLE_360)
  4717.                 tempor-=ANGLE_360;
  4718.  
  4719.             player_weapon_trajectory =
  4720.                 (tempor+ANGLE_360)-(view_angle+ANGLE_360);
  4721.  
  4722.             enemy_distance = Find_Object_Distance_Special(index);
  4723.  
  4724.             if (((int)enemy_distance) < 100)
  4725.                 hitable_arc = ANGLE_10;
  4726.             else
  4727.             if (((int)enemy_distance) < 200)
  4728.                 hitable_arc = ANGLE_8;
  4729.             else
  4730.             if (((int)enemy_distance) < 300)
  4731.                 hitable_arc = ANGLE_6;
  4732.             else
  4733.             if (((int)enemy_distance) < 400)
  4734.                 hitable_arc = ANGLE_4;
  4735.             else
  4736.             if (((int)enemy_distance) < 500)
  4737.                 hitable_arc = ANGLE_2;
  4738.  
  4739.             if((player_weapon_trajectory < hitable_arc) &&
  4740.                (player_weapon_trajectory > -hitable_arc) &&
  4741.                (enemy_distance<500L)                  &&
  4742.                (vz_buffer[ANGLE_45+player_weapon_trajectory] > enemy_distance))
  4743.             {
  4744.                 AIMED = 1;
  4745.                 aimed_sort_of = 1;
  4746.             }
  4747.             else
  4748.             {
  4749.                 AIMED = 0;
  4750.  
  4751.                 if((player_weapon_trajectory < (ANGLE_10)) &&
  4752.                    (player_weapon_trajectory > (-ANGLE_10)))
  4753.                 {
  4754.                     aimed_sort_of = 1;
  4755.                 }
  4756.                 else
  4757.                     aimed_sort_of = 0;
  4758.  
  4759.             }
  4760.  
  4761.             tempor += ANGLE_180;
  4762.  
  4763.             if (tempor > ANGLE_360)
  4764.                 tempor-=ANGLE_360;
  4765.  
  4766.             enemies[(index)].vitals.angle = tempor;
  4767.  
  4768.             if (enemies[(index)].state == EVADING)
  4769.             {
  4770.                 switch(duck_pattern[enemies[(index)].pat_num])
  4771.                 {
  4772.                     case 0: enemies[(index)].vitals.angle+=ANGLE_30; break;
  4773.                     case 1: enemies[(index)].vitals.angle; break;
  4774.                     case 2: enemies[(index)].vitals.angle-=ANGLE_30; break;
  4775.                 }
  4776.  
  4777.                 enemies[(index)].pat_num++;
  4778.  
  4779.                 if (enemies[(index)].pat_num > PAT_LIMIT)
  4780.                     enemies[(index)].pat_num = 0;
  4781.             }
  4782.  
  4783.             if (enemies[(index)].vitals.angle>ANGLE_360)
  4784.                 enemies[(index)].vitals.angle-=ANGLE_360;
  4785.  
  4786.             if (enemies[(index)].vitals.angle<0)
  4787.                 enemies[(index)].vitals.angle+=ANGLE_360;
  4788.  
  4789.             if ((player_state == PLAYER_FIRING) &&
  4790.                 (AIMED)                            &&
  4791.                 (the_gun.curr_frame == 4))
  4792.             {
  4793.                 if (Player_Ammo)
  4794.                 {
  4795.                     enemies[(index)].state = HIT;
  4796.                     --enemies[(index)].hit_points;
  4797.  
  4798.                     if (enemies[(index)].hit_points <= 0)
  4799.                     {
  4800.                         if (digital_enabled)
  4801.                         {
  4802.                             Sound_Stop();
  4803.                             Sound_Play((sound_ptr)&global_sounds[2]);
  4804.                         }
  4805.  
  4806.                         enemies[(index)].state = DYING;
  4807.                         enemies[(index)].threshold = 8;
  4808.                         enemies[(index)].hit_points = 5;
  4809.                     }
  4810.                 }
  4811.             }
  4812.             else
  4813.             if ((player_state == PLAYER_FIRING) &&
  4814.                 (aimed_sort_of)                    &&
  4815.                 (the_gun.curr_frame == 5)       &&
  4816.                 (!Player_Ammo))
  4817.             {
  4818.                 if (enemy_distance < 60)
  4819.                 {
  4820.                     enemies[(index)].state = HIT;
  4821.                     --enemies[(index)].hit_points;
  4822.  
  4823.                     if (enemies[(index)].hit_points <= 0)
  4824.                     {
  4825.                         if (digital_enabled)
  4826.                         {
  4827.                             Sound_Stop();
  4828.                             Sound_Play((sound_ptr)&global_sounds[2]);
  4829.                         }
  4830.  
  4831.                         enemies[(index)].state = DYING;
  4832.                         enemies[(index)].threshold = 8;
  4833.                         enemies[(index)].hit_points = 5;
  4834.  
  4835.                         Damage = 250/enemy_distance;
  4836.  
  4837.                         if (Damage > 5) Damage = 5;
  4838.                         Player_Strength -= Damage;
  4839.  
  4840.                         Red_Factor = 63-(Player_Strength>>1);
  4841.                         color_all.red = Red_Factor;
  4842.                         color_all.blue = 0;
  4843.                         color_all.green = 0;
  4844.  
  4845.                         Write_Color_Reg(0, (RGB_color_ptr)&color_all);
  4846. //                        Red_Factor++;
  4847.  
  4848. //                        if (Red_Factor == 64)
  4849. //                            Red_Factor = 16;
  4850.  
  4851.                         Restore_Black = 1;
  4852.  
  4853.                     }
  4854.                 }
  4855.                }
  4856.             else
  4857.             if (enemy_distance>500L)
  4858.             {
  4859.                 enemies[index].state = WAITING;
  4860.             }
  4861.             else
  4862.             if ((enemy_distance<50L) ||
  4863.                 (enemies[(index)].state == EVADING))
  4864.             {
  4865.                 if (enemies[(index)].state!=EVADING)
  4866.                     enemies[(index)].pat_num = (rand()%2)*2;
  4867.  
  4868.                 enemies[(index)].vitals.angle -= ANGLE_180;
  4869.  
  4870.                 if (enemies[(index)].vitals.angle < ANGLE_0)
  4871.                     enemies[(index)].vitals.angle += ANGLE_360;
  4872.  
  4873.                 tempor = enemies[(index)].vitals.angle;
  4874.  
  4875.                 enemy_dx=cos(6.28*tempor/ANGLE_360)*7;
  4876.                 enemy_dy=sin(6.28*tempor/ANGLE_360)*7;
  4877.  
  4878.                 enemies[(index)].vitals.x+=enemy_dx;
  4879.                 enemies[(index)].vitals.y+=enemy_dy;
  4880.  
  4881.                 enemies[(index)].state = EVADING;
  4882.  
  4883.                 Translate_Enemy((index), enemy_dx, enemy_dy);
  4884.             }
  4885.             else
  4886.             if ((enemy_distance<500L) ||
  4887.                 (enemies[(index)].state == PURSUING))
  4888.             {
  4889.                 enemies[(index)].state = PURSUING;
  4890.  
  4891.                 in_view = 0;
  4892.  
  4893. //                    if (enemies[(index)].pat_num == 1)
  4894. //                    {
  4895.                     // get enemy position to see if player is really
  4896.                     // in it's sights...
  4897.  
  4898.                     in_view=Enemy_Line_Of_Sight(enemies[(index)].vitals.x,
  4899.                                                 enemies[(index)].vitals.y,
  4900.                                                 enemies[(index)].vitals.angle,
  4901.                                                 enemy_distance);
  4902. //                    }
  4903.  
  4904.                 if (((rand()%15) < 3) && in_view)    //(in_view)
  4905.                 {
  4906.                     enemies[(index)].state = FIRING;
  4907.  
  4908.                     if (digital_enabled)
  4909.                     {
  4910.                         Sound_Stop();
  4911.                         Sound_Play((sound_ptr)&global_sounds[3]);
  4912.                     }
  4913.  
  4914.                     Damage = 250/enemy_distance;
  4915.  
  4916.                     if (Damage > 5) Damage = 5;
  4917.                     Player_Strength -= Damage;
  4918.  
  4919.                     Red_Factor = 63-(Player_Strength>>1);
  4920.                     color_all.red = Red_Factor;
  4921.                     color_all.blue = 0;
  4922.                     color_all.green = 0;
  4923.  
  4924.                     Write_Color_Reg(0, (RGB_color_ptr)&color_all);
  4925. //                        Red_Factor++;
  4926.  
  4927. //                        if (Red_Factor == 64)
  4928. //                            Red_Factor = 16;
  4929.  
  4930.                     Restore_Black = 1;
  4931.  
  4932.                 }
  4933.  
  4934.                 tempor = enemies[(index)].vitals.angle;
  4935.  
  4936.                 enemy_dx=cos(6.28*tempor/ANGLE_360)*7;
  4937.                 enemy_dy=sin(6.28*tempor/ANGLE_360)*7;
  4938.  
  4939.                 enemies[(index)].vitals.x+=enemy_dx;
  4940.                 enemies[(index)].vitals.y+=enemy_dy;
  4941.  
  4942.                 Translate_Enemy((index), enemy_dx, enemy_dy);
  4943.             }
  4944.         }
  4945.  
  4946.     }
  4947.  
  4948.     pat_start = Restore_Black;
  4949.  
  4950. } // end Process_Enemy_Events
  4951.  
  4952. /////////////////////////////////////////////////////////
  4953.  
  4954. void New_Game(void)
  4955. {
  4956.     int scale;
  4957.  
  4958.     Player_Strength = 63;
  4959.     Got_Rapid_Fire = 0;
  4960.  
  4961.     Player_Ammo = 28;
  4962.  
  4963.     which_map = 0;
  4964.  
  4965.     Level_Select(which_map);
  4966.  
  4967.     x=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  4968.     y=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  4969.     view_angle=ANGLE_60;
  4970.  
  4971.     Make_Gray_Palette();
  4972.  
  4973. // build the scaler table.  This table holds MAX_SCALE different arrays.  Each
  4974. // array consists of the pre-computed indices for an object to be scaled
  4975.  
  4976.     for (scale=1; scale<=WINDOW_HALF_HEIGHT; scale++)
  4977.     {
  4978.  
  4979.         // create the indices for this scale
  4980.  
  4981.         Create_Scale_Data(scale, (int *)scale_table[scale]);
  4982.  
  4983.     } // end for scale
  4984.  
  4985.     // THE SECOND Create_Scale_Data FUNCTION REFERED TO HERE IS USED
  4986.     // TO COMPUTE SCALES FOR CASES WHERE THE BOTTOM AND THE TOP OF A WALL
  4987.     // SLIVER ARE BEYOND THE VERTICAL EXTENTS OF THE VIEWPORT!
  4988.  
  4989.     for (scale=WINDOW_HALF_HEIGHT+1; scale<=MAX_SCALE; scale++)
  4990.     {
  4991.  
  4992.         // create the indices for this scale
  4993.  
  4994.         Create_Scale_Data2(scale, (int *)scale_table[scale]);
  4995.  
  4996.     } // end for scale
  4997.  
  4998.     beat_it = 0;
  4999. }
  5000.  
  5001. void Level_Just_Map(int lev_number)
  5002. {
  5003.     FILE  *fp, *fopen();
  5004.     int ob_num,gunner_num;
  5005.  
  5006.     int index,row,column;
  5007.     char buffer[WORLD_COLUMNS+2],ch;
  5008.     int door_num = 0;
  5009.     int result;
  5010.     long pos;
  5011.  
  5012.     // open the file
  5013.  
  5014.     if (!(fp = fopen("world.dat","r")))
  5015.            return(0);
  5016.  
  5017.     pos = (1088L*(long)(lev_number<<1));
  5018.     result = fseek( fp, pos, SEEK_SET);
  5019.     if( result )
  5020.          Print_String_Mode_Y(10,10,79,"Fseek failure",0);
  5021.  
  5022.     // load in the data
  5023.  
  5024.     for (row=0; row<WORLD_ROWS; row++)
  5025.     {
  5026.         // load in the next row
  5027.  
  5028.         for (column=0; column<WORLD_COLUMNS; column++)
  5029.         {
  5030.  
  5031.             while((ch = getc(fp))==10){} // filter out CR
  5032.  
  5033.             // translate character to integer
  5034.  
  5035.             if (ch == ' ')
  5036.                    ch=0;
  5037.             else
  5038.                    ch = ch - '0';
  5039.  
  5040.             // insert data into world
  5041.  
  5042.             if (ch==4)
  5043.                 world[(WORLD_ROWS-1) - row][column].block_type = 0;
  5044.             else
  5045.                 world[(WORLD_ROWS-1) - row][column].block_type = ch;
  5046.  
  5047.             Block_Map[(WORLD_ROWS-1) - row][column] = ch;
  5048.  
  5049.  
  5050.             if ((ch == 2) || (ch == 3)) // if it's a door
  5051.             {
  5052.                 world[(WORLD_ROWS-1) - row][column].door_id = door_num;
  5053.  
  5054.  
  5055.                 doors[door_num].door_y = (WORLD_ROWS-1) - row;
  5056.                 doors[door_num].door_x = column;
  5057.                 doors[door_num].door_state = CLOSED;
  5058.                 doors[door_num].door_block_type = ch;
  5059.                 doors[door_num].locked=0;
  5060.                 doors[door_num].door_speed=5;
  5061.                 doors[door_num].door_increment=0;
  5062.                 doors[door_num].door_wait_to_close=0;
  5063.  
  5064.                 door_num++;
  5065.             }
  5066.         } // end for column
  5067.  
  5068.         // process the row
  5069.  
  5070.     } // end for row
  5071.  
  5072.     total_world_doors = door_num;  // used by Process_Doors
  5073.  
  5074.     fclose(fp);
  5075.  
  5076.     if (which_map<4)
  5077.     {
  5078.         rotate_em = 1;
  5079.         Make_Gray_Palette();
  5080.     }
  5081.     else
  5082.     {
  5083.         rotate_em = 0;
  5084.         Make_Light_Metallic_Blue_Palette();
  5085.     }
  5086. }
  5087.  
  5088. int Load_Game(void)
  5089. {
  5090.     FILE  *fp, *fopen();
  5091.     int looper, Cur[10];
  5092.     int numb = 0, scale;
  5093.     char buff[14]="player_d.at";
  5094.  
  5095.  
  5096.     if (!(fp = fopen("plynames.dat","rb")))
  5097.     {
  5098.          Print_String_Mode_Y(20,150,170,"No saved games on record...",0);
  5099.          Print_String_Mode_Y(20,170,170,"...press space...",0);
  5100.          while(!keyboard_state[MAKE_SPACE]){};
  5101.          Print_String_Mode_Y(20,150,0,"No saved games on record...",0);
  5102.          Print_String_Mode_Y(20,170,0,"...press space...",0);
  5103.  
  5104.          return(1);
  5105.     }
  5106.     else
  5107.     {
  5108.         fread(names, sizeof(name_obj)*5, 1, fp);
  5109.  
  5110.         Refresh_Name_List(170);
  5111.         fclose(fp);
  5112.  
  5113.         while(keyboard_state[MAKE_2] || keyboard_state[MAKE_3]);
  5114.  
  5115.         numb = Slot_Selection();
  5116.         buff[11] = (char)(numb+49);
  5117.  
  5118.     }
  5119.  
  5120.     Refresh_Name_List(0);
  5121.  
  5122.  
  5123.     if ((fp = fopen(buff,"rb")))
  5124.     {
  5125.         fread(Cur, sizeof(Cur), 1, fp);
  5126.  
  5127.         Player_Strength=Cur[0];
  5128.         Player_Ammo=Cur[1];
  5129.         which_map=Cur[2];
  5130.         Got_Rapid_Fire=Cur[3];
  5131.         x=Cur[4];
  5132.         y=Cur[5];
  5133.         view_angle=Cur[6];
  5134.         Number_Of_Fixed_Objects=Cur[7];
  5135.         Number_Of_Enemies=Cur[8];
  5136.         total_world_doors=Cur[9];
  5137.  
  5138.         fread(initial_object_list, sizeof(objects)*Number_Of_Fixed_Objects, 1, fp);
  5139.         fread(enemies, sizeof(enemy_objects)*Number_Of_Enemies, 1, fp);
  5140.         Level_Just_Map(which_map);
  5141.  
  5142.         fread(doors, sizeof(doors)*total_world_doors, 1, fp);
  5143.  
  5144.         fclose(fp);
  5145.  
  5146.     }
  5147.  
  5148.     for (looper=0; looper < total_world_doors; looper++)
  5149.     {
  5150.         if (doors[looper].door_state == OPEN)
  5151.         {
  5152.               world[doors[looper].door_y][doors[looper].door_x].block_type = 0;
  5153.  
  5154.               // Allow the player to pass through the vacant doorway
  5155.  
  5156.             Block_Map[doors[looper].door_y][doors[looper].door_x] = 0;
  5157.         }
  5158.     }
  5159.  
  5160. // build the scaler table.  This table holds MAX_SCALE different arrays.  Each
  5161. // array consists of the pre-computed indices for an object to be scaled
  5162.  
  5163.     for (scale=1; scale<=WINDOW_HALF_HEIGHT; scale++)
  5164.     {
  5165.  
  5166.         // create the indices for this scale
  5167.  
  5168.         Create_Scale_Data(scale, (int *)scale_table[scale]);
  5169.  
  5170.     } // end for scale
  5171.  
  5172.     // THE SECOND Create_Scale_Data FUNCTION REFERED TO HERE IS USED
  5173.     // TO COMPUTE SCALES FOR CASES WHERE THE BOTTOM AND THE TOP OF A WALL
  5174.     // SLIVER ARE BEYOND THE VERTICAL EXTENTS OF THE VIEWPORT!
  5175.  
  5176.     for (scale=WINDOW_HALF_HEIGHT+1; scale<=MAX_SCALE; scale++)
  5177.     {
  5178.  
  5179.         // create the indices for this scale
  5180.  
  5181.         Create_Scale_Data2(scale, (int *)scale_table[scale]);
  5182.  
  5183.     } // end for scale
  5184.  
  5185.  
  5186.     Update_Weapon_Statis_Display(Player_Ammo/4);
  5187.  
  5188.     Update_Life_Statis_Display(Player_Strength/4);
  5189.  
  5190.     beat_it = 0;
  5191.  
  5192.     switch(which_map)
  5193.     {
  5194.          case 0:sprintf(where_am_i,"...somewhere in map 1");break;
  5195.          case 1:sprintf(where_am_i,"...somewhere in map 2");break;
  5196.          case 2:sprintf(where_am_i,"...somewhere in map 3");break;
  5197.          case 3:sprintf(where_am_i,"...somewhere in map 4");break;
  5198.          case 4:sprintf(where_am_i,"...somewhere in map 5");break;
  5199.        default:break;
  5200.     } //end switch
  5201. }
  5202.  
  5203. int Slot_Selection(void)
  5204. {
  5205.     int done = 0;
  5206.  
  5207.     while(!done)
  5208.     {
  5209.         if (keyboard_state[MAKE_1])
  5210.             return(0);
  5211.  
  5212.         if (keyboard_state[MAKE_2])
  5213.             return(1);
  5214.  
  5215.         if (keyboard_state[MAKE_3])
  5216.             return(2);
  5217.  
  5218.         if (keyboard_state[MAKE_4])
  5219.             return(3);
  5220.  
  5221.         if (keyboard_state[MAKE_5])
  5222.             return(4);
  5223.     }
  5224. } // end Slot_Selection
  5225.  
  5226. void Refresh_Name_List(int what_shade)
  5227. {
  5228.     Print_String_Mode_Y(10,30,what_shade,"1.",0);
  5229.     Print_String_Mode_Y(10,40,what_shade,"2.",0);
  5230.     Print_String_Mode_Y(10,50,what_shade,"3.",0);
  5231.     Print_String_Mode_Y(10,60,what_shade,"4.",0);
  5232.     Print_String_Mode_Y(10,70,what_shade,"5.",0);
  5233.     Print_String_Mode_Y(30,30,what_shade,names[0].name,0);
  5234.     Print_String_Mode_Y(30,40,what_shade,names[1].name,0);
  5235.     Print_String_Mode_Y(30,50,what_shade,names[2].name,0);
  5236.     Print_String_Mode_Y(30,60,what_shade,names[3].name,0);
  5237.     Print_String_Mode_Y(30,70,what_shade,names[4].name,0);
  5238. }
  5239.  
  5240. void Save_Game(void)
  5241. {
  5242.     FILE  *fp, *fopen();
  5243.     int looper, Cur[10];
  5244.     int numb = 0;
  5245.     char buff[14]="player_d.at", ch;
  5246.     int character;
  5247.     int done = 0;
  5248.     int sel_choice;
  5249.  
  5250.     if (!(fp = fopen("plynames.dat","rb")))
  5251.     {
  5252.          sprintf(names[0].name,"Unused Slot");
  5253.          sprintf(names[1].name,"Unused Slot");
  5254.          sprintf(names[2].name,"Unused Slot");
  5255.          sprintf(names[3].name,"Unused Slot");
  5256.          sprintf(names[4].name,"Unused Slot");
  5257.     }
  5258.     else
  5259.     {
  5260.         fread(names, sizeof(name_obj)*5, 1, fp);
  5261.     }
  5262.  
  5263.     Refresh_Name_List(170);
  5264.  
  5265.     Print_String_Mode_Y(10,10,170,"Select a slot #",0);
  5266.  
  5267.     while(keyboard_state[MAKE_2]);
  5268.  
  5269.     sel_choice = Slot_Selection();
  5270.     buff[11] = (char)(sel_choice+49);
  5271.  
  5272.  //   if (!strncmp( names[sel_choice].name, "Unused Slot", 11 ))
  5273.         sprintf(names[sel_choice].name,"           ");
  5274.  
  5275. //    while(keys_active);
  5276.  
  5277.     Refresh_Name_List(170);
  5278.  
  5279.     Keyboard_Remove_Driver();
  5280.  
  5281.     character = 0;
  5282.     done = 0;
  5283.  
  5284.     while(!done)
  5285.     {
  5286.  
  5287.         ch = getch();
  5288.  
  5289.         if (ch == 13)
  5290.             done = 1;
  5291.         else
  5292.         if (ch == 8)
  5293.         {
  5294.              --character;
  5295.              if (character < 0) character = 0;
  5296.              else names[sel_choice].name[character]=32;
  5297.  
  5298.             Refresh_Name_List(170);
  5299.  
  5300.  
  5301.         }
  5302.         else
  5303.         {
  5304.             keys_active = 0;
  5305.  
  5306.             if (character < 11)
  5307.             {
  5308.                 names[sel_choice].name[character] = ch;
  5309.  
  5310.  
  5311.                 ++character;
  5312.  
  5313.                 Refresh_Name_List(170);
  5314.             }
  5315.             if (character>11) character = 11;
  5316.            }
  5317.     }
  5318.  
  5319.     Keyboard_Install_Driver();
  5320.  
  5321.     Refresh_Name_List(0);
  5322.  
  5323.     fp = fopen("plynames.dat","wb");
  5324.     fwrite(names, sizeof(name_obj)*5, 1, fp);
  5325.     fclose(fp);
  5326.  
  5327.  
  5328.     Cur[0]=Player_Strength;
  5329.     Cur[1]=Player_Ammo;
  5330.     Cur[2]=which_map;
  5331.     Cur[3]=Got_Rapid_Fire;
  5332.     Cur[4]=x;
  5333.     Cur[5]=y;
  5334.     Cur[6]=view_angle;
  5335.     Cur[7]=Number_Of_Fixed_Objects;
  5336.     Cur[8]=Number_Of_Enemies;
  5337.     Cur[9]=total_world_doors;
  5338.  
  5339.     if ((fp = fopen(buff,"wb")))
  5340.     {
  5341.         fwrite(Cur, sizeof(Cur), 1, fp);
  5342.         fwrite(initial_object_list, sizeof(objects)*Number_Of_Fixed_Objects, 1, fp);
  5343.         fwrite(enemies, sizeof(enemy_objects)*Number_Of_Enemies, 1, fp);
  5344.         fwrite(doors, sizeof(doors)*total_world_doors, 1, fp);
  5345.         fclose(fp);
  5346.  
  5347.     }
  5348.  
  5349. } // end Save_Game
  5350.  
  5351. void Rotate_Em(int well)
  5352. {
  5353.     static int color_counter = -1;
  5354.  
  5355.     if (well==0) return;
  5356.  
  5357.     color_counter++;
  5358.  
  5359.     if (well == 1)
  5360.     {
  5361.         if ((color_counter >= 0) && (color_counter<40))
  5362.             Make_Gray_Palette_OAAT(color_counter-0,1);
  5363.         if ((color_counter >= 40) && (color_counter<80))
  5364.             Make_Blue_Palette_OAAT(color_counter-40,1);
  5365.         if ((color_counter >= 80) && (color_counter<120))
  5366.             Make_Gray_Palette_OAAT(color_counter-80,1);
  5367.         if ((color_counter >= 120) && (color_counter<160))
  5368.             Make_Cyan_Palette_OAAT(color_counter-120,1);
  5369.         if ((color_counter >= 160) && (color_counter<200))
  5370.             Make_Gray_Palette_OAAT(color_counter-160,1);
  5371.         if ((color_counter >= 200) && (color_counter<240))
  5372.             Make_Gold_Palette_OAAT(color_counter-200,1);
  5373.         if (color_counter >= 240)
  5374.             color_counter = -1;
  5375.     }
  5376.     else
  5377.     if (well == 2)
  5378.     {
  5379.         if ((color_counter >= 0) && (color_counter<40))
  5380.             Make_Gray_Palette_OAAT(color_counter-1,1);
  5381.         if ((color_counter >= 40) && (color_counter<80))
  5382.             Make_Blue_Palette_OAAT(color_counter-40,1);
  5383.         if ((color_counter >= 41) && (color_counter<81))
  5384.             Make_Blue_Palette_OAAT(color_counter-41,1);
  5385.         if ((color_counter >= 80) && (color_counter<120))
  5386.             Make_Cyan_Palette_OAAT(color_counter-80,1);
  5387.         if ((color_counter >= 81) && (color_counter<121))
  5388.             Make_Cyan_Palette_OAAT(color_counter-81,1);
  5389.         if ((color_counter >= 120) && (color_counter<160))
  5390.             Make_Gold_Palette_OAAT(color_counter-120,1);
  5391.         if ((color_counter >= 121) && (color_counter<161))
  5392.             Make_Gold_Palette_OAAT(color_counter-121,1);
  5393.         if (color_counter >= 161)
  5394.             color_counter = -1;
  5395.     }
  5396.     else
  5397.     if (well == 3)
  5398.     {
  5399.         if ((color_counter >= 0) && (color_counter<40))
  5400.             Make_Gray_Palette_OAAT(color_counter-0,0);
  5401.         if ((color_counter >= 40) && (color_counter<80))
  5402.             Make_Blue_Palette_OAAT(color_counter-40,1);
  5403.         if ((color_counter >= 41) && (color_counter<81))
  5404.             Make_Gold_Palette_OAAT(color_counter-41,0);
  5405.         if ((color_counter >= 51) && (color_counter<91))
  5406.             Make_Blue_Palette_OAAT(color_counter-51,1);
  5407.         if (color_counter >= 91)
  5408.             color_counter = -1;
  5409.     }
  5410.     else
  5411.     if (well == 4)
  5412.     {
  5413.         Make_Light_Metallic_Blue_Palette();
  5414.         rotate_em = 0;
  5415.     }
  5416. } // end Rotate_Em
  5417.  
  5418. // M A I N ///////////////////////////////////////////////////////////////////
  5419.  
  5420. int main(int argc, char **argv)
  5421. {
  5422.     char buffer[80];
  5423.  
  5424.     long player_weapon_trajectory, enemy_distance;
  5425.  
  5426.     int x_door,y_door,feel_x,feel_y;
  5427.     int done=0;
  5428.     int sequence;
  5429.     int scaler,Did_he=0;
  5430.  
  5431.     int show_help = 0;
  5432.  
  5433.     int choose, frames;
  5434.  
  5435.     long tempor;
  5436.  
  5437.     int index;
  5438.     int fat;
  5439.     long query;
  5440.  
  5441.     int sub_array[7];
  5442.     int how_long=0;
  5443.     int obj_id, obj_threshold;
  5444.  
  5445.     int just_print_mess;
  5446.  
  5447.     int sub_view_angle;
  5448.  
  5449.     int color_counter = 0;
  5450.  
  5451.     long dx,dy;
  5452.  
  5453.     FILE  *file_pointer, *fopen();
  5454.  
  5455.     int old_weapon_statis, new_weapon_statis;
  5456.  
  5457.     int old_life_statis, new_life_statis;
  5458.  
  5459.  
  5460. // beginning of code
  5461.  
  5462.     color_floor = 8;
  5463.     color_floor = color_floor | (color_floor << 8);
  5464.  
  5465.     color_ceil = 0;
  5466.     color_ceil = color_ceil | (color_ceil << 8);
  5467.  
  5468.     color_1 = 8;
  5469.     color_1 = color_1 | (color_1 << 8);
  5470.     color_1 = color_1 | (color_1 << 16);
  5471.  
  5472.     // seed random number generator
  5473.  
  5474.     srand(13);
  5475.  
  5476.     printf("\"\Slow Runnings\"\ version 1.5 is FREEWARE by James McCue.\n");
  5477.     printf("Slow Runnings - Copyright 1997!\n");
  5478.     printf("\nPress any key to continue...");
  5479.  
  5480.     getch();
  5481.  
  5482.     just_print_mess = Parse_Commands(argc,argv);
  5483.  
  5484.     if (music_enabled)
  5485.     {
  5486.         Music_Load("test.xmi",(music_ptr)&song);
  5487.  
  5488.         Music_Play((music_ptr)&song,0);
  5489.     }
  5490.  
  5491.     Keyboard_Install_Driver();
  5492.  
  5493.     Set_Mode_Y();
  5494.  
  5495.        _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
  5496.        _outp(CRT_CONTROLLER+1,0x00);
  5497.  
  5498.     Set_Visual_Page_Mode_Y_Half(mode_y_page);
  5499.  
  5500.     mode_y_page = !mode_y_page;
  5501.  
  5502.     Load_PCX_and_Page_Flip("opening.pcx",1);
  5503.  
  5504.     while (!keys_active);
  5505.  
  5506.     Fade_to_Black_and_Paint_Both(SCREEN_DARKNESS);
  5507.     Paint_All_Four_Black();
  5508.  
  5509.     Load_PCX_and_Page_Flip("story1.pcx",1);
  5510.  
  5511.     Make_Blue_Palette();
  5512.  
  5513.     while (!keys_active);
  5514.  
  5515.     Load_PCX_and_Page_Flip("story2.pcx",0);
  5516.  
  5517.     while (!keys_active);
  5518.  
  5519.     Load_PCX_and_Page_Flip("story3.pcx",0);
  5520.  
  5521.     while (!keys_active);
  5522.  
  5523.     Load_PCX_and_Page_Flip("story4.pcx",0);
  5524.  
  5525.     while (!keys_active);
  5526.  
  5527.     Load_PCX_and_Page_Flip("story5.pcx",0);
  5528.  
  5529.  
  5530.     while (!keys_active);
  5531.  
  5532.     Fade_to_Black_and_Paint_Both(SCREEN_DARKNESS);
  5533.     Paint_All_Four_Black();
  5534.  
  5535.  
  5536.     sprintf(buffer,"Beginning Initialization");
  5537.     Print_String_Mode_Y(10,10,170,buffer,0);
  5538.  
  5539.     Wait_Display_Mode();
  5540.  
  5541.     Set_Visual_Page_Mode_Y_Half(mode_y_page);
  5542.  
  5543.     mode_y_page = !mode_y_page;
  5544.  
  5545.     PCX_Init((pcx_picture_ptr)&image_pcx);
  5546.  
  5547.     PCX_Load("backw2.pcx", (pcx_picture_ptr)&image_pcx,1);
  5548.  
  5549.     PCX_Copy_To_Video_Mem((pcx_picture_ptr)&image_pcx, pagey_0_buffer);
  5550.  
  5551.     PCX_Delete((pcx_picture_ptr)&image_pcx);
  5552.  
  5553.  
  5554.     PCX_Init((pcx_picture_ptr)&image_pcx);
  5555.  
  5556.     PCX_Load("keyhelp.pcx", (pcx_picture_ptr)&image_pcx,0);
  5557.  
  5558.     PCX_Copy_To_Video_Mem((pcx_picture_ptr)&image_pcx, pagey_2_buffer);
  5559.  
  5560.     PCX_Delete((pcx_picture_ptr)&image_pcx);
  5561.  
  5562.     sprintf(buffer,"Background to Vid Mem - done!");
  5563.     Print_String_Mode_Y(10,20,170,buffer,0);
  5564.  
  5565.     // render initial view
  5566.  
  5567.     Load_64x64_Sprites((sprite_ptr)&wall_frames,"objectmp.pcx",12);
  5568.     Load_64x64_Sprites((sprite_ptr)&ob_frames,"objects.pcx",5);
  5569.     Load_64x64_Sprites((sprite_ptr)&duck_frames,"multi2.pcx",11);
  5570.     Load_64x64_Sprites((sprite_ptr)&duck_death,"multid.pcx",4);
  5571.     Load_64x64_Sprites((sprite_ptr)&the_gun,"thegun.pcx",8);
  5572.  
  5573.     the_gun.x = 128;
  5574.     the_gun.y = 88;
  5575.     the_gun.curr_frame = 0;
  5576.  
  5577.     // load in the textures
  5578.  
  5579.  
  5580.     sprintf(buffer,"Keyboard Driver Installed");
  5581.     Print_String_Mode_Y(10,50,170,buffer,0);
  5582.  
  5583.     // initialize sound system
  5584.  
  5585.     Allocate_World();
  5586.  
  5587.     sprintf(buffer,"Level Allocated");
  5588.     Print_String_Mode_Y(10,60,170,buffer,0);
  5589.  
  5590.     // build all the lookup tables
  5591.     if ((file_pointer = fopen("data.pov","rb")))
  5592.     {
  5593.         fread(sub_array, sizeof(sub_array), 1, file_pointer);
  5594.  
  5595.         my_size = sub_array[0];
  5596.         COLUMN_OFFSET = sub_array[1];
  5597.         my_height= sub_array[2];
  5598.         my_left = sub_array[3];
  5599.         my_right = sub_array[4];
  5600.         my_v_scale = sub_array[5];
  5601.         choose = sub_array[6];
  5602.  
  5603.         fclose(file_pointer);
  5604.  
  5605.     }
  5606.  
  5607.     Build_Tables();
  5608.  
  5609.     sprintf(buffer,"Trig/Scale tables made.");
  5610.     Print_String_Mode_Y(10,70,170,buffer,0);
  5611.  
  5612.     which_map = 0;
  5613.  
  5614.     Init_Objects();
  5615.  
  5616.     Level_Select(which_map);
  5617.  
  5618.     x=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  5619.     y=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  5620.     view_angle=ANGLE_60;
  5621.  
  5622.  
  5623.     sprintf(buffer,"Map Loaded...");
  5624.     Print_String_Mode_Y(10,80,170,buffer,0);
  5625.  
  5626.  
  5627. //    Number_Of_Movable_Objects = 0;
  5628.     sprintf(buffer,"Remember 'K' for keyboard help!");
  5629.     Print_String_Mode_Y(35,125,252,buffer,0);
  5630.  
  5631.     sprintf(buffer,"Press any key to Play.");
  5632.     Print_String_Mode_Y(70,185,253,buffer,0);
  5633.  
  5634.     while(!keys_active);
  5635.  
  5636.     Wait_Display_Mode();
  5637.  
  5638.     Set_Visual_Page_Mode_Y_Half(PAGE_3);
  5639.  
  5640.     Wait_Retrace_Mode();
  5641.  
  5642.     Set_Working_Page_Mode_Y(PAGE_3);
  5643.  
  5644.     Print_String_Mode_Y(40,80,170,"1. New Game",0);
  5645.     Print_String_Mode_Y(40,120,170,"2. Load Game",0);
  5646.  
  5647.     keys_active = 0;
  5648.  
  5649.     if (keys_active < 0) keys_active = 0;
  5650.  
  5651.     fat = 0;
  5652.  
  5653.     while(!fat)
  5654.     {
  5655.  
  5656.         if(keyboard_state[MAKE_1])
  5657.         {
  5658.             Print_String_Mode_Y(40,80,0,"1. New Game",0);
  5659.             Print_String_Mode_Y(40,120,0,"2. Load Game",0);
  5660.                New_Game();
  5661.                fat=1;
  5662.  
  5663.         }
  5664.         if(keyboard_state[MAKE_2])
  5665.         {
  5666.             Print_String_Mode_Y(40,80,0,"1. New Game",0);
  5667.             Print_String_Mode_Y(40,120,0,"2. Load Game",0);
  5668.                Load_Game();
  5669.                how_long=18;
  5670.                fat=1;
  5671.  
  5672.         }
  5673.     }
  5674.  
  5675.     Wait_Display_Mode();
  5676.  
  5677.     Set_Visual_Page_Mode_Y_Half(PAGE_3);
  5678.  
  5679.     mode_y_page = !mode_y_page;
  5680.  
  5681.     fat = 0;
  5682.  
  5683.     mode_y_page = PAGE_0;
  5684.  
  5685.     for (index = 0; index <=255; index++)
  5686.         Read_Color_Reg(index, (RGB_color_ptr)&old_all[index]);
  5687.  
  5688. // Start by copying bitmap to both pages
  5689.  
  5690.     Wait_Display_Mode();
  5691.  
  5692.     Set_Visual_Page_Mode_Y_Half(mode_y_page);
  5693.  
  5694.     mode_y_page = !mode_y_page;
  5695.  
  5696.     Setup_Initial_Display();
  5697.  
  5698.     Ray_Caster();
  5699.  
  5700. //    Weak_Attempt();
  5701.  
  5702.     Draw_Walls();
  5703.  
  5704.     Setup_Initial_Display();
  5705.  
  5706.     if (digital_enabled)
  5707.     {
  5708.         Sound_Load("pickup.voc",(sound_ptr)&global_sounds[0],1);
  5709.         Sound_Load("plyrshot.voc",(sound_ptr)&global_sounds[1],1);
  5710.         Sound_Load("boom.voc",(sound_ptr)&global_sounds[2],1);
  5711.         Sound_Load("enemshot.voc",(sound_ptr)&global_sounds[3],1);
  5712.         Sound_Load("nextmap.voc",(sound_ptr)&global_sounds[4],1);
  5713.         Sound_Load("dooropen.voc",(sound_ptr)&global_sounds[5],1);
  5714.         Sound_Load("click.voc",(sound_ptr)&global_sounds[6],1);
  5715.     }
  5716.  
  5717.     Ray_Caster();
  5718.  
  5719. //    Weak_Attempt();
  5720.  
  5721.     Draw_Walls();
  5722.  
  5723.     // wait for user to press ESC to quit
  5724.  
  5725.     if (music_enabled)
  5726.     {
  5727.         Music_Stop();
  5728.  
  5729.         if (which_map<4)
  5730.             Music_Play((music_ptr)&song,1);
  5731.         else
  5732.             Music_Play((music_ptr)&song,2);
  5733.     }
  5734.  
  5735.     Begin_Object_List();
  5736.  
  5737.     color_counter =-1;
  5738.  
  5739.     query = Timer_Query();
  5740.  
  5741.     while(!done)
  5742.     {
  5743.         Process_Doors();
  5744.  
  5745.         while ((Timer_Query() - query)<1);
  5746.  
  5747.         query = Timer_Query();
  5748.  
  5749.         Wait_Display_Mode();
  5750.  
  5751.         Set_Visual_Page_Mode_Y_Half(mode_y_page);
  5752.  
  5753.         if (pat_start)
  5754.         {
  5755.             if (pat_start<2)
  5756.             {
  5757.                 Process_Flashes();
  5758.                 ++pat_start;
  5759.             }
  5760.             else
  5761.                 pat_start = 0;
  5762.         }
  5763.  
  5764.         if (rotate_em)
  5765.         {
  5766.             Rotate_Em(which_map);
  5767.  
  5768.         } // end if rotate_em
  5769.  
  5770.         old_weapon_statis = Player_Ammo / 4;
  5771.  
  5772.         old_life_statis = Player_Strength /4;
  5773.  
  5774.         if (Did_he)
  5775.         {
  5776.             for (index = 0; index <= 255; index++)
  5777.             {
  5778.                 Write_Color_Reg(index, (RGB_color_ptr)&old_all[index]);
  5779.  
  5780.             }
  5781.  
  5782.             Did_he=0;
  5783.         }
  5784.  
  5785.         Did_he = Did_Player_Die();
  5786.  
  5787.         mode_y_page = !mode_y_page;
  5788.  
  5789.         dx=dy=0;
  5790.  
  5791.         if (keyboard_state[MAKE_SPACE])
  5792.         {
  5793.             // test if there is a door in front of player
  5794.  
  5795.             // project a "feeler" 3 steps in front of player and test for a door
  5796.  
  5797.             x_door = (int)(x + cos(6.28*view_angle/ANGLE_360)*3*15);
  5798.             y_door = (int)(y + sin(6.28*view_angle/ANGLE_360)*3*15);
  5799.  
  5800.             // compute cell position
  5801.  
  5802.             feel_x = x_door/CELL_X_SIZE;
  5803.             feel_y = y_door/CELL_Y_SIZE;
  5804.  
  5805.             // test for door
  5806.  
  5807.             if ((world[feel_y][feel_x].block_type == 2) || (world[feel_y][feel_x].block_type == 3))
  5808.             {
  5809.                 id_number = world[feel_y][feel_x].door_id;
  5810.  
  5811.                 if ((doors[id_number].door_state == CLOSED) ||
  5812.                     (doors[id_number].door_state == CLOSING))
  5813.                 {
  5814.  
  5815.                     if (doors[id_number].door_state == CLOSED)
  5816.                     {
  5817.                         if (digital_enabled)
  5818.                         {
  5819.                             Sound_Stop();
  5820.                             Sound_Play((sound_ptr)&global_sounds[0]);
  5821.                         }
  5822.  
  5823.                     }
  5824.                     // make door disappear by starting process
  5825.  
  5826.                     doors[id_number].door_y = feel_y;
  5827.                     doors[id_number].door_x = feel_x;
  5828.                     doors[id_number].door_state = OPENING;
  5829.                     doors[id_number].door_increment += 6;
  5830.  
  5831.                 }
  5832.             } // end if a door was found
  5833.             else
  5834.             if (world[feel_y][feel_x].block_type==7)
  5835.             {
  5836.                 if (digital_enabled)
  5837.                 {
  5838.                     Sound_Stop();
  5839.                     Sound_Play((sound_ptr)&global_sounds[4]);
  5840.                 }
  5841.  
  5842.                 x=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  5843.                 y=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  5844.                 view_angle=ANGLE_60;
  5845.  
  5846.                 ++which_map;
  5847.  
  5848.                 if (which_map == 5)
  5849.                 {
  5850.                     at_end = 1;
  5851.                     really_at_end = 1;
  5852.                     done = 1;
  5853.                     while(keyboard_state[MAKE_SPACE]){};
  5854.                 }
  5855.                 else
  5856.                 {
  5857.                     if(which_map<4)
  5858.                     {
  5859.                         Level_Select(which_map);
  5860.                     }
  5861.                     else
  5862.                     {
  5863.                         Level_Select(which_map);
  5864.                         if (music_enabled)
  5865.                         {
  5866.                             Music_Stop();
  5867.  
  5868.                             Music_Play((music_ptr)&song,2);
  5869.                         }
  5870.                     }
  5871.                 }
  5872.  
  5873.             }
  5874.             else
  5875.             if (world[feel_y][feel_x].block_type==9)
  5876.             {
  5877.                 if (digital_enabled)
  5878.                 {
  5879.                     Sound_Stop();
  5880.                     Sound_Play((sound_ptr)&global_sounds[4]);
  5881.                 }
  5882.  
  5883.                 x=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  5884.                 y=(8<<CELL_X_SIZE_FP)+(CELL_X_SIZE>>1);
  5885.                 view_angle=ANGLE_60;
  5886.  
  5887.                 if (which_map == 4)
  5888.                 {
  5889.                     at_end = 1;
  5890.                     really_at_end = 1;
  5891.                     done = 1;
  5892.                     while(keyboard_state[MAKE_SPACE]){};
  5893.                 }
  5894.  
  5895.             }
  5896.         }
  5897.  
  5898.         if (keyboard_state[MAKE_F])
  5899.         {
  5900.             if (player_state==PLAYER_NOT_FIRING)
  5901.             {
  5902.                 if (digital_enabled)
  5903.                 {
  5904.                     Sound_Stop();
  5905.  
  5906.                     if (Player_Ammo)
  5907.                         Sound_Play((sound_ptr)&global_sounds[1]);
  5908.                     else
  5909.                         Sound_Play((sound_ptr)&global_sounds[6]);
  5910.                 }
  5911.  
  5912.                 player_state = PLAYER_FIRING;
  5913.             }
  5914.  
  5915.             if ((player_state==PLAYER_FIRING) && (the_gun.curr_frame > 5) && (Got_Rapid_Fire))
  5916.             {
  5917.                 if (digital_enabled)
  5918.                 {
  5919.                     Sound_Stop();
  5920.                     if (Player_Ammo)
  5921.                         Sound_Play((sound_ptr)&global_sounds[1]);
  5922.                     else
  5923.                         Sound_Play((sound_ptr)&global_sounds[6]);
  5924.                 }
  5925.  
  5926.                 the_gun.curr_frame = 2;
  5927.             }
  5928.         }
  5929.  
  5930.         if (keyboard_state[MAKE_P])
  5931.         {
  5932.             Print_String_Mode_Y(20,70,255,"Paused - press SPACE to continue...",1);
  5933.  
  5934.             while (!keyboard_state[MAKE_SPACE]);
  5935.         }
  5936.  
  5937.         if (keyboard_state[MAKE_K])
  5938.         {
  5939.             Wait_Display_Mode();
  5940.  
  5941.             Set_Visual_Page_Mode_Y_Half(PAGE_2);
  5942.  
  5943.             while (!keyboard_state[MAKE_G]) {};
  5944.  
  5945.             Wait_Display_Mode();
  5946.  
  5947.             Set_Visual_Page_Mode_Y_Half(!mode_y_page);
  5948.  
  5949.         }
  5950.  
  5951.         if (keyboard_state[MAKE_F5])
  5952.         {
  5953.             Wait_Display_Mode();
  5954.  
  5955.             Set_Visual_Page_Mode_Y_Half(PAGE_3);
  5956.  
  5957.             Wait_Retrace_Mode();
  5958.  
  5959.             Set_Working_Page_Mode_Y(PAGE_3);
  5960.  
  5961.             Print_String_Mode_Y(40,80,170,"1. New Game",0);
  5962.             Print_String_Mode_Y(40,100,170,"2. Save Game",0);
  5963.             Print_String_Mode_Y(40,120,170,"3. Load Game",0);
  5964.  
  5965.             while(!fat)
  5966.             {
  5967.                 if(keyboard_state[MAKE_1])
  5968.                 {
  5969.                     Print_String_Mode_Y(40,80,0,"1. New Game",0);
  5970.                     Print_String_Mode_Y(40,100,0,"2. Save Game",0);
  5971.                     Print_String_Mode_Y(40,120,0,"3. Load Game",0);
  5972.                        New_Game();
  5973.                        fat=1;
  5974.                 }
  5975.                 if(keyboard_state[MAKE_2])
  5976.                 {
  5977.                     Print_String_Mode_Y(40,80,0,"1. New Game",0);
  5978.                     Print_String_Mode_Y(40,100,0,"2. Save Game",0);
  5979.                     Print_String_Mode_Y(40,120,0,"3. Load Game",0);
  5980.                        Save_Game();
  5981.                        fat=1;
  5982.                 }
  5983.                 if(keyboard_state[MAKE_3])
  5984.                 {
  5985.                     Print_String_Mode_Y(40,80,0,"1. New Game",0);
  5986.                     Print_String_Mode_Y(40,100,0,"2. Save Game",0);
  5987.                     Print_String_Mode_Y(40,120,0,"3. Load Game",0);
  5988.                        Load_Game();
  5989.  
  5990.                     if (music_enabled)
  5991.                     {
  5992.                         Music_Stop();
  5993.  
  5994.                         if (which_map<4)
  5995.                             Music_Play((music_ptr)&song,1);
  5996.                         else
  5997.                             Music_Play((music_ptr)&song,2);
  5998.                     }
  5999.  
  6000.                        how_long=18;
  6001.                        fat=1;
  6002.                 }
  6003.  
  6004.             }
  6005.  
  6006.             mode_y_page = !mode_y_page;
  6007.  
  6008.             Wait_Display_Mode();
  6009.  
  6010.             Set_Visual_Page_Mode_Y_Half(mode_y_page);
  6011.  
  6012.             mode_y_page = !mode_y_page;
  6013.  
  6014.             fat = 0;
  6015.         }
  6016.         if (keyboard_state[MAKE_RIGHT])
  6017.         {
  6018.             if ((view_angle-=ANGLE_7)<ANGLE_0)
  6019.                 view_angle+=ANGLE_360;
  6020.  
  6021.             sub_view_angle = view_angle + ANGLE_90;
  6022.             if (sub_view_angle>=ANGLE_360)
  6023.                 sub_view_angle-=ANGLE_360;
  6024.  
  6025.             // move player along view vector foward
  6026.  
  6027.             dx=cos(6.28*sub_view_angle/ANGLE_360)*3;
  6028.             dy=sin(6.28*sub_view_angle/ANGLE_360)*3;
  6029.  
  6030.             x+=dx;
  6031.             y+=dy;
  6032.  
  6033.             Translate_Player(dx, dy);
  6034.         }
  6035.  
  6036.         if (keyboard_state[MAKE_LEFT])
  6037.         {
  6038.             if ((view_angle+=ANGLE_7)>=ANGLE_360)
  6039.                 view_angle-=ANGLE_360;
  6040.  
  6041.             sub_view_angle = view_angle - ANGLE_90;
  6042.             if (sub_view_angle<0)
  6043.                 sub_view_angle+=ANGLE_360;
  6044.  
  6045.             // move player along view vector foward
  6046.  
  6047.             dx=cos(6.28*sub_view_angle/ANGLE_360)*3;
  6048.             dy=sin(6.28*sub_view_angle/ANGLE_360)*3;
  6049.  
  6050.             x+=dx;
  6051.             y+=dy;
  6052.  
  6053.             Translate_Player(dx, dy);
  6054.         }
  6055.  
  6056.  
  6057.         if (keyboard_state[MAKE_UP] || keyboard_state[MAKE_DOWN])
  6058.         {
  6059.             if (keyboard_state[MAKE_UP])
  6060.             {
  6061.  
  6062.                 // move player along view vector foward
  6063.  
  6064.                 dx=cos(6.28*view_angle/ANGLE_360)*15;
  6065.                 dy=sin(6.28*view_angle/ANGLE_360)*15;
  6066.  
  6067.                 x+=dx;
  6068.                 y+=dy;
  6069.  
  6070.             }
  6071.  
  6072.             if (keyboard_state[MAKE_DOWN])
  6073.             {
  6074.                 // move player along view vector backward
  6075.  
  6076.                 dx=-cos(6.28*view_angle/ANGLE_360)*15;
  6077.                 dy=-sin(6.28*view_angle/ANGLE_360)*15;
  6078.  
  6079.                 x+=dx;
  6080.                 y+=dy;
  6081.  
  6082.             }
  6083.  
  6084.             Translate_Player(dx, dy);
  6085.         }  // end if player in motion
  6086.  
  6087.         if (keyboard_state[MAKE_C]  || keyboard_state[MAKE_V])
  6088.         {
  6089.             if (keyboard_state[MAKE_C])
  6090.             {
  6091.                 sub_view_angle = view_angle + ANGLE_90;
  6092.                 if (sub_view_angle>ANGLE_360)
  6093.                     sub_view_angle-=ANGLE_360;
  6094.  
  6095.                 // move player along view vector foward
  6096.  
  6097.                 dx=cos(6.28*sub_view_angle/ANGLE_360)*10;
  6098.                 dy=sin(6.28*sub_view_angle/ANGLE_360)*10;
  6099.  
  6100.                 x+=dx;
  6101.                 y+=dy;
  6102.  
  6103.             }
  6104.  
  6105.             if (keyboard_state[MAKE_V])
  6106.             {
  6107.                 sub_view_angle = view_angle - ANGLE_90;
  6108.                 if (sub_view_angle<0)
  6109.                     sub_view_angle+=ANGLE_360;
  6110.  
  6111.                 // move player along view vector backward
  6112.  
  6113.                 dx=cos(6.28*sub_view_angle/ANGLE_360)*10;
  6114.                 dy=sin(6.28*sub_view_angle/ANGLE_360)*10;
  6115.  
  6116.                 x+=dx;
  6117.                 y+=dy;
  6118.  
  6119.             }
  6120.  
  6121.             Translate_Player(dx, dy);
  6122.  
  6123.         }  // end if player in motion
  6124.  
  6125.  
  6126.         if (keyboard_state[MAKE_ESC])
  6127.         {
  6128.              done=1;
  6129.         }
  6130.  
  6131.         // render the view
  6132.  
  6133. // THE FOLLOWING FUNCTION: Ray_Caster();    -has been modified so that
  6134. //        the actual drawing is done elsewhere, in order to interleave the
  6135. //         ray casting with the time spent waiting for VGA page flipping to
  6136. //        take hold!!! Gad Zooks! - IT WORKS!
  6137.  
  6138.         Ray_Caster();
  6139.  
  6140. //        Weak_Attempt();
  6141.  
  6142.  
  6143. ///  CODE THAT NEEDS A BATH!
  6144. /////////////////////////////////////////////////////////
  6145.         Process_Enemy_Events();
  6146.  
  6147.         if (just_grabbed_something)
  6148.         {
  6149.             if (digital_enabled)
  6150.             {
  6151.                 Sound_Stop();
  6152.                 Sound_Play((sound_ptr)&global_sounds[5]);
  6153.             }
  6154.  
  6155.             pat_start = 1;
  6156.  
  6157.             for (index = 0; index <= 15; index++)
  6158.             {
  6159.                 Read_Color_Reg(index, (RGB_color_ptr)&color_all);
  6160.  
  6161.                 switch (what_obj)
  6162.                 {
  6163.                     case 4:
  6164.                     {
  6165.                         color_all.green += 32;
  6166.  
  6167.                         if (color_all.green > 63)
  6168.                             color_all.green = 63;
  6169.                     } break;
  6170.  
  6171.                     case 5:
  6172.                     {
  6173.                         color_all.green += 32;
  6174.  
  6175.                         if (color_all.green > 63)
  6176.                             color_all.green = 63;
  6177.                     } break;
  6178.  
  6179.                     case 6:
  6180.                     {
  6181.                         color_all.blue  += 32;
  6182.  
  6183.                         if (color_all.blue > 63)
  6184.                             color_all.blue = 63;
  6185.                     } break;
  6186.                 }
  6187.  
  6188.                 Write_Color_Reg(index, (RGB_color_ptr)&color_all);
  6189.  
  6190.             }
  6191.  
  6192.  
  6193.             for (index = 16; index <= 80; index++)
  6194.             {
  6195.                 Read_Color_Reg(index, (RGB_color_ptr)&old_all[index]);
  6196.  
  6197.                 switch (what_obj)
  6198.                 {
  6199.                     case 4:
  6200.                     {
  6201.                         color_all.green = old_all[index].green + 32;
  6202.  
  6203.                         if (color_all.green > 63)
  6204.                             color_all.green = 63;
  6205.                     } break;
  6206.  
  6207.                     case 5:
  6208.                     {
  6209.                         color_all.green = old_all[index].green + 32;
  6210.  
  6211.                         if (color_all.green > 63)
  6212.                             color_all.green = 63;
  6213.                     } break;
  6214.  
  6215.                     case 6:
  6216.                     {
  6217.                         color_all.blue = old_all[index].blue + 32;
  6218.  
  6219.                         if (color_all.blue > 63)
  6220.                             color_all.blue = 63;
  6221.                     } break;
  6222.                 }
  6223.  
  6224.                 Write_Color_Reg(index, (RGB_color_ptr)&color_all);
  6225.  
  6226.             }
  6227.  
  6228.             for (index = 81; index <= 255; index++)
  6229.             {
  6230.                 Read_Color_Reg(index, (RGB_color_ptr)&color_all);
  6231.  
  6232.                 switch (what_obj)
  6233.                 {
  6234.                     case 4:
  6235.                     {
  6236.                         color_all.green += 32;
  6237.  
  6238.                         if (color_all.green > 63)
  6239.                             color_all.green = 63;
  6240.                     } break;
  6241.  
  6242.                     case 5:
  6243.                     {
  6244.                         color_all.green += 32;
  6245.  
  6246.                         if (color_all.green > 63)
  6247.                             color_all.green = 63;
  6248.                     } break;
  6249.  
  6250.                     case 6:
  6251.                     {
  6252.                         color_all.blue  += 32;
  6253.  
  6254.                         if (color_all.blue > 63)
  6255.                             color_all.blue = 63;
  6256.                     } break;
  6257.                 }
  6258.  
  6259.                 Write_Color_Reg(index, (RGB_color_ptr)&color_all);
  6260.  
  6261.             }
  6262.  
  6263.  
  6264.         }
  6265.  
  6266.         Begin_Object_List();
  6267.  
  6268.         Find_Object_Distance();
  6269.  
  6270.         Sort_Object_List();
  6271.  
  6272.         Wait_Retrace_Mode();
  6273.  
  6274.         Set_Working_Page_Mode_Y(mode_y_page);
  6275.  
  6276.         Erase_Scene();
  6277.  
  6278.         Draw_Walls();
  6279.  
  6280.         for (index = (Number_Of_Fixed_Objects+Number_Of_Enemies); index >= 0; index--)
  6281.         {
  6282.             if (object_list[index].dist < 1000)
  6283.             {
  6284.                 if ((object_list[index].kind_of_object == 2) ||
  6285.                     (object_list[index].kind_of_object == 3))
  6286.                 {
  6287.                     obj_id = object_list[index].id_number;
  6288.  
  6289.                     if (enemies[object_list[index].id_number].state == DYING)
  6290.                     {
  6291.                         --enemies[object_list[index].id_number].threshold;
  6292.  
  6293.                         if (enemies[object_list[index].id_number].threshold == 0)
  6294.                             enemies[object_list[index].id_number].state = DEAD;
  6295.                     }
  6296.  
  6297.                     obj_threshold = enemies[object_list[index].id_number].threshold;
  6298.  
  6299.                 }
  6300.  
  6301.                 Find_and_Maybe_Plot_Objects(object_list[index],obj_id,obj_threshold);
  6302.             }
  6303.         }
  6304.         if (player_state == PLAYER_FIRING)
  6305.         {
  6306.             ++the_gun.curr_frame;
  6307.  
  6308.             if ((the_gun.curr_frame == 4) && (Player_Ammo))
  6309.                 --Player_Ammo;
  6310.             else
  6311.             if (the_gun.curr_frame == 4)
  6312.                 ++the_gun.curr_frame;
  6313.  
  6314.             if (the_gun.curr_frame > 7)
  6315.             {
  6316.                 the_gun.curr_frame = 0;
  6317.  
  6318.                 player_state = PLAYER_NOT_FIRING;
  6319.             }
  6320.         }
  6321.  
  6322.         Sprite_Draw_Clip_Special((sprite_ptr)&the_gun, video_buffer);
  6323.  
  6324.         new_weapon_statis = Player_Ammo / 4;
  6325.  
  6326.         if (new_weapon_statis!=old_weapon_statis)
  6327.             Update_Weapon_Statis_Display(new_weapon_statis);
  6328.  
  6329.         new_life_statis = Player_Strength / 4;
  6330.  
  6331.         if (new_life_statis!=old_life_statis)
  6332.             Update_Life_Statis_Display(new_life_statis);
  6333.  
  6334.         if (doors[0].door_state != CLOSED && which_map==4 && !beat_it)
  6335.         {
  6336.             Make_Gold_Palette();
  6337.             beat_it = 1;
  6338.         }
  6339.  
  6340.         if (doors[0].door_state != CLOSED && which_map==4)
  6341.         {
  6342.             sprintf(buffer,"You have not seen the last of me!");
  6343.             Print_String_Mode_Y(15,15,170,buffer,1);
  6344.             sprintf(buffer,"hmmm... actually - you haven't");
  6345.             Print_String_Mode_Y(15,25,170,buffer,1);
  6346.             sprintf(buffer,"even seen me YET!...oh well...");
  6347.             Print_String_Mode_Y(15,35,170,buffer,1);
  6348.         }
  6349.  
  6350.         if(how_long)
  6351.         {
  6352.             Print_String_Mode_Y(15,20,255,where_am_i,1);
  6353.             --how_long;
  6354.         }
  6355.     } //end while
  6356.  
  6357.     // De-allocate Memory
  6358.  
  6359.     Sprite_Delete((sprite_ptr)&wall_frames);
  6360.  
  6361.     Sprite_Delete((sprite_ptr)&duck_frames);
  6362.  
  6363.     Sprite_Delete((sprite_ptr)&duck_death);
  6364.  
  6365.     Sprite_Delete((sprite_ptr)&ob_frames);
  6366.  
  6367.     Sprite_Delete((sprite_ptr)&the_gun);
  6368.  
  6369.     // free memory associated with lookup tables...
  6370.  
  6371.     for (index = 0; index < WORLD_ROWS; index++)
  6372.     {
  6373.         _ffree(Block_Map[index]);
  6374.     }
  6375.  
  6376.     _ffree(tan_table);
  6377.     _ffree(inv_tan_table);
  6378.     _ffree(x_step);
  6379.     _ffree(y_step);
  6380.     _ffree(cos_table);
  6381.     _ffree(inv_cos_table);
  6382.     _ffree(inv_sin_table);
  6383.  
  6384.     for (scaler=0; scaler<=MAX_SCALE; scaler++)
  6385.     {
  6386.  
  6387.         free(scale_table[scaler]);
  6388.  
  6389.     } // end for scaler
  6390.  
  6391.     // pot up the lights...
  6392.  
  6393.     if (at_end)
  6394.     {
  6395.         for(index=0; index<20; index++)
  6396.         {
  6397.             for(pal_reg=0; pal_reg<=255; pal_reg++)
  6398.             {
  6399.                 // get the next color to fade
  6400.  
  6401.                 Read_Color_Reg(pal_reg,(RGB_color_ptr)&color_all);
  6402.  
  6403.                 // test if this color register is already at peak intensity
  6404.  
  6405.                 color_all.red += 4;
  6406.  
  6407.                 // test if this color register is already white
  6408.                 if (color_all.red > 63)
  6409.                     color_all.red=63;
  6410.  
  6411.                 color_all.green += 4;
  6412.  
  6413.                 if (color_all.green > 63)
  6414.                     color_all.green=63;
  6415.  
  6416.                 // set the color to a diminshed intensity
  6417.  
  6418.                 Write_Color_Reg(pal_reg,(RGB_color_ptr)&color_all);
  6419.  
  6420.             } // end for pal reg
  6421.  
  6422.             // wait a bit
  6423.  
  6424.             Time_Delay(1);
  6425.  
  6426.         } // end for index
  6427.     }
  6428.     else
  6429.     {
  6430.         Screen_Transition(SCREEN_WHITENESS);
  6431.     }
  6432.  
  6433.     if (really_at_end)
  6434.     {
  6435.         if (music_enabled)
  6436.         {
  6437.             Music_Stop();
  6438.  
  6439.             Music_Play((music_ptr)&song,3);
  6440.         }
  6441.  
  6442.         mode_y_page = !mode_y_page;
  6443.  
  6444.         Wait_Retrace_Mode();
  6445.  
  6446.         Set_Working_Page_Mode_Y(mode_y_page);
  6447.  
  6448.         // erase the screen
  6449.  
  6450.         outp(SEQUENCER,SEQ_PLANE_ENABLE);
  6451.         outp(SEQUENCER+1,0x0f);
  6452.  
  6453.         _asm
  6454.         {
  6455.  
  6456.             les di,video_buffer   // point es:di to video buffer, same addre for mode Z
  6457.             xor ax,ax             // zero out AH and AL
  6458.             mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  6459.             rep stosw             // move the color into the video buffer really fast!
  6460.  
  6461.         } // end inline asm
  6462.  
  6463.         Load_PCX_and_Page_Flip("winning.pcx",0);
  6464.  
  6465.         for (index = 0; index <=15; index++)
  6466.             Write_Color_Reg(index, (RGB_color_ptr)&old_all[index]);
  6467.  
  6468.         for (index = 16; index <= 60; index++)
  6469.         {
  6470.             color_all.red = 0;
  6471.             color_all.green = 0;
  6472.             color_all.blue = (index-16);
  6473.  
  6474.             Write_Color_Reg(index, (RGB_color_ptr)&color_all);
  6475.  
  6476.         }
  6477.  
  6478.         for (index = 61; index <=255; index++)
  6479.             Write_Color_Reg(index, (RGB_color_ptr)&old_all[index]);
  6480.  
  6481.         keys_active=0;
  6482.  
  6483.         while(!keys_active){};
  6484.  
  6485.  
  6486.         Fade_to_Black_and_Paint_Both(FULL_SCREEN_DARKNESS);
  6487.  
  6488.     }
  6489.  
  6490.     free(object_list);
  6491.     free(initial_object_list);
  6492.  
  6493.     if (digital_enabled)
  6494.     {
  6495.         Sound_Stop();
  6496.  
  6497.         Sound_Unload((sound_ptr)&global_sounds[0]);
  6498.         Sound_Unload((sound_ptr)&global_sounds[1]);
  6499.         Sound_Unload((sound_ptr)&global_sounds[2]);
  6500.         Sound_Unload((sound_ptr)&global_sounds[3]);
  6501.         Sound_Unload((sound_ptr)&global_sounds[4]);
  6502.         Sound_Unload((sound_ptr)&global_sounds[5]);
  6503.         Sound_Unload((sound_ptr)&global_sounds[6]);
  6504.  
  6505.     }
  6506.  
  6507.     if (music_enabled)
  6508.     {
  6509.         Music_Stop();
  6510.  
  6511.         Music_Unload((music_ptr)&song);
  6512.     }
  6513.  
  6514.     Set_Graphics_Mode(TEXT_MODE);
  6515.  
  6516.  
  6517.     printf("\nProgramming: James McCue!\n");
  6518.     printf("   -with the help of the great Andre' Lamothe's BLACK ART OF 3D\n");
  6519.     printf("GAME PROGRAMMING (Waite Group Press) graphics library - and his WRITINGS!!!\n\n");
  6520.  
  6521.     printf("Concept: Not much of one - is there? - by James McCue\n");
  6522.     printf("'Art?': Walls, Enemies and most stuff - James McCue\n");
  6523.  
  6524.     printf("ART: Doors, and that face, That face, THAT COVER GIRL FACE\n");
  6525.     printf("    - BY MY BROTHER ROBERT MCCUE\n\n");
  6526.  
  6527.     printf("If you wish, contact me via e-mail at QBALL1723@AOL.COM\n\n");
  6528.  
  6529.     printf("This program is completely free, but if you'd wish to contribute to my\n");
  6530.     printf("game programming cause... please send $5.00 to:\n\n");
  6531.     printf("James McCue, P.O. Box 151, Bethpage, NY 11714-4831\n\n");
  6532.  
  6533.     printf("Thank you for playing Slow Runnings!\n\n");
  6534.     printf("Visit my website: http://members.aol.com/qball1723/index.htm\n\n");
  6535.  
  6536.     Keyboard_Remove_Driver();
  6537.  
  6538.     getch();
  6539.     return(0);
  6540. } // end main
  6541.  
  6542.  
  6543.