home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / automap.c < prev    next >
Text File  |  1998-06-08  |  34KB  |  1,196 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/main/rcs/automap.c $
  15.  * $Revision: 2.2 $
  16.  * $Author: john $
  17.  * $Date: 1995/03/21 14:41:26 $
  18.  * 
  19.  * Routines for displaying the auto-map.
  20.  * 
  21.  * $Log: automap.c $
  22.  * Revision 2.2  1995/03/21  14:41:26  john
  23.  * Ifdef'd out the NETWORK code.
  24.  * 
  25.  * Revision 2.1  1995/03/20  18:16:06  john
  26.  * Added code to not store the normals in the segment structure.
  27.  * 
  28.  * Revision 2.0  1995/02/27  11:32:55  john
  29.  * New version 2.0, which has no anonymous unions, builds with
  30.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  31.  * 
  32.  * Revision 1.117  1995/02/22  14:11:31  allender
  33.  * remove anonymous unions from object structure
  34.  * 
  35.  * Revision 1.116  1995/02/22  13:24:39  john
  36.  * Removed the vecmat anonymous unions.
  37.  * 
  38.  * Revision 1.115  1995/02/09  14:57:02  john
  39.  * Reduced mem usage. Made automap slide farther.
  40.  * 
  41.  * Revision 1.114  1995/02/07  20:40:44  rob
  42.  * Allow for anarchy automap of player pos by option.
  43.  * 
  44.  * Revision 1.113  1995/02/07  15:45:33  john
  45.  * Made automap memory be static.
  46.  * 
  47.  * Revision 1.112  1995/02/02  12:24:00  adam
  48.  * played with automap labels
  49.  * 
  50.  * Revision 1.111  1995/02/02  01:52:52  john
  51.  * Made the automap use small font.
  52.  * 
  53.  * Revision 1.110  1995/02/02  01:34:34  john
  54.  * Made Reset in automap not change segmentlimit.
  55.  * 
  56.  * Revision 1.109  1995/02/02  01:23:11  john
  57.  * Finalized the new automap partial viewer.
  58.  * 
  59.  * Revision 1.108  1995/02/02  00:49:45  mike
  60.  * new automap segment-depth functionality.
  61.  * 
  62.  * Revision 1.107  1995/02/02  00:23:04  john
  63.  * Half of the code for new connected distance stuff in automap.
  64.  * 
  65.  * Revision 1.106  1995/02/01  22:54:00  john
  66.  * Made colored doors not fade in automap. Made default
  67.  * viewing area be maxxed.
  68.  * 
  69.  * Revision 1.105  1995/02/01  13:16:13  john
  70.  * Added great grates. 
  71.  * 
  72.  * Revision 1.104  1995/01/31  12:47:06  john
  73.  * Made Alt+F only work with cheats enabled.
  74.  * 
  75.  * Revision 1.103  1995/01/31  12:41:23  john
  76.  * Working with new controls.
  77.  * 
  78.  * Revision 1.102  1995/01/31  12:04:19  john
  79.  * Version 2 of new key control.
  80.  * 
  81.  * Revision 1.101  1995/01/31  11:32:00  john
  82.  * First version of new automap system.
  83.  * 
  84.  * Revision 1.100  1995/01/28  16:55:48  john
  85.  * Made keys draw in automap in the segments that you have
  86.  * visited.
  87.  * 
  88.  * Revision 1.99  1995/01/28  14:44:51  john
  89.  * Made hostage doors show up on automap.
  90.  * 
  91.  * Revision 1.98  1995/01/22  17:03:49  rob
  92.  * Fixed problem drawing playerships in automap coop/team mode
  93.  * 
  94.  * Revision 1.97  1995/01/21  17:23:11  john
  95.  * Limited S movement in map. Made map bitmap load from disk
  96.  * and then freed it.
  97.  * 
  98.  * Revision 1.96  1995/01/19  18:55:38  john
  99.  * Don't draw players in automap if not obj_player.
  100.  * 
  101.  * Revision 1.95  1995/01/19  18:48:13  john
  102.  * Made player colors better in automap.
  103.  * 
  104.  * Revision 1.94  1995/01/19  17:34:52  rob
  105.  * Added team colorizations in automap.
  106.  * 
  107.  * Revision 1.93  1995/01/19  17:15:36  rob
  108.  * Trying to add player ships into map for coop and team mode.
  109.  * 
  110.  * Revision 1.92  1995/01/19  17:11:09  john
  111.  * Added code for Rob to draw Multiplayer ships in automap.
  112.  * 
  113.  * Revision 1.91  1995/01/12  13:35:20  john
  114.  * Fixed bug with Segment 0 not getting displayed 
  115.  * in automap if you have EDITOR compiled in.
  116.  * 
  117.  * Revision 1.90  1995/01/08  16:17:14  john
  118.  * Added code to draw player's up vector while in automap.
  119.  * 
  120.  * Revision 1.89  1995/01/08  16:09:41  john
  121.  * Fixed problems with grate.
  122.  * 
  123.  * Revision 1.88  1994/12/14  22:54:17  john
  124.  * Fixed bug that didn't show hostages in automap.
  125.  * 
  126.  * Revision 1.87  1994/12/09  00:41:03  mike
  127.  * fix hang in automap print screen
  128.  * 
  129.  * Revision 1.86  1994/12/05  23:37:15  matt
  130.  * Took out calls to warning() function
  131.  * 
  132.  * Revision 1.85  1994/12/03  22:35:28  yuan
  133.  * Localization 412
  134.  * 
  135.  * Revision 1.84  1994/12/02  15:05:45  matt
  136.  * Added new "official" cheats
  137.  * 
  138.  * Revision 1.83  1994/11/30  12:10:49  adam
  139.  * added support for PCX titles/brief screens
  140.  * 
  141.  * Revision 1.82  1994/11/27  23:15:12  matt
  142.  * Made changes for new mprintf calling convention
  143.  * 
  144.  * Revision 1.81  1994/11/27  15:35:52  matt
  145.  * Enable screen shots even when debugging is turned off
  146.  * 
  147.  * Revision 1.80  1994/11/26  22:51:43  matt
  148.  * Removed editor-only fields from segment structure when editor is compiled
  149.  * out, and padded segment structure to even multiple of 4 bytes.
  150.  * 
  151.  * Revision 1.79  1994/11/26  16:22:48  matt
  152.  * Reduced leave_time
  153.  * 
  154.  * Revision 1.78  1994/11/23  22:00:10  mike
  155.  * show level number.
  156.  * 
  157.  * Revision 1.77  1994/11/21  11:40:33  rob
  158.  * Tweaked the game-loop for automap in multiplayer games.
  159.  * 
  160.  * Revision 1.76  1994/11/18  16:42:06  adam
  161.  * removed a font
  162.  * 
  163.  * Revision 1.75  1994/11/17  13:06:48  adam
  164.  * changed font
  165.  * 
  166.  * Revision 1.74  1994/11/14  20:47:17  john
  167.  * Attempted to strip out all the code in the game 
  168.  * directory that uses any ui code.
  169.  * 
  170.  */
  171.  
  172.  
  173. #pragma off (unreferenced)
  174. static char rcsid[] = "$Id: automap.c 2.2 1995/03/21 14:41:26 john Exp $";
  175. #pragma on (unreferenced)
  176.  
  177. #include <stdio.h>
  178. #include <stdlib.h>
  179. #include <string.h>
  180. #include <math.h>
  181.  
  182. #include "error.h"
  183. #include "3d.h"
  184. #include "inferno.h"
  185. #include "mem.h"
  186. #include "render.h"
  187. #include "object.h"
  188. #include "vclip.h"
  189. #include "game.h"
  190. #include "mono.h"
  191. #include "polyobj.h"
  192. #include "sounds.h"
  193. #include "player.h"
  194. #include "bm.h"
  195. #include "key.h"
  196. #include "screens.h"
  197. #include "textures.h"
  198. #include "mouse.h"
  199. #include "timer.h"
  200. #include "segpoint.h"
  201. #include "joy.h"
  202. #include "iff.h"
  203. #include "pcx.h"
  204. #include "palette.h"
  205. #include "wall.h"
  206. #include "hostage.h"
  207. #include "fuelcen.h"
  208. #include "gameseq.h"
  209. #include "gamefont.h"
  210. #include "network.h"
  211. #include "kconfig.h"
  212. #include "multi.h"
  213. #include "endlevel.h"
  214. #include "text.h"
  215. #include "gauges.h"
  216. #include "powerup.h"
  217. #include "network.h" 
  218.  
  219. #define EF_USED            1        // This edge is used
  220. #define EF_DEFINING        2        // A structure defining edge that should always draw.
  221. #define EF_FRONTIER        4        // An edge between the known and the unknown.
  222. #define EF_SECRET            8        // An edge that is part of a secret wall.
  223. #define EF_GRATE            16        // A grate... draw it all the time.
  224. #define EF_NO_FADE        32        // An edge that doesn't fade with distance
  225. #define EF_TOO_FAR        64        // An edge that is too far away
  226.  
  227. typedef struct Edge_info {
  228.     union {
  229.         short    verts[2];        // 4 bytes
  230.         long vv;
  231.     };
  232.     ubyte sides[4];            // 4 bytes
  233.     short segnum[4];            // 8 bytes    // This might not need to be stored... If you can access the normals of a side.
  234.     ubyte flags;                // 1 bytes     // See the EF_??? defines above.
  235.     ubyte color;                // 1 bytes
  236.     ubyte num_faces;            // 1 bytes    // 19 bytes...
  237. } Edge_info;
  238.  
  239. //OLD BUT GOOD -- #define MAX_EDGES_FROM_VERTS(v)   ((v*5)/2)
  240. // THE following was determined by John by loading levels 1-14 and recording
  241. // numbers on 10/26/94. 
  242. //#define MAX_EDGES_FROM_VERTS(v)   (((v)*21)/10)
  243. #define MAX_EDGES_FROM_VERTS(v)        ((v)*4)
  244. //#define MAX_EDGES (MAX_EDGES_FROM_VERTS(MAX_VERTICES))
  245.  
  246. #define MAX_EDGES 6000        // Determined by loading all the levels by John & Mike, Feb 9, 1995
  247.  
  248. #define    WALL_NORMAL_COLOR                 BM_XRGB( 29, 29, 29 )
  249. #define    WALL_DOOR_COLOR                    BM_XRGB( 21, 31, 11 )
  250. #define    WALL_DOOR_BLUE                        BM_XRGB( 0, 0, 31)
  251. #define    WALL_DOOR_GOLD                        BM_XRGB( 31, 31, 0)
  252. #define    WALL_DOOR_RED                        BM_XRGB( 31, 0, 0)
  253.  
  254. // Segment visited list
  255. ubyte Automap_visited[MAX_SEGMENTS];
  256.  
  257. // Edge list variables
  258. static int Num_edges=0;
  259. static int Max_edges;        //set each frame
  260. static int Highest_edge_index = -1;
  261. static Edge_info Edges[MAX_EDGES];
  262. static short DrawingListBright[MAX_EDGES];
  263.  
  264. //static short DrawingListBright[MAX_EDGES];
  265. //static short Edge_used_list[MAX_EDGES];                //which entries in edge_list have been used
  266.  
  267. // Map movement defines
  268. #define PITCH_DEFAULT 9000
  269. #define ZOOM_DEFAULT i2f(20*10)
  270. #define ZOOM_MIN_VALUE i2f(20*5)
  271. #define ZOOM_MAX_VALUE i2f(20*100)
  272.  
  273. #define SLIDE_SPEED                 (350)
  274. #define ZOOM_SPEED_FACTOR        (1500)
  275. #define ROT_SPEED_DIVISOR        (115000)
  276.  
  277. // Screen anvas variables
  278. static int current_page=0;
  279. static grs_canvas Pages[2];
  280. static grs_canvas DrawingPages[2];
  281.  
  282. // Flags
  283. static int Automap_cheat = 0;        // If set, show everything
  284.  
  285. // Rendering variables
  286. static fix Automap_zoom = 0x9000;
  287. static vms_vector view_target;
  288. static fix Automap_farthest_dist = (F1_0 * 20 * 50);        // 50 segments away
  289. static vms_matrix    ViewMatrix;
  290. static fix ViewDist=0;
  291.  
  292. void automap_clear_visited()    
  293. {
  294.     int i;
  295.     for (i=0; i<MAX_SEGMENTS; i++ )
  296.         Automap_visited[i] = 0;
  297. }
  298.  
  299. grs_canvas *name_canv;
  300.  
  301. void draw_player( object * obj )
  302. {
  303.     vms_vector arrow_pos, head_pos;
  304.     g3s_point sphere_point, arrow_point, head_point;
  305.  
  306.     // Draw Console player -- shaped like a ellipse with an arrow.
  307.     g3_rotate_point(&sphere_point,&obj->pos);
  308.     g3_draw_sphere(&sphere_point,obj->size);
  309.  
  310.     // Draw shaft of arrow
  311.     vm_vec_scale_add( &arrow_pos, &obj->pos, &obj->orient.fvec, obj->size*3 );
  312.     g3_rotate_point(&arrow_point,&arrow_pos);
  313.     g3_draw_line( &sphere_point, &arrow_point );
  314.  
  315.     // Draw right head of arrow
  316.     vm_vec_scale_add( &head_pos, &obj->pos, &obj->orient.fvec, obj->size*2 );
  317.     vm_vec_scale_add2( &head_pos, &obj->orient.rvec, obj->size*1 );
  318.     g3_rotate_point(&head_point,&head_pos);
  319.     g3_draw_line( &arrow_point, &head_point );
  320.  
  321.     // Draw left head of arrow
  322.     vm_vec_scale_add( &head_pos, &obj->pos, &obj->orient.fvec, obj->size*2 );
  323.     vm_vec_scale_add2( &head_pos, &obj->orient.rvec, obj->size*(-1) );
  324.     g3_rotate_point(&head_point,&head_pos);
  325.     g3_draw_line( &arrow_point, &head_point );
  326.  
  327.     // Draw player's up vector
  328.     vm_vec_scale_add( &arrow_pos, &obj->pos, &obj->orient.uvec, obj->size*2 );
  329.     g3_rotate_point(&arrow_point,&arrow_pos);
  330.     g3_draw_line( &sphere_point, &arrow_point );
  331. }
  332.  
  333.  
  334. void draw_automap()
  335. {
  336.     int i;
  337.     int color;
  338.     object * objp;
  339.     vms_vector viewer_position;
  340.     g3s_point sphere_point;
  341.  
  342.     current_page ^= 1;
  343.     gr_set_current_canvas(&DrawingPages[current_page]);
  344.  
  345.     gr_clear_canvas(0);
  346.  
  347.     g3_start_frame();
  348.     render_start_frame();
  349.     
  350.     vm_vec_scale_add(&viewer_position,&view_target,&ViewMatrix.fvec,-ViewDist );
  351.  
  352.     g3_set_view_matrix(&viewer_position,&ViewMatrix,Automap_zoom);
  353.  
  354.     draw_all_edges();
  355.  
  356.     // Draw player...
  357. #ifdef NETWORK
  358.     if (Game_mode & GM_TEAM)
  359.         color = get_team(Player_num);
  360.     else
  361. #endif    
  362.         color = Player_num;    // Note link to above if!
  363.     gr_setcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b));
  364.     draw_player(&Objects[Players[Player_num].objnum]);
  365.                 
  366.     // Draw player(s)...
  367. #ifdef NETWORK
  368.     if ( (Game_mode & (GM_TEAM | GM_MULTI_COOP)) || (Netgame.game_flags & NETGAME_FLAG_SHOW_MAP) )    {
  369.         for (i=0; i<N_players; i++)        {
  370.             if ( (i != Player_num) && ((Game_mode & GM_MULTI_COOP) || (get_team(Player_num) == get_team(i)) || (Netgame.game_flags & NETGAME_FLAG_SHOW_MAP)) )    {
  371.                 if ( Objects[Players[i].objnum].type == OBJ_PLAYER )    {
  372.                     if (Game_mode & GM_TEAM)
  373.                         color = get_team(i);
  374.                     else
  375.                         color = i;
  376.                     gr_setcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b));
  377.                     draw_player(&Objects[Players[i].objnum]);
  378.                 }
  379.             }
  380.         }
  381.     }
  382. #endif
  383.  
  384.     objp = &Objects[0];
  385.     for (i=0;i<=Highest_object_index;i++,objp++) {
  386.         switch( objp->type )    {
  387.         case OBJ_HOSTAGE:
  388.             gr_setcolor(BM_XRGB(0,31,0));
  389.             g3_rotate_point(&sphere_point,&objp->pos);
  390.             g3_draw_sphere(&sphere_point,objp->size);    
  391.             break;
  392.         case OBJ_POWERUP:
  393.             if ( Automap_visited[objp->segnum] )    {
  394.                 if ( (objp->id==POW_KEY_RED) || (objp->id==POW_KEY_BLUE) || (objp->id==POW_KEY_GOLD) )    {
  395.                     switch (objp->id) {
  396.                     case POW_KEY_RED:        gr_setcolor(gr_getcolor(63, 5, 5));    break;
  397.                     case POW_KEY_BLUE:    gr_setcolor(gr_getcolor(5, 5, 63)); break;
  398.                     case POW_KEY_GOLD:    gr_setcolor(gr_getcolor(63, 63, 10)); break;
  399.                     }
  400.                     g3_rotate_point(&sphere_point,&objp->pos);
  401.                     g3_draw_sphere(&sphere_point,objp->size*4);    
  402.                 }
  403.             }
  404.             break;
  405.         }
  406.     }
  407.  
  408.     g3_end_frame();
  409.  
  410.     gr_bitmapm(5,5,&name_canv->cv_bitmap);
  411.  
  412.     gr_show_canvas( &Pages[current_page] );
  413.     
  414. }
  415.  
  416. #define LEAVE_TIME 0x4000
  417.  
  418. //print to canvas & double height
  419. grs_canvas *print_to_canvas(char *s,grs_font *font, int fc, int bc)
  420. {
  421.     int y;
  422.     ubyte *data;
  423.     int rs;
  424.     grs_canvas *temp_canv,*save_canv;
  425.  
  426.     save_canv = grd_curcanv;
  427.  
  428.     temp_canv = gr_create_canvas(font->ft_w*strlen(s),font->ft_h*2);
  429.  
  430.     gr_set_current_canvas(temp_canv);
  431.     gr_set_curfont(font);
  432.     gr_clear_canvas(255);                        //trans color
  433.     gr_set_fontcolor(fc,bc);
  434.     gr_printf(0,0,s);
  435.  
  436.     //now double it, since we're drawing to 400-line modex screen
  437.  
  438.     data = temp_canv->cv_bitmap.bm_data;
  439.     rs = temp_canv->cv_bitmap.bm_rowsize;
  440.  
  441.     for (y=temp_canv->cv_bitmap.bm_h/2;y--;) {
  442.         memcpy(data+(rs*y*2),data+(rs*y),temp_canv->cv_bitmap.bm_w);
  443.         memcpy(data+(rs*(y*2+1)),data+(rs*y),temp_canv->cv_bitmap.bm_w);
  444.     }
  445.  
  446.     gr_set_current_canvas(save_canv);
  447.  
  448.     return temp_canv;
  449. }
  450.  
  451. //print to buffer, double heights, and blit bitmap to screen
  452. modex_printf(int x,int y,char *s,int fontnum)
  453. {
  454.     grs_canvas *temp_canv;
  455.  
  456.     temp_canv = print_to_canvas(s,Gamefonts[fontnum], BM_XRGB(20,20,20), -1);
  457.  
  458.     gr_bitmapm(x,y,&temp_canv->cv_bitmap);
  459.  
  460.     gr_free_canvas(temp_canv);
  461. }
  462.  
  463. create_name_canv()
  464. {
  465.     char    name_level[128];
  466.  
  467.     if (Current_level_num > 0)
  468.         sprintf(name_level, "%s %i: ",TXT_LEVEL, Current_level_num);
  469.     else
  470.         name_level[0] = 0;
  471.  
  472.     strcat(name_level, Current_level_name);
  473.  
  474.     gr_set_fontcolor(BM_XRGB(0,31,0),-1);
  475.     name_canv = print_to_canvas(name_level,Gamefonts[GFONT_SMALL], BM_XRGB(0,31,0), -1);
  476.  
  477. }
  478.  
  479. void modex_print_message(int x, int y, char *str)
  480. {
  481.     int    i;
  482.  
  483.     for (i=0; i<2; i++ )    {
  484.         gr_set_current_canvas(&Pages[i]);
  485.         modex_printf(x, y, str, GFONT_MEDIUM_1);
  486.     }
  487.  
  488.     gr_set_current_canvas(&DrawingPages[current_page]);
  489. }
  490.  
  491. extern void GameLoop(int, int );
  492. extern int set_segment_depths(int start_seg, ubyte *segbuf);
  493.  
  494. void do_automap( int key_code )    {
  495.     int done=0;
  496.     vms_matrix    tempm;
  497.     vms_angvec    tangles;
  498.     int leave_mode=0;
  499.     int first_time=1;
  500.     int pcx_error;
  501.     int i;
  502.     int c;
  503.     char filename[] = "MAP.PCX";
  504.     fix entry_time;
  505.     int pause_game=1;        // Set to 1 if everything is paused during automap...No pause during net.
  506.     fix t1, t2;
  507.     control_info saved_control_info;
  508.     grs_bitmap Automap_background;
  509.     int Max_segments_away = 0;
  510.     int SegmentLimit = 1;
  511.  
  512.     key_code = key_code;    // disable warning...
  513.  
  514.     if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence))
  515.         pause_game = 0;
  516.  
  517.     if (pause_game)
  518.         stop_time();
  519.  
  520.     create_name_canv();
  521.  
  522.     Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES);            //make maybe smaller than max
  523.     //Edges    = malloc( sizeof(Edge_info)*Max_edges);
  524.     //if ( Edges == NULL )    {
  525.     //    mprintf((0, "Couldn't get %dK for automap!", sizeof(Edge_info)*Max_edges/1024));
  526.     //    return;
  527.     //}
  528.     //DrawingListBright = malloc( sizeof(short)*Max_edges);
  529.     //if ( DrawingListBright == NULL )    {
  530.     //    mprintf((0, "Couldn't get %dK for automap!", sizeof(short)*Max_edges/1024));
  531.     //    return;
  532.     //}
  533.  
  534.     mprintf( (0, "Num_vertices=%d, Max_edges=%d, (MAX:%d)\n", Num_vertices, Max_edges, MAX_EDGES ));
  535.     mprintf( (0, "Allocated %d K for automap edge list\n", (sizeof(Edge_info)+sizeof(short))*Max_edges/1024 ));
  536.  
  537.     gr_set_mode( SM_320x400U );
  538.     gr_palette_clear();
  539.  
  540.     gr_init_sub_canvas(&Pages[0],grd_curcanv,0,0,320,400);
  541.     gr_init_sub_canvas(&Pages[1],grd_curcanv,0,401,320,400);
  542.     gr_init_sub_canvas(&DrawingPages[0],&Pages[0],16,69,288,272);
  543.     gr_init_sub_canvas(&DrawingPages[1],&Pages[1],16,69,288,272);
  544.  
  545.     Automap_background.bm_data = NULL;
  546.     pcx_error = pcx_read_bitmap(filename,&Automap_background,BM_LINEAR,NULL);
  547.     if ( pcx_error != PCX_ERROR_NONE )    {
  548.         printf("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
  549.         Error("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
  550.         return;
  551.     }
  552.  
  553.     for (i=0; i<2; i++ )    {
  554.         gr_set_current_canvas(&Pages[i]);
  555.         gr_bitmap( 0, 0, &Automap_background );
  556.         modex_printf( 40, 22,TXT_AUTOMAP,GFONT_BIG_1);
  557.         modex_printf( 70,353,TXT_TURN_SHIP,GFONT_SMALL);
  558.         modex_printf( 70,369,TXT_SLIDE_UPDOWN,GFONT_SMALL);
  559.         modex_printf( 70,385,TXT_VIEWING_DISTANCE,GFONT_SMALL);
  560.     }
  561.     if ( Automap_background.bm_data )
  562.         free( Automap_background.bm_data );
  563.     Automap_background.bm_data = NULL;
  564.  
  565.     gr_set_current_canvas(&DrawingPages[current_page]);
  566.  
  567.     automap_build_edge_list();
  568.  
  569.     if ( ViewDist==0 ) 
  570.         ViewDist = ZOOM_DEFAULT;
  571.     ViewMatrix = Objects[Players[Player_num].objnum].orient;
  572.  
  573.     tangles.p = PITCH_DEFAULT;
  574.     tangles.h  = 0;
  575.     tangles.b  = 0;
  576.  
  577.     done = 0;
  578.  
  579.     view_target = Objects[Players[Player_num].objnum].pos;
  580.  
  581.     t1 = entry_time = timer_get_fixed_seconds();
  582.     t2 = t1;
  583.  
  584.     //Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum
  585.     Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
  586.     SegmentLimit = Max_segments_away;
  587.  
  588.     adjust_segment_limit(SegmentLimit);
  589.  
  590.     while(!done)    {
  591.         if ( leave_mode==0 && Controls.automap_state && (timer_get_fixed_seconds()-entry_time)>LEAVE_TIME)
  592.             leave_mode = 1;
  593.  
  594.         if ( !Controls.automap_state && (leave_mode==1) )
  595.             done=1;
  596.  
  597.         if (!pause_game)    {
  598.             ushort old_wiggle;
  599.             saved_control_info = Controls;                // Save controls so we can zero them
  600.             memset(&Controls,0,sizeof(control_info));    // Clear everything...
  601.             old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE;    // Save old wiggle
  602.             ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE;        // Turn off wiggle
  603.             #ifdef NETWORK
  604.             if (multi_menu_poll())
  605.                 done = 1;
  606.             #endif
  607. //            GameLoop( 0, 0 );        // Do game loop with no rendering and no reading controls.
  608.             ConsoleObject->mtype.phys_info.flags |= old_wiggle;    // Restore wiggle
  609.             Controls = saved_control_info;
  610.         } 
  611.  
  612.         controls_read_all();        
  613.         if ( Controls.automap_down_count )    {
  614.             if (leave_mode==0)
  615.                 done = 1;
  616.             c = 0;
  617.         }
  618.  
  619.         while( (c=key_inkey()) )    {
  620.             switch( c ) {
  621.             #ifndef NDEBUG
  622.             case KEY_BACKSP: Int3(); break;
  623.             #endif
  624.     
  625.             case KEY_PRINT_SCREEN: save_screen_shot(1); break;
  626.     
  627.             case KEY_ESC:
  628.                 if (leave_mode==0)
  629.                     done = 1;
  630.                  break;
  631.             case KEY_ALTED+KEY_F:        // Alt+F shows full map, if cheats enabled
  632.                 if (Cheats_enabled) 
  633.                 {
  634.                     uint t;    
  635.                     t = Players[Player_num].flags;
  636.                     Players[Player_num].flags |= PLAYER_FLAGS_MAP_ALL_CHEAT;
  637.                     automap_build_edge_list();
  638.                     Players[Player_num].flags=t;
  639.                  }
  640.                 break;
  641.     
  642.     #ifndef NDEBUG
  643.               case KEY_DEBUGGED+KEY_F:     {
  644.                 for (i=0; i<=Highest_segment_index; i++ )
  645.                     Automap_visited[i] = 1;
  646.                 automap_build_edge_list();
  647.                 Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
  648.                 SegmentLimit = Max_segments_away;
  649.                 adjust_segment_limit(SegmentLimit);
  650.                 }
  651.                 break;
  652.     #endif
  653.             case KEY_MINUS:
  654.                 if (SegmentLimit > 1)         {
  655.                     SegmentLimit--;
  656.                     adjust_segment_limit(SegmentLimit);
  657.                 }
  658.                 break;
  659.             case KEY_EQUAL:
  660.                 if (SegmentLimit < Max_segments_away)     {
  661.                     SegmentLimit++;
  662.                     adjust_segment_limit(SegmentLimit);
  663.                 }
  664.                 break;
  665.             }
  666.         }
  667.  
  668.         if ( Controls.fire_primary_down_count )    {
  669.             // Reset orientation
  670.             ViewDist = ZOOM_DEFAULT;
  671.             tangles.p = PITCH_DEFAULT;
  672.             tangles.h  = 0;
  673.             tangles.b  = 0;
  674.             view_target = Objects[Players[Player_num].objnum].pos;
  675.         }
  676.  
  677.         ViewDist -= Controls.forward_thrust_time*ZOOM_SPEED_FACTOR;
  678.  
  679.         tangles.p += fixdiv( Controls.pitch_time, ROT_SPEED_DIVISOR );
  680.         tangles.h  += fixdiv( Controls.heading_time, ROT_SPEED_DIVISOR );
  681.         tangles.b  += fixdiv( Controls.bank_time, ROT_SPEED_DIVISOR*2 );
  682.         
  683.         if ( Controls.vertical_thrust_time || Controls.sideways_thrust_time )    {
  684.             vms_angvec    tangles1;
  685.             vms_vector    old_vt;
  686.             old_vt = view_target;
  687.             tangles1 = tangles;
  688.             vm_angles_2_matrix(&tempm,&tangles1);
  689.             vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
  690.             vm_vec_scale_add2( &view_target, &ViewMatrix.uvec, Controls.vertical_thrust_time*SLIDE_SPEED );
  691.             vm_vec_scale_add2( &view_target, &ViewMatrix.rvec, Controls.sideways_thrust_time*SLIDE_SPEED );
  692.             if ( vm_vec_dist_quick( &view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) )    {
  693.                 view_target = old_vt;
  694.             }
  695.         } 
  696.  
  697.         vm_angles_2_matrix(&tempm,&tangles);
  698.         vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
  699.  
  700.         if ( ViewDist < ZOOM_MIN_VALUE ) ViewDist = ZOOM_MIN_VALUE;
  701.         if ( ViewDist > ZOOM_MAX_VALUE ) ViewDist = ZOOM_MAX_VALUE;
  702.  
  703.         draw_automap();
  704.  
  705.         if ( first_time )    {
  706.             first_time = 0;
  707.             gr_palette_load( gr_palette );
  708.         }
  709.  
  710.         t2 = timer_get_fixed_seconds();
  711.         if (pause_game)
  712.             FrameTime=t2-t1;
  713.         t1 = t2;
  714.     }
  715.  
  716.     //free(Edges);
  717.     //free(DrawingListBright);
  718.     gr_free_canvas(name_canv);  name_canv=NULL;
  719.  
  720.     mprintf( (0, "Automap memory freed\n" ));
  721.  
  722.     game_flush_inputs();
  723.  
  724.     if (pause_game)
  725.         start_time();
  726. }
  727.  
  728. void adjust_segment_limit(int SegmentLimit)
  729. {
  730.     int i,e1;
  731.     Edge_info * e;
  732.  
  733.     mprintf(( 0, "Seglimit: %d\n", SegmentLimit ));
  734.     
  735.     for (i=0; i<=Highest_edge_index; i++ )    {
  736.         e = &Edges[i];
  737.         e->flags |= EF_TOO_FAR;
  738.         for (e1=0; e1<e->num_faces; e1++ )    {
  739.             if ( Automap_visited[e->segnum[e1]] <= SegmentLimit )    {
  740.                 e->flags &= (~EF_TOO_FAR);
  741.                 break;
  742.             }
  743.         }
  744.     }
  745.     
  746. }
  747.  
  748. void draw_all_edges()    
  749. {
  750.     g3s_codes cc;
  751.     int i,j,nbright;
  752.     ubyte nfacing,nnfacing;
  753.     Edge_info *e;
  754.     vms_vector *tv1;
  755.     fix distance;
  756.     fix min_distance = 0x7fffffff;
  757.     g3s_point *p1, *p2;
  758.     
  759.     
  760.     nbright=0;
  761.  
  762.     for (i=0; i<=Highest_edge_index; i++ )    {
  763.         //e = &Edges[Edge_used_list[i]];
  764.         e = &Edges[i];
  765.         if (!(e->flags & EF_USED)) continue;
  766.  
  767.         if ( e->flags & EF_TOO_FAR) continue;
  768.  
  769.         if (e->flags&EF_FRONTIER)    {                        // A line that is between what we have seen and what we haven't
  770.             if ( (!(e->flags&EF_SECRET))&&(e->color==WALL_NORMAL_COLOR))
  771.                 continue;        // If a line isn't secret and is normal color, then don't draw it
  772.         }
  773.  
  774.         cc=rotate_list(2,e->verts);
  775.         distance = Segment_points[e->verts[1]].z;
  776.  
  777.         if (min_distance>distance )
  778.             min_distance = distance;
  779.  
  780.         if (!cc.and)     {    //all off screen?
  781.             nfacing = nnfacing = 0;
  782.             tv1 = &Vertices[e->verts[0]];
  783.             j = 0;
  784.             while( j<e->num_faces && (nfacing==0 || nnfacing==0) )    {
  785.                 #ifdef COMPACT_SEGS
  786.                 vms_vector temp_v;
  787.                 get_side_normal(&Segments[e->segnum[j]], e->sides[j], 0, &temp_v );
  788.                 if (!g3_check_normal_facing( tv1, &temp_v ) )
  789.                 #else
  790.                 if (!g3_check_normal_facing( tv1, &Segments[e->segnum[j]].sides[e->sides[j]].normals[0] ) )
  791.                 #endif
  792.                     nfacing++;
  793.                 else
  794.                     nnfacing++;
  795.                 j++;
  796.             }
  797.  
  798.             if ( nfacing && nnfacing )    {
  799.                 // a contour line
  800.                 DrawingListBright[nbright++] = e-Edges;
  801.             } else if ( e->flags&(EF_DEFINING|EF_GRATE) )    {
  802.                 if ( nfacing == 0 )    {
  803.                     if ( e->flags & EF_NO_FADE )
  804.                         gr_setcolor( e->color );
  805.                     else
  806.                         gr_setcolor( gr_fade_table[e->color+256*8] );
  807.                     g3_draw_line( &Segment_points[e->verts[0]], &Segment_points[e->verts[1]] );
  808.                 }     else {
  809.                     DrawingListBright[nbright++] = e-Edges;
  810.                 }
  811.             }
  812.         }
  813.     }
  814.         
  815. ///    mprintf( (0, "Min distance=%.2f, ViewDist=%.2f, Delta=%.2f\n", f2fl(min_distance), f2fl(ViewDist), f2fl(min_distance)- f2fl(ViewDist) ));
  816.  
  817.     if ( min_distance < 0 ) min_distance = 0;
  818.  
  819.     // Sort the bright ones using a shell sort
  820.     {
  821.         int t;
  822.         int i, j, incr, v1, v2;
  823.     
  824.         incr = nbright / 2;
  825.         while( incr > 0 )    {
  826.             for (i=incr; i<nbright; i++ )    {
  827.                 j = i - incr;
  828.                 while (j>=0 )    {
  829.                     // compare element j and j+incr
  830.                     v1 = Edges[DrawingListBright[j]].verts[0];
  831.                     v2 = Edges[DrawingListBright[j+incr]].verts[0];
  832.  
  833.                     if (Segment_points[v1].z < Segment_points[v2].z) {
  834.                         // If not in correct order, them swap 'em
  835.                         t=DrawingListBright[j+incr];
  836.                         DrawingListBright[j+incr]=DrawingListBright[j];
  837.                         DrawingListBright[j]=t;
  838.                         j -= incr;
  839.                     }
  840.                     else
  841.                         break;
  842.                 }
  843.             }
  844.             incr = incr / 2;
  845.         }
  846.     }
  847.                     
  848.     // Draw the bright ones
  849.     for (i=0; i<nbright; i++ )    {
  850.         int color;
  851.         fix dist;
  852.         e = &Edges[DrawingListBright[i]];
  853.         p1 = &Segment_points[e->verts[0]];
  854.         p2 = &Segment_points[e->verts[1]];
  855.         dist = p1->z - min_distance;
  856.         // Make distance be 1.0 to 0.0, where 0.0 is 10 segments away;
  857.         if ( dist < 0 ) dist=0;
  858.         if ( dist >= Automap_farthest_dist ) continue;
  859.  
  860.         if ( e->flags & EF_NO_FADE )    {
  861.             gr_setcolor( e->color );
  862.         } else {
  863.             dist = F1_0 - fixdiv( dist, Automap_farthest_dist );
  864.             color = f2i( dist*31 );
  865.             gr_setcolor( gr_fade_table[e->color+color*256] );    
  866.         }
  867.         g3_draw_line( p1, p2 );
  868.     }
  869.  
  870. }
  871.  
  872.  
  873. //==================================================================
  874. //
  875. // All routines below here are used to build the Edge list
  876. //
  877. //==================================================================
  878.  
  879.  
  880. //finds edge, filling in edge_ptr. if found old edge, returns index, else return -1
  881. static int automap_find_edge(int v0,int v1,Edge_info **edge_ptr)
  882. {
  883.     long vv;
  884.     short hash,oldhash;
  885.     int ret;
  886.  
  887.     vv = (v1<<16) + v0;
  888.  
  889.     oldhash = hash = ((v0*5+v1) % Max_edges);
  890.  
  891.     ret = -1;
  892.  
  893.     while (ret==-1) {
  894.         if (Edges[hash].num_faces == 0 ) ret=0;
  895.         else if (Edges[hash].vv == vv) ret=1;
  896.         else {
  897.             if (++hash==Max_edges) hash=0;
  898.             if (hash==oldhash) Error("Edge list full!");
  899.         }
  900.     }
  901.  
  902.     *edge_ptr = &Edges[hash];
  903.  
  904.     if (ret == 0)
  905.         return -1;
  906.     else
  907.         return hash;
  908.  
  909. }
  910.  
  911.  
  912. void add_one_edge( short va, short vb, ubyte color, ubyte side, short segnum, int hidden, int grate, int no_fade )    {
  913.     int found;
  914.     Edge_info *e;
  915.     short tmp;
  916.  
  917.     if ( Num_edges >= Max_edges)    {
  918.         // GET JOHN! (And tell him that his 
  919.         // MAX_EDGES_FROM_VERTS formula is hosed.)
  920.         // If he's not around, save the mine, 
  921.         // and send him  mail so he can look 
  922.         // at the mine later. Don't modify it.
  923.         // This is important if this happens.
  924.         Int3();        // LOOK ABOVE!!!!!!
  925.         return;
  926.     }
  927.  
  928.     if ( va > vb )    {
  929.         tmp = va;
  930.         va = vb;
  931.         vb = tmp;
  932.     }
  933.  
  934.     found = automap_find_edge(va,vb,&e);
  935.         
  936.     if (found == -1) {
  937.         e->verts[0] = va;
  938.         e->verts[1] = vb;
  939.         e->color = color;
  940.         e->num_faces = 1;
  941.         e->flags = EF_USED | EF_DEFINING;            // Assume a normal line
  942.         e->sides[0] = side;
  943.         e->segnum[0] = segnum;
  944.         //Edge_used_list[Num_edges] = e-Edges;
  945.         if ( (e-Edges) > Highest_edge_index )
  946.             Highest_edge_index = e - Edges;
  947.         Num_edges++;
  948.     } else {
  949.         //Assert(e->num_faces < 8 );
  950.  
  951.         if ( color != WALL_NORMAL_COLOR )
  952.             e->color = color;
  953.         if ( e->num_faces < 4 ) {
  954.             e->sides[e->num_faces] = side;                    
  955.             e->segnum[e->num_faces] = segnum;
  956.             e->num_faces++;
  957.         }
  958.     }
  959.  
  960.     if ( grate )
  961.         e->flags |= EF_GRATE;
  962.  
  963.     if ( hidden )
  964.         e->flags|=EF_SECRET;        // Mark this as a hidden edge
  965.     if ( no_fade )
  966.         e->flags |= EF_NO_FADE;
  967. }
  968.  
  969. void add_one_unknown_edge( short va, short vb )    {
  970.     int found;
  971.     Edge_info *e;
  972.     short tmp;
  973.  
  974.     if ( va > vb )    {
  975.         tmp = va;
  976.         va = vb;
  977.         vb = tmp;
  978.     }
  979.  
  980.     found = automap_find_edge(va,vb,&e);
  981.     if (found != -1)     
  982.         e->flags|=EF_FRONTIER;        // Mark as a border edge
  983. }
  984.  
  985. extern obj_position Player_init[];
  986.  
  987. void add_segment_edges(segment *seg)
  988. {
  989.     int     is_grate, no_fade;
  990.     ubyte    color;
  991.     int    sn;
  992.     int    segnum = seg-Segments;
  993.     int    hidden_flag;
  994.     
  995.     for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++) {
  996.         short    vertex_list[4];
  997.  
  998.         hidden_flag = 0;
  999.  
  1000.         is_grate = 0;
  1001.         no_fade = 0;
  1002.  
  1003.         color = 255;
  1004.         if (seg->children[sn] == -1) {
  1005.             color = WALL_NORMAL_COLOR;
  1006.         }
  1007.  
  1008.         switch( seg->special )    {
  1009.         case SEGMENT_IS_FUELCEN:
  1010.             color = BM_XRGB( 29, 27, 13 );
  1011.             break;
  1012.         case SEGMENT_IS_CONTROLCEN:
  1013.             color = BM_XRGB( 29, 0, 0 );
  1014.             break;
  1015.         case SEGMENT_IS_ROBOTMAKER:
  1016.             color = BM_XRGB( 29, 0, 31 );
  1017.             break;
  1018.         }
  1019.  
  1020.         if (seg->sides[sn].wall_num > -1)    {
  1021.  
  1022.             switch( Walls[seg->sides[sn].wall_num].type )    {
  1023.             case WALL_DOOR:
  1024.                 if (Walls[seg->sides[sn].wall_num].keys == KEY_BLUE) {
  1025.                     no_fade = 1;
  1026.                     color = WALL_DOOR_BLUE;
  1027.                     //mprintf((0, "Seg %i, side %i has BLUE wall\n", segnum, sn));
  1028.                 } else if (Walls[seg->sides[sn].wall_num].keys == KEY_GOLD) {
  1029.                     no_fade = 1;
  1030.                     color = WALL_DOOR_GOLD;
  1031.                     //mprintf((0, "Seg %i, side %i has GOLD wall\n", segnum, sn));
  1032.                 } else if (Walls[seg->sides[sn].wall_num].keys == KEY_RED) {
  1033.                     no_fade = 1;
  1034.                     color = WALL_DOOR_RED;
  1035.                     //mprintf((0, "Seg %i, side %i has RED wall\n", segnum, sn));
  1036.                 } else if (!(WallAnims[Walls[seg->sides[sn].wall_num].clip_num].flags & WCF_HIDDEN)) {
  1037.                     int    connected_seg = seg->children[sn];
  1038.                     if (connected_seg != -1) {
  1039.                         int connected_side = find_connect_side(seg, &Segments[connected_seg]);
  1040.                         int    keytype = Walls[Segments[connected_seg].sides[connected_side].wall_num].keys;
  1041.                         if ((keytype != KEY_BLUE) && (keytype != KEY_GOLD) && (keytype != KEY_RED))
  1042.                             color = WALL_DOOR_COLOR;
  1043.                         else {
  1044.                             switch (Walls[Segments[connected_seg].sides[connected_side].wall_num].keys) {
  1045.                                 case KEY_BLUE:    color = WALL_DOOR_BLUE;    no_fade = 1; break;
  1046.                                 case KEY_GOLD:    color = WALL_DOOR_GOLD;    no_fade = 1; break;
  1047.                                 case KEY_RED:    color = WALL_DOOR_RED;    no_fade = 1; break;
  1048.                                 default:    Error("Inconsistent data.  Supposed to be a colored wall, but not blue, gold or red.\n");
  1049.                             }
  1050.                             //mprintf((0, "Seg %i, side %i has a colored door on the other side.\n", segnum, sn));
  1051.                         }
  1052.                     }
  1053.                 } else {
  1054.                     color = WALL_NORMAL_COLOR;
  1055.                     hidden_flag = 1;
  1056.                     //mprintf((0, "Wall at seg:side %i:%i is hidden.\n", seg-Segments, sn));
  1057.                 }
  1058.                 break;
  1059.             case WALL_CLOSED:
  1060.                 // Make grates draw properly
  1061.                 color = WALL_NORMAL_COLOR;
  1062.                 is_grate = 1;
  1063.                 break;
  1064.             case WALL_BLASTABLE:
  1065.                 // Hostage doors
  1066.                 color = WALL_DOOR_COLOR;    
  1067.                 break;
  1068.             }
  1069.         }
  1070.     
  1071.         if (segnum==Player_init[Player_num].segnum)
  1072.             color = BM_XRGB(31,0,31);
  1073.  
  1074.         if ( color != 255 )    {
  1075.             // If they have a map powerup, draw unvisited areas in dark blue.
  1076.             if (Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL && (!Automap_visited[segnum]))    
  1077.                 color = BM_XRGB( 0, 0, 25 );
  1078.  
  1079.             get_side_verts(vertex_list,segnum,sn);
  1080.             add_one_edge( vertex_list[0], vertex_list[1], color, sn, segnum, hidden_flag, 0, no_fade );
  1081.             add_one_edge( vertex_list[1], vertex_list[2], color, sn, segnum, hidden_flag, 0, no_fade );
  1082.             add_one_edge( vertex_list[2], vertex_list[3], color, sn, segnum, hidden_flag, 0, no_fade );
  1083.             add_one_edge( vertex_list[3], vertex_list[0], color, sn, segnum, hidden_flag, 0, no_fade );
  1084.  
  1085.             if ( is_grate )    {
  1086.                 add_one_edge( vertex_list[0], vertex_list[2], color, sn, segnum, hidden_flag, 1, no_fade );
  1087.                 add_one_edge( vertex_list[1], vertex_list[3], color, sn, segnum, hidden_flag, 1, no_fade );
  1088.             }
  1089.         }
  1090.     }
  1091.  
  1092. }
  1093.  
  1094.  
  1095. // Adds all the edges from a segment we haven't visited yet.
  1096.  
  1097. void add_unknown_segment_edges(segment *seg)
  1098. {
  1099.     int sn;
  1100.     int segnum = seg-Segments;
  1101.     
  1102.     for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++) {
  1103.         short    vertex_list[4];
  1104.  
  1105.         // Only add edges that have no children
  1106.         if (seg->children[sn] == -1) {
  1107.             get_side_verts(vertex_list,segnum,sn);
  1108.     
  1109.             add_one_unknown_edge( vertex_list[0], vertex_list[1] );
  1110.             add_one_unknown_edge( vertex_list[1], vertex_list[2] );
  1111.             add_one_unknown_edge( vertex_list[2], vertex_list[3] );
  1112.             add_one_unknown_edge( vertex_list[3], vertex_list[0] );
  1113.         }
  1114.  
  1115.  
  1116.     }
  1117.  
  1118. }
  1119.  
  1120. void automap_build_edge_list()
  1121. {    
  1122.     int    i,e1,e2,s;
  1123.     Edge_info * e;
  1124.  
  1125.     Automap_cheat = 0;
  1126.  
  1127.     if ( Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL_CHEAT )
  1128.         Automap_cheat = 1;        // Damn cheaters...
  1129.  
  1130.     // clear edge list
  1131.     for (i=0; i<Max_edges; i++) {
  1132.         Edges[i].num_faces = 0;
  1133.         Edges[i].flags = 0;
  1134.     }
  1135.     Num_edges = 0;
  1136.     Highest_edge_index = -1;
  1137.  
  1138.     if (Automap_cheat || (Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL) )    {
  1139.         // Cheating, add all edges as visited
  1140.         for (s=0; s<=Highest_segment_index; s++)
  1141.             #ifdef EDITOR
  1142.             if (Segments[s].segnum != -1)
  1143.             #endif
  1144.             {
  1145.                 add_segment_edges(&Segments[s]);
  1146.             }
  1147.     } else {
  1148.         // Not cheating, add visited edges, and then unvisited edges
  1149.         for (s=0; s<=Highest_segment_index; s++)
  1150.             #ifdef EDITOR
  1151.             if (Segments[s].segnum != -1)
  1152.             #endif
  1153.                 if (Automap_visited[s]) {
  1154.                     add_segment_edges(&Segments[s]);
  1155.                 }
  1156.     
  1157.         for (s=0; s<=Highest_segment_index; s++)
  1158.             #ifdef EDITOR
  1159.             if (Segments[s].segnum != -1)
  1160.             #endif
  1161.                 if (!Automap_visited[s]) {
  1162.                     add_unknown_segment_edges(&Segments[s]);
  1163.                 }
  1164.     }
  1165.  
  1166.     // Find unnecessary lines (These are lines that don't have to be drawn because they have small curvature)
  1167.     for (i=0; i<=Highest_edge_index; i++ )    {
  1168.         e = &Edges[i];
  1169.         if (!(e->flags&EF_USED)) continue;
  1170.  
  1171.         for (e1=0; e1<e->num_faces; e1++ )    {
  1172.             for (e2=1; e2<e->num_faces; e2++ )    {
  1173.                 if ( (e1 != e2) && (e->segnum[e1] != e->segnum[e2]) )    {
  1174.                     #ifdef COMPACT_SEGS
  1175.                     vms_vector v1, v2;
  1176.                     get_side_normal(&Segments[e->segnum[e1]], e->sides[e1], 0, &v1 );
  1177.                     get_side_normal(&Segments[e->segnum[e2]], e->sides[e2], 0, &v2 );
  1178.                     if ( vm_vec_dot(&v1,&v2) > (F1_0-(F1_0/10))  )    {
  1179.                     #else
  1180.                     if ( vm_vec_dot( &Segments[e->segnum[e1]].sides[e->sides[e1]].normals[0], &Segments[e->segnum[e2]].sides[e->sides[e2]].normals[0] ) > (F1_0-(F1_0/10))  )    {
  1181.                     #endif
  1182.                         e->flags &= (~EF_DEFINING);
  1183.                         break;
  1184.                     }
  1185.                 }
  1186.             }
  1187.             if (!(e->flags & EF_DEFINING))
  1188.                 break;
  1189.         }
  1190.     }    
  1191.  
  1192.     mprintf( (0, "Automap used %d / %d edges\n", Num_edges, Max_edges  ));
  1193.  
  1194. }
  1195. 
  1196.