CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

MAP.CPP (109350B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/MAP.CPP 3     3/14/97 5:15p Joe_b $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : MAP.CPP                                                      *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : September 10, 1993                                           *
     28  *                                                                                             *
     29  *                  Last Update : October 5, 1996 [JLB]                                        *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   MapClass::Base_Region -- Finds the owner and base zone for specified cell.                *
     34  *   MapClass::Cell_Region -- Determines the region from a specified cell number.              *
     35  *   MapClass::Cell_Threat -- Gets a houses threat value for a cell                            *
     36  *   MapClass::Close_Object -- Finds a clickable close object to the specified coordinate.     *
     37  *   MapClass::Destroy_Bridge_At -- Destroyes the bridge at location specified.                *
     38  *   MapClass::Detach -- Remove specified object from map references.                          *
     39  *   MapClass::In_Radar -- Is specified cell in the radar map?                                 *
     40  *   MapClass::Init -- clears all cells                                                        *
     41  *   MapClass::Intact_Bridge_Count -- Determine the number of intact bridges.                  *
     42  *   MapClass::Logic -- Handles map related logic functions.                                   *
     43  *   MapClass::Nearby_Location -- Finds a generally clear location near a specified cell.      *
     44  *   MapClass::One_Time -- Performs special one time initializations for the map.              *
     45  *   MapClass::Overlap_Down -- computes & marks object's overlap cells                         *
     46  *   MapClass::Overlap_Up -- Computes & clears object's overlap cells                          *
     47  *   MapClass::Overpass -- Performs any final cleanup to a freshly constructed map.            *
     48  *   MapClass::Pick_Up -- Removes specified object from the map.                               *
     49  *   MapClass::Place_Down -- Places the specified object onto the map.                         *
     50  *   MapClass::Place_Random_Crate -- Places a crate at random location on map.                 *
     51  *   MapClass::Read_Binary -- Reads the binary data from the straw specified.                  *
     52  *   MapClass::Remove_Crate -- Remove a crate from the specified cell.                         *
     53  *   MapClass::Set_Map_Dimensions -- Initialize the map.                                       *
     54  *   MapClass::Sight_From -- Mark as visible the cells within a specified radius.              *
     55  *   MapClass::Validate -- validates every cell on the map                                     *
     56  *   MapClass::Write_Binary -- Pipes the map template data to the destination specified.       *
     57  *   MapClass::Zone_Reset -- Resets all zone numbers to match the map.                         *
     58  *   MapClass::Zone_Span -- Flood fills the specified zone from the cell origin.               *
     59  *   MapClass::Pick_Random_Location -- Picks a random location on the map.                     *
     60  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     61 
     62 #include "function.h"
     63 
     64 #define	MCW	MAP_CELL_W
     65 int const MapClass::RadiusOffset[] = {
     66 	/* 0  */	0,
     67 	/* 1  */	(-MCW*1)-1,(-MCW*1)+0,(-MCW*1)+1,-1,1,(MCW*1)-1,(MCW*1)+0,(MCW*1)+1,
     68 	/* 2  */	(-MCW*2)-1,(-MCW*2)+0,(-MCW*2)+1,(-MCW*1)-2,(-MCW*1)+2,-2,2,(MCW*1)-2,(MCW*1)+2,(MCW*2)-1,(MCW*2)+0,(MCW*2)+1,
     69 	/* 3  */	(-MCW*3)-1,(-MCW*3)+0,(-MCW*3)+1,(-MCW*2)-2,(-MCW*2)+2,(-MCW*1)-3,(-MCW*1)+3,-3,3,(MCW*1)-3,(MCW*1)+3,(MCW*2)-2,(MCW*2)+2,(MCW*3)-1,(MCW*3)+0,(MCW*3)+1,
     70 	/* 4  */	(-MCW*4)-1,(-MCW*4)+0,(-MCW*4)+1,(-MCW*3)-3,(-MCW*3)-2,(-MCW*3)+2,(-MCW*3)+3,(-MCW*2)-3,(-MCW*2)+3,(-MCW*1)-4,(-MCW*1)+4,-4,4,(MCW*1)-4,(MCW*1)+4,(MCW*2)-3,(MCW*2)+3,(MCW*3)-3,(MCW*3)-2,(MCW*3)+2,(MCW*3)+3,(MCW*4)-1,(MCW*4)+0,(MCW*4)+1,
     71 	/* 5  */	(-MCW*5)-1,(-MCW*5)+0,(-MCW*5)+1,(-MCW*4)-3,(-MCW*4)-2,(-MCW*4)+2,(-MCW*4)+3,(-MCW*3)-4,(-MCW*3)+4,(-MCW*2)-4,(-MCW*2)+4,(-MCW*1)-5,(-MCW*1)+5,-5,5,(MCW*1)-5,(MCW*1)+5,(MCW*2)-4,(MCW*2)+4,(MCW*3)-4,(MCW*3)+4,(MCW*4)-3,(MCW*4)-2,(MCW*4)+2,(MCW*4)+3,(MCW*5)-1,(MCW*5)+0,(MCW*5)+1,
     72 	/* 6  */	(-MCW*6)-1,(-MCW*6)+0,(-MCW*6)+1,(-MCW*5)-3,(-MCW*5)-2,(-MCW*5)+2,(-MCW*5)+3,(-MCW*4)-4,(-MCW*4)+4,(-MCW*3)-5,(-MCW*3)+5,(-MCW*2)-5,(-MCW*2)+5,(-MCW*1)-6,(-MCW*1)+6,-6,6,(MCW*1)-6,(MCW*1)+6,(MCW*2)-5,(MCW*2)+5,(MCW*3)-5,(MCW*3)+5,(MCW*4)-4,(MCW*4)+4,(MCW*5)-3,(MCW*5)-2,(MCW*5)+2,(MCW*5)+3,(MCW*6)-1,(MCW*6)+0,(MCW*6)+1,
     73 	/* 7  */	(-MCW*7)-1,(-MCW*7)+0,(-MCW*7)+1,(-MCW*6)-3,(-MCW*6)-2,(-MCW*6)+2,(-MCW*6)+3,(-MCW*5)-5,(-MCW*5)-4,(-MCW*5)+4,(-MCW*5)+5,(-MCW*4)-5,(-MCW*4)+5,(-MCW*3)-6,(-MCW*3)+6,(-MCW*2)-6,(-MCW*2)+6,(-MCW*1)-7,(-MCW*1)+7,-7,7,(MCW*1)-7,(MCW*1)+7,(MCW*2)-6,(MCW*2)+6,(MCW*3)-6,(MCW*3)+6,(MCW*4)-5,(MCW*4)+5,(MCW*5)-5,(MCW*5)-4,(MCW*5)+4,(MCW*5)+5,(MCW*6)-3,(MCW*6)-2,(MCW*6)+2,(MCW*6)+3,(MCW*7)-1,(MCW*7)+0,(MCW*7)+1,
     74 	/* 8  */	(-MCW*8)-1,(-MCW*8)+0,(-MCW*8)+1,(-MCW*7)-3,(-MCW*7)-2,(-MCW*7)+2,(-MCW*7)+3,(-MCW*6)-5,(-MCW*6)-4,(-MCW*6)+4,(-MCW*6)+5,(-MCW*5)-6,(-MCW*5)+6,(-MCW*4)-6,(-MCW*4)+6,(-MCW*3)-7,(-MCW*3)+7,(-MCW*2)-7,(-MCW*2)+7,(-MCW*1)-8,(-MCW*1)+8,-8,8,(MCW*1)-8,(MCW*1)+8,(MCW*2)-7,(MCW*2)+7,(MCW*3)-7,(MCW*3)+7,(MCW*4)-6,(MCW*4)+6,(MCW*5)-6,(MCW*5)+6,(MCW*6)-5,(MCW*6)-4,(MCW*6)+4,(MCW*6)+5,(MCW*7)-3,(MCW*7)-2,(MCW*7)+2,(MCW*7)+3,(MCW*8)-1,(MCW*8)+0,(MCW*8)+1,
     75 	/* 9  */	(-MCW*9)-1,(-MCW*9)+0,(-MCW*9)+1,(-MCW*8)-3,(-MCW*8)-2,(-MCW*8)+2,(-MCW*8)+3,(-MCW*7)-5,(-MCW*7)-4,(-MCW*7)+4,(-MCW*7)+5,(-MCW*6)-6,(-MCW*6)+6,(-MCW*5)-7,(-MCW*5)+7,(-MCW*4)-7,(-MCW*4)+7,(-MCW*3)-8,(-MCW*3)+8,(-MCW*2)-8,(-MCW*2)+8,(-MCW*1)-9,(-MCW*1)+9,-9,9,(MCW*1)-9,(MCW*1)+9,(MCW*2)-8,(MCW*2)+8,(MCW*3)-8,(MCW*3)+8,(MCW*4)-7,(MCW*4)+7,(MCW*5)-7,(MCW*5)+7,(MCW*6)-6,(MCW*6)+6,(MCW*7)-5,(MCW*7)-4,(MCW*7)+4,(MCW*7)+5,(MCW*8)-3,(MCW*8)-2,(MCW*8)+2,(MCW*8)+3,(MCW*9)-1,(MCW*9)+0,(MCW*9)+1,
     76 	/* 10 */	(-MCW*10)-1,(-MCW*10)+0,(-MCW*10)+1,(-MCW*9)-3,(-MCW*9)-2,(-MCW*9)+2,(-MCW*9)+3,(-MCW*8)-5,(-MCW*8)-4,(-MCW*8)+4,(-MCW*8)+5,(-MCW*7)-7,(-MCW*7)-6,(-MCW*7)+6,(-MCW*7)+7,(-MCW*6)-7,(-MCW*6)+7,(-MCW*5)-8,(-MCW*5)+8,(-MCW*4)-8,(-MCW*4)+8,(-MCW*3)-9,(-MCW*3)+9,(-MCW*2)-9,(-MCW*2)+9,(-MCW*1)-10,(-MCW*1)+10,-10,10,(MCW*1)-10,(MCW*1)+10,(MCW*2)-9,(MCW*2)+9,(MCW*3)-9,(MCW*3)+9,(MCW*4)-8,(MCW*4)+8,(MCW*5)-8,(MCW*5)+8,(MCW*6)-7,(MCW*6)+7,(MCW*7)-7,(MCW*7)-6,(MCW*7)+6,(MCW*7)+7,(MCW*8)-5,(MCW*8)-4,
     77 			(MCW*8)+4,(MCW*8)+5,(MCW*9)-3,(MCW*9)-2,(MCW*9)+2,(MCW*9)+3,(MCW*10)-1,(MCW*10)+0,(MCW*10)+1,
     78 };
     79 
     80 int const MapClass::RadiusCount[11] = {1,9,21,37,61,89,121,161,205,253,309};
     81 
     82 
     83 CellClass * BlubCell;
     84 
     85 /***********************************************************************************************
     86  * MapClass::One_Time -- Performs special one time initializations for the map.                *
     87  *                                                                                             *
     88  *    This routine is used by the game initialization function in order to perform any one     *
     89  *    time initializations required for the map. This includes allocation of the map and       *
     90  *    setting up its default dimensions.                                                       *
     91  *                                                                                             *
     92  * INPUT:   none                                                                               *
     93  *                                                                                             *
     94  * OUTPUT:  none                                                                               *
     95  *                                                                                             *
     96  * WARNINGS:   This routine MUST be called once and only once.                                 *
     97  *                                                                                             *
     98  * HISTORY:                                                                                    *
     99  *   05/31/1994 JLB : Created.                                                                 *
    100  *   12/01/1994 BR : Added CellTriggers initialization                                         *
    101  *=============================================================================================*/
    102 void MapClass::One_Time(void)
    103 {
    104 	GScreenClass::One_Time();
    105 
    106 	XSize = MAP_CELL_W;
    107 	YSize = MAP_CELL_H;
    108 	Size = XSize * YSize;
    109 
    110 	/*
    111 	**	Allocate the cell array.
    112 	*/
    113 	Alloc_Cells();
    114 }
    115 
    116 
    117 /***********************************************************************************************
    118  * MapClass::Init_Clear -- clears the map & buffers to a known state                           *
    119  *                                                                                             *
    120  * INPUT:                                                                                      *
    121  *      none.                                                                                  *
    122  *                                                                                             *
    123  * OUTPUT:                                                                                     *
    124  *      none.                                                                                  *
    125  *                                                                                             *
    126  * WARNINGS:                                                                                   *
    127  *      none.                                                                                  *
    128  *                                                                                             *
    129  * HISTORY:                                                                                    *
    130  *   03/17/1995 BRR : Created.                                                                 *
    131  *=============================================================================================*/
    132 void MapClass::Init_Clear(void)
    133 {
    134 	GScreenClass::Init_Clear();
    135 	Init_Cells();
    136 	TiberiumScan = 0;
    137 	TiberiumGrowthCount = 0;
    138 	TiberiumGrowthExcess = 0;
    139 	TiberiumSpreadCount = 0;
    140 	TiberiumSpreadExcess = 0;
    141 	for (int index = 0; index < ARRAY_SIZE(Crates); index++) {
    142 		Crates[index].Init();
    143 	}
    144 }
    145 
    146 
    147 /***********************************************************************************************
    148  * MapClass::Alloc_Cells -- allocates the cell array                                           *
    149  *                                                                                             *
    150  * This routine should be called at One_Time, and after loading the Map object from a save     *
    151  * game, but prior to loading the cell objects.                                                *
    152  *                                                                                             *
    153  * INPUT:                                                                                      *
    154  *      none.                                                                                  *
    155  *                                                                                             *
    156  * OUTPUT:                                                                                     *
    157  *      none.                                                                                  *
    158  *                                                                                             *
    159  * WARNINGS:                                                                                   *
    160  *      none.                                                                                  *
    161  *                                                                                             *
    162  * HISTORY:                                                                                    *
    163  *   03/17/1995 BRR : Created.                                                                 *
    164  *=============================================================================================*/
    165 void MapClass::Alloc_Cells(void)
    166 {
    167 	/*
    168 	**	Assume that whatever the contents of the VectorClass are is garbage
    169 	**	(it may have been loaded from a save-game file), so zero it out first.
    170 	*/
    171 	new (&Array) VectorClass<CellClass>;
    172 	Array.Resize(Size);
    173 }
    174 
    175 
    176 /***********************************************************************************************
    177  * MapClass::Free_Cells -- frees the cell array                                                *
    178  *                                                                                             *
    179  * This routine is used by the Load_Game routine to free the map's cell array before loading   *
    180  * the map object from disk; the array is then re-allocated & cleared before the cell objects  *
    181  * are loaded.                                                                                 *
    182  *                                                                                             *
    183  * INPUT:                                                                                      *
    184  *      none.                                                                                  *
    185  *                                                                                             *
    186  * OUTPUT:                                                                                     *
    187  *      none.                                                                                  *
    188  *                                                                                             *
    189  * WARNINGS:                                                                                   *
    190  *      none.                                                                                  *
    191  *                                                                                             *
    192  * HISTORY:                                                                                    *
    193  *   03/17/1995 BRR : Created.                                                                 *
    194  *=============================================================================================*/
    195 void MapClass::Free_Cells(void)
    196 {
    197 	Array.Clear();
    198 }
    199 
    200 
    201 /***********************************************************************************************
    202  * MapClass::Init_Cells -- Initializes the cell array to a fresh state.                        *
    203  *                                                                                             *
    204  * This routine is used by Init_Clear to set the cells to a known state; it's also used by     *
    205  * the Load_Game routine to init all cells before loading a set of cells from disk, so it      *
    206  * needs to be called separately from the other Init_xxx() routines.                           *
    207  *                                                                                             *
    208  * INPUT:                                                                                      *
    209  *      none.                                                                                  *
    210  *                                                                                             *
    211  * OUTPUT:                                                                                     *
    212  *      none.                                                                                  *
    213  *                                                                                             *
    214  * WARNINGS:                                                                                   *
    215  *      none.                                                                                  *
    216  *                                                                                             *
    217  * HISTORY:                                                                                    *
    218  *   03/17/1995 BRR : Created.                                                                 *
    219  *=============================================================================================*/
    220 void MapClass::Init_Cells(void)
    221 {
    222 	TotalValue = 0;
    223 	for (int index = 0; index < MAP_CELL_TOTAL; index++) {
    224 		new (&Array[index]) CellClass;
    225 	}
    226 }
    227 
    228 
    229 /***********************************************************************************************
    230  * MapClass::Set_Map_Dimensions -- Set map dimensions.                                         *
    231  *                                                                                             *
    232  *    This routine is used to set the legal limits and position of the                         *
    233  *    map as it relates to the overall map array. Typically, this is                           *
    234  *    called by the scenario loading code.                                                     *
    235  *                                                                                             *
    236  * INPUT:   x,y   -- The X and Y coordinate of the "upper left" corner                         *
    237  *                   of the map.                                                               *
    238  *                                                                                             *
    239  *          w,h   -- The width and height of the legal map.                                    *
    240  *                                                                                             *
    241  * OUTPUT:  none                                                                               *
    242  *                                                                                             *
    243  * WARNINGS:   none                                                                            *
    244  *                                                                                             *
    245  * HISTORY:                                                                                    *
    246  *   05/14/1994 JLB : Created.                                                                 *
    247  *=============================================================================================*/
    248 void MapClass::Set_Map_Dimensions(int x, int y, int w, int h)
    249 {
    250 	MapCellX = x;
    251 	MapCellY = y;
    252 	MapCellWidth = w;
    253 	MapCellHeight = h;
    254 }
    255 
    256 
    257 /***********************************************************************************************
    258  * MapClass::Sight_From -- Mark as visible the cells within a specified radius.                *
    259  *                                                                                             *
    260  *    This routine is used to reveal the cells around a specific location.                     *
    261  *    Typically, as a unit moves or is deployed, this routine will be                          *
    262  *    called. Since it deals with MANY cells, it needs to be extremely                         *
    263  *    fast.                                                                                    *
    264  *                                                                                             *
    265  * INPUT:   cell     -- The coordinate that the sighting originates from.                      *
    266  *                                                                                             *
    267  *          sightrange-- The distance in cells that sighting extends.                          *
    268  *                                                                                             *
    269  *          incremental-- Is this an incremental sighting. In other                            *
    270  *                      words, has this function been called before where                      *
    271  *                      the center coordinate is no more than one cell                         *
    272  *                      distant from the last time?                                            *
    273  *                                                                                             *
    274  * OUTPUT:  none                                                                               *
    275  *                                                                                             *
    276  * WARNINGS:   none                                                                            *
    277  *                                                                                             *
    278  * HISTORY:                                                                                    *
    279  *   05/19/1992 JLB : Created.                                                                 *
    280  *   03/08/1994 JLB : Updated to use sight table and incremental flag.                         *
    281  *   05/18/1994 JLB : Converted to member function.                                            *
    282  *=============================================================================================*/
    283 void MapClass::Sight_From(CELL cell, int sightrange, HouseClass * house, bool incremental)
    284 {
    285 	int xx;				// Center cell X coordinate (bounds checking).
    286 	int const * ptr;	// Offset pointer.
    287 	int count;			// Counter for number of offsets to process.
    288 
    289 	/*
    290 	**	Units that are off-map cannot sight.
    291 	*/
    292 	if (!In_Radar(cell)) return;
    293 	if (!sightrange || sightrange > 10) return;
    294 
    295 	/*
    296 	**	Determine logical cell coordinate for center scan point.
    297 	*/
    298 	xx = Cell_X(cell);
    299 
    300 	/*
    301 	**	Incremental scans only scan the outer rings. Full scans
    302 	**	scan all internal cells as well.
    303 	*/
    304 	count = RadiusCount[sightrange];
    305 	ptr = &RadiusOffset[0];
    306 	if (incremental) {
    307 		if (sightrange > 2) {
    308 			ptr += RadiusCount[sightrange-3];
    309 			count -= RadiusCount[sightrange-3];
    310 		}
    311 	}
    312 
    313 	/*
    314 	**	Process all offsets required for the desired scan.
    315 	*/
    316 	while (count--) {
    317 		CELL	newcell;			// New cell with offset.
    318 		int	xdiff;			// New cell's X coordinate distance from center.
    319 
    320 		newcell = cell + *ptr++;
    321 
    322 		/*
    323 		**	Determine if the map edge has been wrapped. If so,
    324 		**	then don't process the cell.
    325 		*/
    326 		if ((unsigned)newcell >= MAP_CELL_TOTAL) continue;
    327 		xdiff = Cell_X(newcell) - xx;
    328 		xdiff = ABS(xdiff);
    329 		if (xdiff > sightrange) continue;
    330 		if (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (sightrange * CELL_LEPTON_W)) continue;
    331 
    332 		/*
    333 		**	Map the cell. For incremental scans, then update
    334 		**	adjacent cells as well. For full scans, just update
    335 		**	the cell itself.
    336 		*/
    337 		//if (!(*this)[newcell].IsMapped) {  // ST - 8/7/2019 10:31AM		
    338 		Map.Map_Cell(newcell, house, true, true);
    339 	}
    340 }
    341 
    342 
    343 /***********************************************************************************************
    344  * MapClass::Shroud_From -- cloak a radius of cells														  *
    345  *                                                                                             *
    346  *    This routine is used to shroud the cells around a specific location.                     *
    347  *    Typically, as a gap generator refreshes (when Encroach_Shadow() is called) this routine's*
    348  *    called. Since it deals with MANY cells, it needs to be extremely                         *
    349  *    fast.                                                                                    *
    350  *                                                                                             *
    351  * INPUT:   cell     -- The coordinate that the shrouding originates from.                     *
    352  *                                                                                             *
    353  *          sightrange-- The distance in cells that sighting extends.                          *
    354  *                                                                                             *
    355  * OUTPUT:  none                                                                               *
    356  *                                                                                             *
    357  * WARNINGS:   none                                                                            *
    358  *                                                                                             *
    359  * HISTORY:                                                                                    *
    360  *   11/10/1995 BWG : Created.                                                                 *
    361  *   08/09/2019  ST : Added house parameter                                                    *
    362  *=============================================================================================*/
    363 void MapClass::Shroud_From(CELL cell, int sightrange, HouseClass *house)
    364 {
    365 	int xx;				// Center cell X coordinate (bounds checking).
    366 	int const * ptr;	// Offset pointer.
    367 	int count;			// Counter for number of offsets to process.
    368 
    369 	/*
    370 	**	Units that are off-map cannot sight.
    371 	*/
    372 	if (!In_Radar(cell)) return;
    373 	if (!sightrange || sightrange > Rule.GapShroudRadius) return;
    374 
    375 	/*
    376 	**	Determine logical cell coordinate for center scan point.
    377 	*/
    378 	xx = Cell_X(cell);
    379 
    380 	/*
    381 	**	Incremental scans only scan the outer rings. Full scans
    382 	**	scan all internal cells as well.
    383 	*/
    384 	count = RadiusCount[sightrange];
    385 	ptr = &RadiusOffset[0];
    386 
    387 	/*
    388 	**	Process all offsets required for the desired scan.
    389 	*/
    390 	while (count--) {
    391 		CELL	newcell;			// New cell with offset.
    392 		int	xdiff;			// New cell's X coordinate distance from center.
    393 
    394 		newcell = cell + *ptr++;
    395 
    396 		/*
    397 		**	Determine if the map edge has been wrapped. If so,
    398 		**	then don't process the cell.
    399 		*/
    400 		if ((unsigned)newcell >= MAP_CELL_TOTAL) continue;
    401 		xdiff = Cell_X(newcell) - xx;
    402 		xdiff = ABS(xdiff);
    403 		if (xdiff > sightrange) continue;
    404 		if (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (sightrange * CELL_LEPTON_W)) continue;
    405 
    406 		/*
    407 		**	Shroud the cell.
    408 		*/
    409 		Map.Shroud_Cell(newcell, house);
    410 	}
    411 }
    412 
    413 
    414 /***********************************************************************************************
    415  * MapClass::Jam_From -- Mark as jammed the cells within a specified radius.                   *
    416  *                                                                                             *
    417  *    This routine is used to jam the cells around a specific location.                        *
    418  *    Typically, as a gap generator structure is created, this routine will be                 *
    419  *    called. Since it deals with MANY cells, it needs to be extremely                         *
    420  *    fast.                                                                                    *
    421  *                                                                                             *
    422  * INPUT:   cell     -- The coordinate that the jamming originates from.                       *
    423  *                                                                                             *
    424  *          jamrange -- The distance in cells that jamming extends.                            *
    425  *                                                                                             *
    426  *                                                                                             *
    427  * OUTPUT:  none                                                                               *
    428  *                                                                                             *
    429  * WARNINGS:   none                                                                            *
    430  *                                                                                             *
    431  * HISTORY:                                                                                    *
    432  *   11/09/1995 BWG : Created.                                                                 *
    433  *=============================================================================================*/
    434 void MapClass::Jam_From(CELL cell, int jamrange, HouseClass * house)
    435 {
    436 	int xx;				// Center cell X coordinate (bounds checking).
    437 	int const * ptr;	// Offset pointer.
    438 	int count;			// Counter for number of offsets to process.
    439 
    440 	/*
    441 	**	Units that are off-map cannot jam.
    442 	*/
    443 	if (!jamrange || jamrange > Rule.GapShroudRadius) return;
    444 
    445 	/*
    446 	**	Determine logical cell coordinate for center scan point.
    447 	*/
    448 	xx = Cell_X(cell);
    449 
    450 	/*
    451 	**	Incremental scans only scan the outer rings. Full scans
    452 	**	scan all internal cells as well.
    453 	*/
    454 	count = RadiusCount[jamrange];
    455 	ptr = &RadiusOffset[0];
    456 
    457 	/*
    458 	**	Process all offsets required for the desired scan.
    459 	*/
    460 	while (count--) {
    461 		CELL	newcell;			// New cell with offset.
    462 		int	xdiff;			// New cell's X coordinate distance from center.
    463 
    464 		newcell = cell + *ptr++;
    465 
    466 		/*
    467 		**	Determine if the map edge has been wrapped. If so,
    468 		**	then don't process the cell.
    469 		*/
    470 		if ((unsigned)newcell >= MAP_CELL_TOTAL) continue;
    471 		xdiff = Cell_X(newcell) - xx;
    472 		xdiff = ABS(xdiff);
    473 		if (xdiff > jamrange) continue;
    474 		if (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (jamrange * CELL_LEPTON_W)) continue;
    475 
    476 		/*
    477 		**	Jam the cell. For incremental scans, then update
    478 		**	adjacent cells as well. For full scans, just update
    479 		**	the cell itself.
    480 		*/
    481 		Map.Jam_Cell(newcell, house/*KO, false*/);
    482 	}
    483 
    484 	/*
    485 	** Updated for client/server multiplayer. ST - 8/12/2019 3:25PM
    486 	*/
    487 	if (Session.Type != GAME_GLYPHX_MULTIPLAYER) {
    488 		if (!house->IsPlayerControl) {
    489 			Map.Constrained_Look(Cell_Coord(cell), Rule.GapShroudRadius * CELL_LEPTON_W, PlayerPtr);
    490 		}
    491 		
    492 	} else {
    493 		
    494 		for (int i = 0; i < Session.Players.Count(); i++) {
    495 			HouseClass *player_house = HouseClass::As_Pointer(Session.Players[i]->Player.ID);
    496 			if (player_house->IsHuman && player_house != house) {
    497 				Map.Constrained_Look(Cell_Coord(cell), Rule.GapShroudRadius * CELL_LEPTON_W, player_house);
    498 			}
    499 		}
    500 	}
    501 
    502 #ifdef OBSOLETE
    503 	/*
    504 	**	The objects on the map need to perform a manual look operation if they happen
    505 	**	to have their sight range overlap the gap radius.
    506 	*/
    507 	if (!house->IsPlayerControl) {
    508 //	if (house != PlayerPtr) {
    509 
    510 		for (int index = 0; index < Map.Layer[LAYER_GROUND].Count(); index++) {
    511 			ObjectClass * object = Map.Layer[LAYER_GROUND][index];
    512 			if (object && object->Is_Techno()) {
    513 				TechnoClass * tech = ((TechnoClass *)object);
    514 
    515 				if (tech->IsDiscoveredByPlayer &&
    516 					(tech->Distance(As_Target(cell)) / CELL_LEPTON_W) <= tech->Techno_Type_Class()->SightRange + Rule.GapShroudRadius &&
    517 					(tech->House->IsPlayerControl ||
    518 					(tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(PlayerPtr)))) {
    519 
    520 					object->Look();
    521 				}
    522 			}
    523 		}
    524 	}
    525 #endif
    526 
    527 #ifdef OBSOLETE
    528 		/*
    529 		** Here all the player's vehicles will perform a look if they're within
    530 		** the shadow.
    531 		*/
    532 		for (int index = 0; index < Units.Count(); index++) {
    533 			UnitClass * unit = Units.Ptr(index);
    534 			if (unit && !unit->IsInLimbo && unit->House == PlayerPtr) {
    535 				int dist = (unit->Distance(As_Target(cell))) / CELL_LEPTON_W;
    536 				if (dist <= unit->Class->SightRange + Rule.GapShroudRadius /*gap generator sightrange*/) {
    537 					unit->Look();
    538 				}
    539 			}
    540 		}
    541 		for (index = 0; index < Infantry.Count(); index++) {
    542 			InfantryClass * unit = Infantry.Ptr(index);
    543 			if (unit && !unit->IsInLimbo && unit->House == PlayerPtr) {
    544 				int dist = (unit->Distance(As_Target(cell))) / CELL_LEPTON_W;
    545 				if (dist <= unit->Class->SightRange + Rule.GapShroudRadius /*gap generator sightrange*/) {
    546 					unit->Look();
    547 				}
    548 			}
    549 		}
    550 		for (index = 0; index < Vessels.Count(); index++) {
    551 			VesselClass * unit = Vessels.Ptr(index);
    552 			if (unit && !unit->IsInLimbo && unit->House == PlayerPtr) {
    553 				int dist = (unit->Distance(As_Target(cell))) / CELL_LEPTON_W;
    554 				if (dist <= unit->Class->SightRange + Rule.GapShroudRadius /*gap generator sightrange*/) {
    555 					unit->Look();
    556 				}
    557 			}
    558 		}
    559 	}
    560 #endif
    561 
    562 }
    563 
    564 
    565 /***********************************************************************************************
    566  * MapClass::UnJam_From -- Remove jamming on the cells within a specified radius.              *
    567  *                                                                                             *
    568  *    This routine is used to jam the cells around a specific location.                        *
    569  *    Typically, as a gap generator structure is created, this routine will be                 *
    570  *    called. Since it deals with MANY cells, it needs to be extremely                         *
    571  *    fast.                                                                                    *
    572  *                                                                                             *
    573  * INPUT:   cell     -- The coordinate that the jamming originates from.                       *
    574  *                                                                                             *
    575  *          jamrange -- The distance in cells that jamming extends.                            *
    576  *                                                                                             *
    577  * OUTPUT:  none                                                                               *
    578  *                                                                                             *
    579  * WARNINGS:   none                                                                            *
    580  *                                                                                             *
    581  * HISTORY:                                                                                    *
    582  *   11/09/1995 BWG : Created.                                                                 *
    583  *=============================================================================================*/
    584 void MapClass::UnJam_From(CELL cell, int jamrange, HouseClass * house)
    585 {
    586 	int xx;				// Center cell X coordinate (bounds checking).
    587 	int const * ptr;	// Offset pointer.
    588 	int count;			// Counter for number of offsets to process.
    589 
    590 	/*
    591 	**	Units that are off-map cannot jam.
    592 	*/
    593 	if (!jamrange || jamrange > Rule.GapShroudRadius) return;
    594 
    595 	/*
    596 	**	Determine logical cell coordinate for center scan point.
    597 	*/
    598 	xx = Cell_X(cell);
    599 
    600 	/*
    601 	**	Incremental scans only scan the outer rings. Full scans
    602 	**	scan all internal cells as well.
    603 	*/
    604 	count = RadiusCount[jamrange];
    605 	ptr = &RadiusOffset[0];
    606 
    607 	/*
    608 	**	Process all offsets required for the desired scan.
    609 	*/
    610 	while (count--) {
    611 		CELL	newcell;			// New cell with offset.
    612 		int	xdiff;			// New cell's X coordinate distance from center.
    613 
    614 		newcell = cell + *ptr++;
    615 
    616 		/*
    617 		**	Determine if the map edge has been wrapped. If so,
    618 		**	then don't process the cell.
    619 		*/
    620 		if ((unsigned)newcell >= MAP_CELL_TOTAL) continue;
    621 		xdiff = Cell_X(newcell) - xx;
    622 		xdiff = ABS(xdiff);
    623 		if (xdiff > jamrange) continue;
    624 		if (Distance(Cell_Coord(newcell), Cell_Coord(cell)) > (jamrange * CELL_LEPTON_W)) continue;
    625 
    626 		/*
    627 		**	Jam the cell. For incremental scans, then update
    628 		**	adjacent cells as well. For full scans, just update
    629 		**	the cell itself.
    630 		*/
    631 		Map.UnJam_Cell(newcell, house);
    632 	}
    633 }
    634 
    635 
    636 /***********************************************************************************************
    637  * MapClass::In_Radar -- Is specified cell in the radar map?                                   *
    638  *                                                                                             *
    639  *    This determines if the specified cell can be within the navigable                        *
    640  *    bounds of the map. Technically, this means, any cell that can be                         *
    641  *    scanned by radar. If a cell returns false from this function, then                       *
    642  *    the player could never move to or pass over this cell.                                   *
    643  *                                                                                             *
    644  * INPUT:   cell  -- The cell to examine.                                                      *
    645  *                                                                                             *
    646  * OUTPUT:  bool; Is this cell possible to be displayed on radar?                              *
    647  *                                                                                             *
    648  * WARNINGS:   none                                                                            *
    649  *                                                                                             *
    650  * HISTORY:                                                                                    *
    651  *   10/07/1992 JLB : Created.                                                                 *
    652  *   04/30/1994 JLB : Converted to member function.                                            *
    653  *   05/01/1994 JLB : Speeded up.                                                              *
    654  *=============================================================================================*/
    655 bool MapClass::In_Radar(CELL cell) const
    656 {
    657 	/*
    658 	**	If the cell value is WAY out of range, then it obviously can't be part of the game
    659 	**	playfield.
    660 	*/
    661 	if ((unsigned)cell > MAP_CELL_TOTAL) return(false);
    662 
    663 	/*
    664 	**	If the cell is off the left or right edge of the playfield, then return the "not in
    665 	**	radar" flag.
    666 	*/
    667 	if ((unsigned)(Cell_X(cell) - MapCellX) >= (unsigned)MapCellWidth) return(false);
    668 
    669 	/*
    670 	**	If the cell is off the top or bottom edge of the playfield, then return the "not in
    671 	**	radar" flag.
    672 	*/
    673 	if ((unsigned)(Cell_Y(cell) - MapCellY) >= (unsigned)MapCellHeight) return(false);
    674 
    675 	return(true);
    676 }
    677 
    678 
    679 /***********************************************************************************************
    680  * MapClass::Place_Down -- Places the specified object onto the map.                           *
    681  *                                                                                             *
    682  *    This routine is used to place an object onto the map. It updates the "occupier" of the   *
    683  *    cells that this object covers. The cells are determined from the Occupy_List function    *
    684  *    provided by the object. Only one cell can have an occupier and this routine is the only  *
    685  *    place that sets this condition.                                                          *
    686  *                                                                                             *
    687  * INPUT:   cell     -- The cell to base object occupation around.                             *
    688  *                                                                                             *
    689  *          object   -- The object to place onto the map.                                      *
    690  *                                                                                             *
    691  * OUTPUT:  none                                                                               *
    692  *                                                                                             *
    693  * WARNINGS:   none                                                                            *
    694  *                                                                                             *
    695  * HISTORY:                                                                                    *
    696  *   07/31/1994 JLB : Created.                                                                 *
    697  *=============================================================================================*/
    698 void MapClass::Place_Down(CELL cell, ObjectClass * object)
    699 {
    700 	if (!object) return;
    701 
    702 	if (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {
    703 		short xlist[32];
    704 		List_Copy(object->Occupy_List(), ARRAY_SIZE(xlist), xlist);
    705 		short const * list = xlist;
    706 		while (*list != REFRESH_EOL) {
    707 			CELL newcell = cell + *list++;
    708 			if ((unsigned)newcell < MAP_CELL_TOTAL) {
    709 				(*this)[newcell].Occupy_Down(object);
    710 				(*this)[newcell].Recalc_Attributes();
    711 				(*this)[newcell].Redraw_Objects();
    712 			}
    713 		}
    714 
    715 		List_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);
    716 		list = xlist;
    717 		while (*list != REFRESH_EOL) {
    718 			CELL newcell = cell + *list++;
    719 			if ((unsigned)newcell < MAP_CELL_TOTAL) {
    720 				(*this)[newcell].Overlap_Down(object);
    721 				(*this)[newcell].Redraw_Objects();
    722 			}
    723 		}
    724 	}
    725 }
    726 
    727 
    728 /***********************************************************************************************
    729  * MapClass::Pick_Up -- Removes specified object from the map.                                 *
    730  *                                                                                             *
    731  *    The object specified is removed from the map by this routine. This will remove the       *
    732  *    occupation flag for all the cells that the object covers. The cells that are covered     *
    733  *    are determined from the Occupy_List function.                                            *
    734  *                                                                                             *
    735  * INPUT:   cell     -- The cell that the object is centered about.                            *
    736  *                                                                                             *
    737  *          object   -- Pointer to the object that will be removed.                            *
    738  *                                                                                             *
    739  * OUTPUT:  none                                                                               *
    740  *                                                                                             *
    741  * WARNINGS:   none                                                                            *
    742  *                                                                                             *
    743  * HISTORY:                                                                                    *
    744  *   07/31/1994 JLB : Created.                                                                 *
    745  *=============================================================================================*/
    746 void MapClass::Pick_Up(CELL cell, ObjectClass * object)
    747 {
    748 	if (!object) return;
    749 
    750 	if (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {
    751 		short xlist[32];
    752 		List_Copy(object->Occupy_List(), ARRAY_SIZE(xlist), xlist);
    753 		short const * list = xlist;
    754 		while (*list != REFRESH_EOL) {
    755 			CELL newcell = cell + *list++;
    756 			if ((unsigned)newcell < MAP_CELL_TOTAL) {
    757 				(*this)[newcell].Occupy_Up(object);
    758 				(*this)[newcell].Recalc_Attributes();
    759 				(*this)[newcell].Redraw_Objects();
    760 			}
    761 		}
    762 
    763 		List_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);
    764 		list = xlist;
    765 		while (*list != REFRESH_EOL) {
    766 			CELL newcell = cell + *list++;
    767 			if ((unsigned)newcell < MAP_CELL_TOTAL) {
    768 				(*this)[newcell].Overlap_Up(object);
    769 				(*this)[newcell].Redraw_Objects();
    770 			}
    771 		}
    772 	}
    773 }
    774 
    775 
    776 /***********************************************************************************************
    777  * MapClass::Overlap_Down -- computes & marks object's overlap cells                           *
    778  *                                                                                             *
    779  * This routine is just like Place_Down, but it doesn't mark the cell's Occupier.              *
    780  * This routine is used to implement MARK_OVERLAP_DOWN, which is useful for changing           *
    781  * an object's render size, but not its logical size (ie when it's selected or an              *
    782  * animation is attached to it).                                                               *
    783  *                                                                                             *
    784  * INPUT:                                                                                      *
    785  *      cell -- The cell to base object overlap around.                                        *
    786  *    object   -- The object to place onto the map.                                            *
    787  *                                                                                             *
    788  * OUTPUT:                                                                                     *
    789  *      none.                                                                                  *
    790  *                                                                                             *
    791  * WARNINGS:                                                                                   *
    792  *      none.                                                                                  *
    793  *                                                                                             *
    794  * HISTORY:                                                                                    *
    795  *   07/12/1995 BRR : Created.                                                                 *
    796  *=============================================================================================*/
    797 void MapClass::Overlap_Down(CELL cell, ObjectClass * object)
    798 {
    799 	if (!object) return;
    800 
    801 	if (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {
    802 		short xlist[32];
    803 		List_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);
    804 		short const * list = xlist;
    805 		while (*list != REFRESH_EOL) {
    806 			CELL newcell = cell + *list++;
    807 			if ((unsigned)newcell < MAP_CELL_TOTAL) {
    808 				(*this)[newcell].Overlap_Down(object);
    809 				(*this)[newcell].Redraw_Objects();
    810 			}
    811 		}
    812 	}
    813 }
    814 
    815 
    816 /***********************************************************************************************
    817  * MapClass::Overlap_Up -- Computes & clears object's overlap cells                            *
    818  *                                                                                             *
    819  * This routine is just like Pick_Up, but it doesn't mark the cell's Occupier.                 *
    820  * This routine is used to implement MARK_OVERLAP_UP, which is useful for changing             *
    821  * an object's render size, but not its logical size (ie when it's selected or an              *
    822  * animation is attached to it).                                                               *
    823  *                                                                                             *
    824  * INPUT:                                                                                      *
    825  *      cell -- The cell to base object overlap around.                                        *
    826  *    object   -- The object to place onto the map.                                            *
    827  *                                                                                             *
    828  * OUTPUT:                                                                                     *
    829  *      none.                                                                                  *
    830  *                                                                                             *
    831  * WARNINGS:                                                                                   *
    832  *      none.                                                                                  *
    833  *                                                                                             *
    834  * HISTORY:                                                                                    *
    835  *   07/12/1995 BRR : Created.                                                                 *
    836  *=============================================================================================*/
    837 void MapClass::Overlap_Up(CELL cell, ObjectClass * object)
    838 {
    839 	if (!object) return;
    840 
    841 	if (object->Class_Of().IsFootprint && object->In_Which_Layer() == LAYER_GROUND)  {
    842 		short xlist[32];
    843 		List_Copy(object->Overlap_List(), ARRAY_SIZE(xlist), xlist);
    844 		short const * list = xlist;
    845 		while (*list != REFRESH_EOL) {
    846 			CELL newcell = cell + *list++;
    847 			if ((unsigned)newcell < MAP_CELL_TOTAL) {
    848 				(*this)[newcell].Overlap_Up(object);
    849 				(*this)[newcell].Redraw_Objects();
    850 			}
    851 		}
    852 	}
    853 }
    854 
    855 
    856 /***********************************************************************************************
    857  * MapClass::Overpass -- Performs any final cleanup to a freshly constructed map.              *
    858  *                                                                                             *
    859  *    This routine will clean up anything necessary with the presumption that the map has      *
    860  *    been freshly created. Such things to clean up include various tiberium concentrations.   *
    861  *                                                                                             *
    862  * INPUT:   none                                                                               *
    863  *                                                                                             *
    864  * OUTPUT:  Returns the total credit value of the tiberium on the map.                         *
    865  *                                                                                             *
    866  * WARNINGS:   none                                                                            *
    867  *                                                                                             *
    868  * HISTORY:                                                                                    *
    869  *   09/19/1994 JLB : Created.                                                                 *
    870  *   02/13/1995 JLB : Returns total tiberium worth.                                            *
    871  *   02/15/1995 JLB : Optimal scan.                                                            *
    872  *=============================================================================================*/
    873 long MapClass::Overpass(void)
    874 {
    875 	long value = 0;
    876 
    877 	/*
    878 	**	Smooth out Tiberium. Cells that are not surrounded by other tiberium
    879 	**	will be reduced in density.
    880 	*/
    881 	for (int y = 0; y < MapCellHeight; y++) {
    882 		for (int x = 0; x < MapCellWidth; x++) {
    883 			CELL cell = (MapCellY+y) * MAP_CELL_W + (MapCellX+x);
    884 			value += (*this)[cell].Tiberium_Adjust(true);
    885 			(*this)[cell].Recalc_Attributes();
    886 		}
    887 	}
    888 	return(value);
    889 }
    890 
    891 
    892 /***********************************************************************************************
    893  * MapClass::Write_Binary -- Pipes the map template data to the destination specified.         *
    894  *                                                                                             *
    895  *    This stores the template data from the map to the output pipe specified. The template    *
    896  *    data consists of the template type number and template icon number for every cell on     *
    897  *    the map. The output is organized in such a way so as to get maximum compression.         *
    898  *                                                                                             *
    899  * INPUT:   pipe  -- Reference to the output pipe that will receive the map template data.     *
    900  *                                                                                             *
    901  * OUTPUT:  Returns with the total number of bytes output to the pipe.                         *
    902  *                                                                                             *
    903  * WARNINGS:   none                                                                            *
    904  *                                                                                             *
    905  * HISTORY:                                                                                    *
    906  *   07/03/1996 JLB : Created.                                                                 *
    907  *=============================================================================================*/
    908 int MapClass::Write_Binary(Pipe & pipe)
    909 {
    910 	int total = 0;
    911 
    912 	LCWPipe comp(LCWPipe::COMPRESS);
    913 	comp.Put_To(&pipe);
    914 
    915 	CellClass * cellptr = &Array[0];
    916 	for (int i = 0; i < MAP_CELL_TOTAL; i++) {
    917 		total += comp.Put(&cellptr->TType, sizeof(cellptr->TType));
    918 		cellptr++;
    919 	}
    920 
    921 	cellptr = &Array[0];
    922 	for (int i = 0; i < MAP_CELL_TOTAL; i++) {
    923 		total += comp.Put(&cellptr->TIcon, sizeof(cellptr->TIcon));
    924 		cellptr++;
    925 	}
    926 
    927 	return(total);
    928 }
    929 
    930 
    931 /***********************************************************************************************
    932  * MapClass::Read_Binary -- Reads the binary data from the straw specified.                    *
    933  *                                                                                             *
    934  *    This routine will retrieve the map template data from the straw specified.               *
    935  *                                                                                             *
    936  * INPUT:   straw -- Reference to the straw that will supply the map template data.            *
    937  *                                                                                             *
    938  * OUTPUT:  bool; Was the template data retrieved?                                             *
    939  *                                                                                             *
    940  * WARNINGS:   none                                                                            *
    941  *                                                                                             *
    942  * HISTORY:                                                                                    *
    943  *   07/03/1996 JLB : Created.                                                                 *
    944  *=============================================================================================*/
    945 bool MapClass::Read_Binary(Straw & straw)
    946 {
    947 	LCWStraw decomp(LCWStraw::DECOMPRESS);
    948 	decomp.Get_From(&straw);
    949 
    950 	CELL cell;
    951 	CellClass * cellptr;
    952 	switch (NewINIFormat) {
    953 		default:
    954 			cellptr = &Array[0];
    955 			for (cell = 0; cell < MAP_CELL_TOTAL; cell++) {
    956 				decomp.Get(&cellptr->TType, sizeof(cellptr->TType));
    957 				cellptr++;
    958 			}
    959 			cellptr = &Array[0];
    960 			for (cell = 0; cell < MAP_CELL_TOTAL; cell++) {
    961 				decomp.Get(&cellptr->TIcon, sizeof(cellptr->TIcon));
    962 				cellptr->Recalc_Attributes();
    963 				cellptr++;
    964 			}
    965 			break;
    966 
    967 		case 0:
    968 		case 1:
    969 		case 2:
    970 			cellptr = &Array[0];
    971 			for (cell = 0; cell < MAP_CELL_TOTAL; cell++) {
    972 				decomp.Get(&cellptr->TType, sizeof(cellptr->TType));
    973 				decomp.Get(&cellptr->TIcon, sizeof(cellptr->TIcon));
    974 				cellptr->Recalc_Attributes();
    975 				cellptr++;
    976 			}
    977 			break;
    978 	}
    979 	return(true);
    980 }
    981 
    982 
    983 /***********************************************************************************************
    984  * MapClass::Logic -- Handles map related logic functions.                                     *
    985  *                                                                                             *
    986  *    Manages tiberium growth and spread.                                                      *
    987  *                                                                                             *
    988  * INPUT:   none                                                                               *
    989  *                                                                                             *
    990  * OUTPUT:  none                                                                               *
    991  *                                                                                             *
    992  * WARNINGS:   none                                                                            *
    993  *                                                                                             *
    994  * HISTORY:                                                                                    *
    995  *   05/11/1995 JLB : Created.                                                                 *
    996  *   07/09/1995 JLB : Handles two directional scan.                                            *
    997  *   08/01/1995 JLB : Gives stronger weight to blossom trees.                                  *
    998  *=============================================================================================*/
    999 void MapClass::Logic(void)
   1000 {
   1001 	if (Debug_Force_Crash) { *((int *)0) = 1; }
   1002 	/*
   1003 	**	Crate regeneration is handled here.
   1004 	*/
   1005 	if (Session.Type != GAME_NORMAL && Session.Options.Goodies) {
   1006 
   1007 		/*
   1008 		**	Find any crate that has expired and then regenerate it at a new
   1009 		**	spot.
   1010 		*/
   1011 		for (int index = 0; index < ARRAY_SIZE(Crates); index++) {
   1012 			if (Crates[index].Is_Expired()) {
   1013 				Crates[index].Remove_It();
   1014 				Place_Random_Crate();
   1015 			}
   1016 		}
   1017 	}
   1018 
   1019 	/*
   1020 	**	Bail early if there is no allowed growth or spread of Tiberium.
   1021 	*/
   1022 	if (!Rule.IsTGrowth && !Rule.IsTSpread) return;
   1023 
   1024 	/*
   1025 	**	Scan another block of the map in order to accumulate the potential
   1026 	**	Tiberium cells that can grow or spread.
   1027 	*/
   1028 	int subcount = MAP_CELL_TOTAL / (Rule.GrowthRate * TICKS_PER_MINUTE);
   1029 
   1030 	/*
   1031 	** Use the Tiberium setting as a multiplier on growth rate. ST - 7/1/2020 3:05PM
   1032 	*/
   1033 	if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   1034 		if (Session.Options.Tiberium > 1) {
   1035 			subcount *= Session.Options.Tiberium;
   1036 		}
   1037 	}		 
   1038 
   1039 	subcount = max(subcount, 1);
   1040 	int index;
   1041 	for (index = TiberiumScan; index < MAP_CELL_TOTAL; index++) {
   1042 		CELL cell = index;
   1043 		if (In_Radar(cell)) {
   1044 			CellClass * ptr = &(*this)[cell];
   1045 
   1046 			/*
   1047 			**	Tiberium cells can grow.
   1048 			*/
   1049 			if (ptr->Can_Tiberium_Grow()) {
   1050 
   1051 				/*
   1052 				**	Either replace an existing recorded cell value or add the new cell value to
   1053 				**	the list.
   1054 				*/
   1055 				if (Random_Pick(0, TiberiumGrowthExcess) <= TiberiumGrowthCount) {
   1056 					if (TiberiumGrowthCount < sizeof(TiberiumGrowth)/sizeof(TiberiumGrowth[0])) {
   1057 						TiberiumGrowth[TiberiumGrowthCount++] = cell;
   1058 					} else {
   1059 						TiberiumGrowth[Random_Pick(0, TiberiumGrowthCount-1)] = cell;
   1060 					}
   1061 				}
   1062 				TiberiumGrowthExcess++;
   1063 			}
   1064 
   1065 			/*
   1066 			**	Heavy Tiberium growth can spread.
   1067 			*/
   1068 			if (ptr->Can_Tiberium_Spread()) {
   1069 				/*
   1070 				**	Either replace an existing recorded cell value or add the new cell value to
   1071 				**	the list.
   1072 				*/
   1073 				if (Random_Pick(0, TiberiumSpreadExcess) <= TiberiumSpreadCount) {
   1074 					if (TiberiumSpreadCount < ARRAY_SIZE(TiberiumSpread)) {
   1075 						TiberiumSpread[TiberiumSpreadCount++] = cell;
   1076 					} else {
   1077 						TiberiumSpread[Random_Pick(0, TiberiumSpreadCount-1)] = cell;
   1078 					}
   1079 				}
   1080 				TiberiumSpreadExcess++;
   1081 			}
   1082 		}
   1083 
   1084 		subcount--;
   1085 		if (subcount == 0) break;
   1086 	}
   1087 	TiberiumScan = index;
   1088 
   1089 	/*
   1090 	**	When the entire map has been processed, proceed with tiberium (ore) growth
   1091 	**	and spread action.
   1092 	*/
   1093 	if (TiberiumScan >= MAP_CELL_TOTAL) {
   1094 		TiberiumScan = 0;
   1095 
   1096 		/*
   1097 		**	Growth logic.
   1098 		*/
   1099 		if (TiberiumGrowthCount) {
   1100 			for (int i = 0; i < TiberiumGrowthCount; i++) {
   1101 				CELL cell = TiberiumGrowth[i];
   1102 				CellClass * newcell = &(*this)[cell];
   1103 				newcell->Grow_Tiberium();
   1104 			}
   1105 		}
   1106 		TiberiumGrowthCount = 0;
   1107 		TiberiumGrowthExcess = 0;
   1108 
   1109 		/*
   1110 		**	Spread logic.
   1111 		*/
   1112 		if (TiberiumSpreadCount) {
   1113 			for (int i = 0; i < TiberiumSpreadCount; i++) {
   1114 				Map[TiberiumSpread[i]].Spread_Tiberium();
   1115 			}
   1116 		}
   1117 		TiberiumSpreadCount = 0;
   1118 		TiberiumSpreadExcess = 0;
   1119 	}
   1120 }
   1121 
   1122 
   1123 /***********************************************************************************************
   1124  * MapClass::Cell_Region -- Determines the region from a specified cell number.                *
   1125  *                                                                                             *
   1126  *    Use this routine to determine what region a particular cell lies in.                     *
   1127  *                                                                                             *
   1128  * INPUT:   cell  -- The cell number to examine.                                               *
   1129  *                                                                                             *
   1130  * OUTPUT:  Returns with the region that the specified cell occupies.                          *
   1131  *                                                                                             *
   1132  * WARNINGS:   none                                                                            *
   1133  *                                                                                             *
   1134  * HISTORY:                                                                                    *
   1135  *   03/15/1995 JLB : Created.                                                                 *
   1136  *=============================================================================================*/
   1137 int MapClass::Cell_Region(CELL cell)
   1138 {
   1139 	return((Cell_X(cell) / REGION_WIDTH) + 1) +	(((Cell_Y(cell) / REGION_HEIGHT) + 1) * MAP_REGION_WIDTH);
   1140 }
   1141 
   1142 
   1143 /***************************************************************************
   1144  * MapClass::Cell_Threat -- Gets a houses threat value for a cell          *
   1145  *                                                                         *
   1146  * INPUT:   CELL        cell    - the cell number to check                 *
   1147  *            HouseType house   - the house to check                       *
   1148  *                                                                         *
   1149  * OUTPUT:                                                                 *
   1150  *                                                                         *
   1151  * WARNINGS:                                                               *
   1152  *                                                                         *
   1153  * HISTORY:                                                                *
   1154  *   04/25/1995 PWG : Created.                                             *
   1155  *=========================================================================*/
   1156 int MapClass::Cell_Threat(CELL cell, HousesType house)
   1157 {
   1158 	int threat = HouseClass::As_Pointer(house)->Regions[Map.Cell_Region(Map[cell].Cell_Number())].Threat_Value();
   1159 	//using function for IsVisible so we have different results for different players - JAS 2019/09/30
   1160 	if (!threat && Map[cell].Is_Visible(house)) {
   1161 		threat = 1;
   1162 	}
   1163 	return(threat);
   1164 }
   1165 
   1166 
   1167 /***********************************************************************************************
   1168  * MapClass::Place_Random_Crate -- Places a crate at random location on map.                   *
   1169  *                                                                                             *
   1170  *    This routine will place a crate at a random location on the map. This routine will only  *
   1171  *    make a limited number of attempts to place and if unsuccessful, it will not place any.   *
   1172  *                                                                                             *
   1173  * INPUT:   none                                                                               *
   1174  *                                                                                             *
   1175  * OUTPUT:  Was a crate successfully placed?                                                   *
   1176  *                                                                                             *
   1177  * WARNINGS:   none                                                                            *
   1178  *                                                                                             *
   1179  * HISTORY:                                                                                    *
   1180  *   07/08/1995 JLB : Created.                                                                 *
   1181  *=============================================================================================*/
   1182 bool MapClass::Place_Random_Crate(void)
   1183 {
   1184 	/*
   1185 	**	Find a crate index that is free for assignment. If there are
   1186 	**	no free slots, then return with failure to place crate.
   1187 	*/
   1188 	int crateindex = 0;
   1189 	for (crateindex = 0; crateindex < ARRAY_SIZE(Crates); crateindex++) {
   1190 		if (!Crates[crateindex].Is_Valid()) break;
   1191 	}
   1192 	if (crateindex == ARRAY_SIZE(Crates)) {
   1193 		return(false);
   1194 	}
   1195 
   1196 	/*
   1197 	**	Give a good effort to scan for and place a crate down on the map.
   1198 	*/
   1199 	for (int index = 0; index < 1000; index++) {
   1200 		CELL cell = Map.Pick_Random_Location();
   1201 
   1202 		if (Crates[crateindex].Create_Crate(cell)) {
   1203 			return(true);
   1204 		}
   1205 	}
   1206 	return(false);
   1207 }
   1208 
   1209 
   1210 /***********************************************************************************************
   1211  * MapClass::Remove_Crate -- Remove a crate from the specified cell.                           *
   1212  *                                                                                             *
   1213  *    This will examine the cell and remove any crates there.                                  *
   1214  *                                                                                             *
   1215  * INPUT:   cell  -- The cell to examine for crates and remove from.                           *
   1216  *                                                                                             *
   1217  * OUTPUT:  bool; Was a crate found at the location specified and was it removed?              *
   1218  *                                                                                             *
   1219  * WARNINGS:   none                                                                            *
   1220  *                                                                                             *
   1221  * HISTORY:                                                                                    *
   1222  *   08/26/1996 JLB : Created.                                                                 *
   1223  *=============================================================================================*/
   1224 bool MapClass::Remove_Crate(CELL cell)
   1225 {
   1226 	if (Session.Type != GAME_NORMAL) {
   1227 		for (int index = 0; index < ARRAY_SIZE(Crates); index++) {
   1228 			if (Crates[index].Is_Here(cell)) {
   1229 				return(Crates[index].Remove_It());
   1230 			}
   1231 		}
   1232 	}
   1233 
   1234 //	if (Session.Type == GAME_NORMAL) {
   1235 		CellClass * cellptr = &(*this)[cell];
   1236 		if (cellptr->Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(cellptr->Overlay).IsCrate) {
   1237 			cellptr->Overlay = OVERLAY_NONE;
   1238 			cellptr->OverlayData = 0;
   1239 			return(true);
   1240 		}
   1241 //	} else {
   1242 //		for (int index = 0; index < ARRAY_SIZE(Crates); index++) {
   1243 //			if (Crates[index].Is_Here(cell)) {
   1244 //				return(Crates[index].Remove_It());
   1245 //			}
   1246 //		}
   1247 //	}
   1248 	return(false);
   1249 }
   1250 
   1251 
   1252 /***************************************************************************
   1253  * MapClass::Validate -- validates every cell on the map                   *
   1254  *                                                                         *
   1255  * This is a debugging routine, designed to detect memory trashers that    *
   1256  * alter the map.  This routine is slow, but thorough.                     *
   1257  *                                                                         *
   1258  * INPUT:                                                                  *
   1259  *      none.                                                              *
   1260  *                                                                         *
   1261  * OUTPUT:                                                                 *
   1262  *      true = map is OK, false = an error was found                       *
   1263  *                                                                         *
   1264  * WARNINGS:                                                               *
   1265  *      none.                                                              *
   1266  *                                                                         *
   1267  * HISTORY:                                                                *
   1268  *   07/08/1995 BRR : Created.                                             *
   1269  *=========================================================================*/
   1270 int MapClass::Validate(void)
   1271 {
   1272 	CELL cell;
   1273 	TemplateType ttype;
   1274 	unsigned char ticon;
   1275 	TemplateTypeClass const *tclass;
   1276 	unsigned char map[13*8];
   1277 	OverlayType overlay;
   1278 	SmudgeType smudge;
   1279 	ObjectClass * obj;
   1280 	LandType land;
   1281 	int i;
   1282 
   1283 BlubCell = &Array[797];
   1284 
   1285 if (BlubCell->Overlapper[1]) {
   1286 	obj = BlubCell->Overlapper[1];
   1287 	if (obj) {
   1288 		if (obj->IsInLimbo)
   1289 		obj = obj;
   1290 	}
   1291 }
   1292 
   1293 	/*
   1294 	**	Check every cell on the map, even those that aren't displayed,
   1295 	**	in the hopes of detecting a memory trasher.
   1296 	*/
   1297 	for (cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   1298 		/*
   1299 		**	Validate Template & Icon data
   1300 		*/
   1301 		ttype = (*this)[cell].TType;
   1302 		ticon = (*this)[cell].TIcon;
   1303 		if (ttype >= TEMPLATE_COUNT && ttype != TEMPLATE_NONE)
   1304 			return(false);
   1305 
   1306 		/*
   1307 		**	To validate the icon value, we have to get a copy of the template's
   1308 		**	"icon map"; this map will have 0xff's in spots where there is no
   1309 		**	icon.  If the icon value is out of range or points to an invalid spot,
   1310 		**	return an error.
   1311 		*/
   1312 		if (ttype != TEMPLATE_NONE) {
   1313 			tclass = &TemplateTypeClass::As_Reference(ttype);
   1314 			ticon = (*this)[cell].TIcon;
   1315 			Mem_Copy(Get_Icon_Set_Map(tclass->Get_Image_Data()), map, tclass->Width * tclass->Height);
   1316 			if (ticon < 0 || ticon >= (tclass->Width * tclass->Height) || map[ticon]==0xff) {
   1317 				return (false);
   1318 			}
   1319 		}
   1320 
   1321 		/*
   1322 		**	Validate Overlay
   1323 		*/
   1324 		overlay = (*this)[cell].Overlay;
   1325 		if (overlay < OVERLAY_NONE || overlay >= OVERLAY_COUNT) {
   1326 			return(false);
   1327 		}
   1328 
   1329 		/*
   1330 		**	Validate Smudge
   1331 		*/
   1332 		smudge = (*this)[cell].Smudge;
   1333 		if (smudge < SMUDGE_NONE || smudge >= SMUDGE_COUNT) {
   1334 			return(false);
   1335 		}
   1336 
   1337 		/*
   1338 		**	Validate LandType
   1339 		*/
   1340 		land = (*this)[cell].Land_Type();
   1341 		if (land < LAND_CLEAR || land >= LAND_COUNT) {
   1342 			return(false);
   1343 		}
   1344 
   1345 		/*
   1346 		**	Validate Occupier
   1347 		*/
   1348 		obj = (*this)[cell].Cell_Occupier();
   1349 		if (obj) {
   1350 			if (
   1351 				((unsigned int)obj & 0xff000000) ||
   1352 				((unsigned int)obj->Next & 0xff000000) ||
   1353 //				((unsigned int)obj->Trigger & 0xff000000) ||
   1354 				obj->IsInLimbo ||
   1355 				((unsigned int)Coord_Cell(obj->Coord) >= MAP_CELL_TOTAL)) {
   1356 
   1357 				return (false);
   1358 			}
   1359 		}
   1360 
   1361 		/*
   1362 		**	Validate Overlappers
   1363 		*/
   1364 		for (i = 0; i < ARRAY_SIZE((*this)[cell].CellClass::Overlapper); i++) {
   1365 			obj = (*this)[cell].Overlapper[i];
   1366 			if (obj) {
   1367 				if (
   1368 					((unsigned int)obj & 0xff000000) ||
   1369 					((unsigned int)obj->Next & 0xff000000) ||
   1370 //					((unsigned int)obj->Trigger & 0xff000000) ||
   1371 					obj->IsInLimbo ||
   1372 					((unsigned int)Coord_Cell(obj->Coord) >= MAP_CELL_TOTAL)) {
   1373 
   1374 					return (false);
   1375 				}
   1376 			}
   1377 		}
   1378 	}
   1379 
   1380 	return (true);
   1381 }
   1382 
   1383 
   1384 /***********************************************************************************************
   1385  * MapClass::Close_Object -- Finds a clickable close object to the specified coordinate.       *
   1386  *                                                                                             *
   1387  *    This routine is used by the mouse input processing code to find a clickable object       *
   1388  *    close to coordinate specified. This is for targeting as well as selection determination. *
   1389  *                                                                                             *
   1390  * INPUT:   coord -- The coordinate to scan for close object from.                             *
   1391  *                                                                                             *
   1392  * OUTPUT:  Returns with a pointer to an object that is nearby the specified coordinate.       *
   1393  *                                                                                             *
   1394  * WARNINGS:   There could be a cloaked object at the location, but it won't be considered     *
   1395  *             if it is not owned by the player.                                               *
   1396  *                                                                                             *
   1397  * HISTORY:                                                                                    *
   1398  *   08/20/1995 JLB : Created.                                                                 *
   1399  *=============================================================================================*/
   1400 ObjectClass * MapClass::Close_Object(COORDINATE coord) const
   1401 {
   1402 	ObjectClass * object = 0;
   1403 	int distance = 0;
   1404 	CELL cell = Coord_Cell(coord);
   1405 
   1406 	/*
   1407 	**	Scan through current and adjacent cells, looking for the
   1408 	**	closest object (within reason) to the specified coordinate.
   1409 	*/
   1410 	static int _offsets[] = {0, -1, 1, -MAP_CELL_W, MAP_CELL_W, MAP_CELL_W-1, MAP_CELL_W+1, -(MAP_CELL_W-1), -(MAP_CELL_W+1)};
   1411 	for (int index = 0; index < (sizeof(_offsets) / sizeof(_offsets[0])); index++) {
   1412 
   1413 		/*
   1414 		**	Examine the cell for close object. Make sure that the cell actually is a
   1415 		**	legal one.
   1416 		*/
   1417 		CELL newcell = cell + _offsets[index];
   1418 		if (In_Radar(newcell)) {
   1419 
   1420 			/*
   1421 			**	Search through all objects that occupy this cell and then
   1422 			**	find the closest object. Check against any previously found object
   1423 			**	to ensure that it is actually closer.
   1424 			*/
   1425 			ObjectClass * o = Array[newcell].Cell_Occupier();
   1426 			while (o != NULL) {
   1427 
   1428 				/*
   1429 				**	Special case check to ignore cloaked object if not allied with the player.
   1430 				*/
   1431 				// Change for client/server multiplayer. ST - 8/7/2019 10:35AM
   1432 				//if (!o->Is_Techno() || ((TechnoClass *)o)->IsOwnedByPlayer || ((TechnoClass *)o)->Cloak != CLOAKED) {
   1433 				if (!o->Is_Techno() || !((TechnoClass *)o)->Is_Cloaked(PlayerPtr)) {
   1434 					int d=-1;
   1435 					if (o->What_Am_I() == RTTI_BUILDING) {
   1436 						d = Distance(coord, Cell_Coord(newcell));
   1437 						if (d > 0x00C0) d = -1;
   1438 					} else {
   1439 						d = Distance(coord, o->Center_Coord());
   1440 					}
   1441 					if (d >= 0 && (!object || d < distance)) {
   1442 						distance = d;
   1443 						object = o;
   1444 					}
   1445 				}
   1446 				o = o->Next;
   1447 			}
   1448 		}
   1449 	}
   1450 
   1451 	/*
   1452 	** Handle aircraft selection separately, since they aren't tracked in cells while flying
   1453 	*/
   1454 	for (int index = 0; index < Aircraft.Count(); index++) {
   1455 		AircraftClass * aircraft = Aircraft.Ptr(index);
   1456 
   1457 		if (aircraft->In_Which_Layer() != LAYER_GROUND) {
   1458 			if (!aircraft->Is_Cloaked(PlayerPtr)) {
   1459 				int d = Distance(coord, Coord_Add(aircraft->Center_Coord(), XY_Coord(0, -aircraft->Height)));
   1460 				if (d >= 0 && (!object || d < distance)) {
   1461 					distance = d;
   1462 					object = aircraft;
   1463 				}
   1464 			}
   1465 		}
   1466 	}
   1467 
   1468 	/*
   1469 	**	Only return the object if it is within 1/4 cell distance from the specified
   1470 	**	coordinate.
   1471 	*/
   1472 	if (object && distance > 0xC0) {
   1473 		object = 0;
   1474 	}
   1475 	return(object);
   1476 }
   1477 
   1478 
   1479 /***********************************************************************************************
   1480  * MapClass::Zone_Reset -- Resets all zone numbers to match the map.                           *
   1481  *                                                                                             *
   1482  *    This routine will rescan the map and fill in the zone values for each of the cells.      *
   1483  *    All cells that are contiguous are given the same zone number.                            *
   1484  *                                                                                             *
   1485  * INPUT:   method   -- The method to recalculate the zones upon. If 1 then recalc non         *
   1486  *                      crushable zone. If 2 then recalc crushable zone. If 3, then            *
   1487  *                      recalc both zones.                                                     *
   1488  *                                                                                             *
   1489  * OUTPUT:  none                                                                               *
   1490  *                                                                                             *
   1491  * WARNINGS:   This is a time consuming routine. Call it as infrequently as possible. It must  *
   1492  *             be called whenever something that would affect contiguousness occurs. Example:  *
   1493  *             when a bridge is built or destroyed.                                            *
   1494  *                                                                                             *
   1495  * HISTORY:                                                                                    *
   1496  *   09/22/1995 JLB : Created.                                                                 *
   1497  *=============================================================================================*/
   1498 bool MapClass::Zone_Reset(int method)
   1499 {
   1500 	/*
   1501 	**	Zero out all zones to a null state.
   1502 	*/
   1503 	for (int index = 0; index < MAP_CELL_TOTAL; index++) {
   1504 		if (method & MZONEF_NORMAL) {
   1505 			Array[index].Zones[MZONE_NORMAL] = 0;
   1506 		}
   1507 		if (method & MZONEF_CRUSHER) {
   1508 			Array[index].Zones[MZONE_CRUSHER] = 0;
   1509 		}
   1510 		if (method & MZONEF_DESTROYER) {
   1511 			Array[index].Zones[MZONE_DESTROYER] = 0;
   1512 		}
   1513 		if (method & MZONEF_WATER) {
   1514 			Array[index].Zones[MZONE_WATER] = 0;
   1515 		}
   1516 	}
   1517 
   1518 	/*
   1519 	**	Normal zone recalculation.
   1520 	*/
   1521 	if (method & MZONEF_NORMAL) {
   1522 		int zone = 1;			// Starting zone number.
   1523 		for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   1524 			if (Zone_Span(cell, zone, MZONE_NORMAL)) {
   1525 				zone++;
   1526 			}
   1527 		}
   1528 	}
   1529 
   1530 	/*
   1531 	**	Crushable wall recalculation.
   1532 	*/
   1533 	if (method & MZONEF_CRUSHER) {
   1534 		int zone = 1;			// Starting zone number.
   1535 		for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   1536 			if (Zone_Span(cell, zone, MZONE_CRUSHER)) {
   1537 				zone++;
   1538 			}
   1539 		}
   1540 	}
   1541 
   1542 	/*
   1543 	**	Wall destroyer zone recalculation.
   1544 	*/
   1545 	if (method & MZONEF_DESTROYER) {
   1546 		int zone = 1;			// Starting zone number.
   1547 		for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   1548 			if (Zone_Span(cell, zone, MZONE_DESTROYER)) {
   1549 				zone++;
   1550 			}
   1551 		}
   1552 	}
   1553 
   1554 	/*
   1555 	**	Water based zone recalcuation.
   1556 	*/
   1557 	if (method & MZONEF_WATER) {
   1558 		int zone = 1;			// Starting zone number.
   1559 		for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   1560 			if (Zone_Span(cell, zone, MZONE_WATER)) {
   1561 				zone++;
   1562 			}
   1563 		}
   1564 	}
   1565 
   1566 	return(false);
   1567 }
   1568 
   1569 
   1570 /***********************************************************************************************
   1571  * MapClass::Zone_Span -- Flood fills the specified zone from the cell origin.                 *
   1572  *                                                                                             *
   1573  *    This routine is used to fill a zone value into the map. The map is "flood filled" from   *
   1574  *    the cell specified. All adjacent (8 connected) and generally passable terrain cells are  *
   1575  *    given the zone number specified. This routine checks for legality before filling         *
   1576  *    occurs. The routine is safe to call even if the legality of the cell is unknown at the   *
   1577  *    time of the call.                                                                        *
   1578  *                                                                                             *
   1579  * INPUT:   cell  -- The cell to begin filling from.                                           *
   1580  *                                                                                             *
   1581  *          zone  -- The zone number to assign to all adjacent cells.                          *
   1582  *                                                                                             *
   1583  *          check -- The zone type to check against.                                           *
   1584  *                                                                                             *
   1585  * OUTPUT:  Returns with the number of cells marked by this routine.                           *
   1586  *                                                                                             *
   1587  * WARNINGS:   This routine is slow and recursive. Only use when necessary.                    *
   1588  *                                                                                             *
   1589  * HISTORY:                                                                                    *
   1590  *   09/25/1995 JLB : Created.                                                                 *
   1591  *   10/05/1996 JLB : Examines crushable walls.                                                *
   1592  *=============================================================================================*/
   1593 int MapClass::Zone_Span(CELL cell, int zone, MZoneType check)
   1594 {
   1595 	int filled = 0;
   1596 	int xbegin = Cell_X(cell);
   1597 	int xend = xbegin;
   1598 	int y = Cell_Y(cell);
   1599 
   1600 	/*
   1601 	**	Perform some preliminary legality checks. If the cell specified
   1602 	**	is illegal, then no further processing is necessary.
   1603 	*/
   1604 	if (y < MapCellY || y >= MapCellY+MapCellHeight || xbegin < MapCellX || xbegin >= MapCellX+MapCellWidth) {
   1605 		return(0);
   1606 	}
   1607 
   1608 	/*
   1609 	**	Find the full extent of the current span by first scanning leftward
   1610 	**	until a boundary is reached.
   1611 	*/
   1612 	for (; xbegin >= MapCellX; xbegin--) {
   1613 		CellClass * cellptr = &(*this)[XY_Cell(xbegin, y)];
   1614 		if (cellptr->Zones[check] != 0 || (!cellptr->Is_Clear_To_Move(check == MZONE_WATER ? SPEED_FLOAT : SPEED_TRACK, true, true, -1, check))) {
   1615 
   1616 			/*
   1617 			**	Special short circuit code to bail from this entire routine if
   1618 			**	it was called for a cell that is not a legal candidate for
   1619 			**	zone marking. This eliminates redundant processing and allows this
   1620 			**	routine to be called for illegal cells without causing an error.
   1621 			*/
   1622 			if (xbegin == Cell_X(cell)) return(0);
   1623 
   1624 			/*
   1625 			**	Otherwise break out of the left scan since a boundary was discovered.
   1626 			*/
   1627 			xbegin++;
   1628 			break;
   1629 		}
   1630 	}
   1631 	xbegin = max(xbegin, MapCellX);
   1632 
   1633 	/*
   1634 	**	Scan rightward until a boundary is reached. This will then define the
   1635 	**	extent of the current span.
   1636 	*/
   1637 	for (; xend < MapCellX+MapCellWidth; xend++) {
   1638 		CellClass * cellptr = &(*this)[XY_Cell(xend, y)];
   1639 		if (cellptr->Zones[check] != 0 || (!cellptr->Is_Clear_To_Move(check == MZONE_WATER ? SPEED_FLOAT : SPEED_TRACK, true, true, -1, check))) {
   1640 			xend--;
   1641 			break;
   1642 		}
   1643 	}
   1644 	xend = min(xend, MapCellX+MapCellWidth-1);
   1645 
   1646 	/*
   1647 	**	At this point we know the bounds of the current span. Fill in the zone values
   1648 	**	for the entire span.
   1649 	*/
   1650 	for (int x = xbegin; x <= xend; x++) {
   1651 		(*this)[XY_Cell(x, y)].Zones[check] = zone;
   1652 		filled++;
   1653 	}
   1654 
   1655 	/*
   1656 	**	Now scan the upper and lower shadow rows. If any of these rows contain
   1657 	**	candidate cells, then recursively call the span process for them. Take
   1658 	**	note that the adjacent span scanning starts one cell wider on each
   1659 	**	end of the scan. This is necessary because diagonals are considered
   1660 	**	adjacent.
   1661 	*/
   1662 	for (int x = xbegin-1; x <= xend; x++) {
   1663 		filled += Zone_Span(XY_Cell(x, y-1), zone, check);
   1664 		filled += Zone_Span(XY_Cell(x, y+1), zone, check);
   1665 	}
   1666 	return(filled);
   1667 }
   1668 
   1669 
   1670 /***********************************************************************************************
   1671  * MapClass::Nearby_Location -- Finds a generally clear location near a specified cell.        *
   1672  *                                                                                             *
   1673  *    This routine is used to find a location that probably will be ok to move to that is      *
   1674  *    located as close as possible to the specified cell. The computer uses this when it has   *
   1675  *    determined the ideal location for an object, but then needs to give a valid movement     *
   1676  *    destination to a unit.                                                                   *
   1677  *                                                                                             *
   1678  * INPUT:   cell  -- The cell that scanning should radiate out from.                           *
   1679  *                                                                                             *
   1680  *          zone  -- The zone that must be matched to find a legal location (value of -1 means *
   1681  *                   any zone will do).                                                        *
   1682  *                                                                                             *
   1683  *                                                                                             *
   1684  *          check -- The type of zone to check against. Only valid if a zone value is given.   *
   1685  *                                                                                             *
   1686  *          checkflagged -- Whether the cell's flagged status is checked (used when dropping). *
   1687  *                                                                                             *
   1688  * OUTPUT:  Returns with the cell that is generally clear (legal to move to) that is close     *
   1689  *          to the specified cell.                                                             *
   1690  *                                                                                             *
   1691  * WARNINGS:   none                                                                            *
   1692  *                                                                                             *
   1693  * HISTORY:                                                                                    *
   1694  *   10/05/1995 JLB : Created.                                                                 *
   1695  *=============================================================================================*/
   1696 CELL MapClass::Nearby_Location(CELL cell, SpeedType speed, int zone, MZoneType check, bool checkflagged, int locationmod) const
   1697 {
   1698 	CELL topten[10];
   1699 	int count = 0;
   1700 	int xx = Cell_X(cell);
   1701 	int yy = Cell_Y(cell);
   1702 
   1703 	/*
   1704 	**	Determine the limits of the scanning in the four directions so that
   1705 	**	it won't scan past the edge of the world.
   1706 	*/
   1707 	int left = MapCellX;
   1708 	int right = MapCellX + MapCellWidth - 1;
   1709 	int top = MapCellY;
   1710 	int bottom = MapCellY + MapCellHeight - 1;
   1711 
   1712 	/*
   1713 	**	Radiate outward from the specified location, looking for the closest
   1714 	**	location that is generally clear.
   1715 	*/
   1716 	for (int radius = 0; radius < MAP_CELL_W; radius++) {
   1717 		CELL newcell;
   1718 		CellClass const * cellptr;
   1719 
   1720 		/*
   1721 		**	Scan the top and bottom rows of the "box".
   1722 		*/
   1723 		for (int x = xx-radius; x <= xx+radius; x++) {
   1724 			if (x >= left && x <= right) {
   1725 				int y = yy-radius;
   1726 				if (y >= top) {
   1727 					newcell = XY_Cell(x, y);
   1728 					cellptr = &Map[newcell];
   1729 					if (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check) && (!checkflagged || !cellptr->IsFlagged)) {
   1730 						topten[count++] = newcell;
   1731 					}
   1732 				}
   1733 				if (count == ARRAY_SIZE(topten)) break;
   1734 
   1735 				y = yy+radius;
   1736 				if (y <= bottom) {
   1737 					newcell = XY_Cell(x, y);
   1738 					cellptr = &Map[newcell];
   1739 					if (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check) && (!checkflagged || !cellptr->IsFlagged)) {
   1740 						topten[count++] = newcell;
   1741 					}
   1742 				}
   1743 				if (count == ARRAY_SIZE(topten)) break;
   1744 			}
   1745 		}
   1746 
   1747 		if (count == ARRAY_SIZE(topten)) break;
   1748 
   1749 		/*
   1750 		**	Scan the left and right columns of the "box".
   1751 		*/
   1752 		for (int y = yy-radius; y <= yy+radius; y++) {
   1753 			if (y >= top && y <= bottom) {
   1754 				int x = xx-radius;
   1755 				if (x >= left) {
   1756 					newcell = XY_Cell(x, y);
   1757 					cellptr = &Map[newcell];
   1758 					if (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check) && (!checkflagged || !cellptr->IsFlagged)) {
   1759 						topten[count++] = newcell;
   1760 					}
   1761 				}
   1762 				if (count == ARRAY_SIZE(topten)) break;
   1763 
   1764 				x = xx+radius;
   1765 				if (x <= right) {
   1766 					newcell = XY_Cell(x, y);
   1767 					cellptr = &Map[newcell];
   1768 					if (Map.In_Radar(newcell) && cellptr->Is_Clear_To_Move(speed, false, false, zone, check) && (!checkflagged || !cellptr->IsFlagged)) {
   1769 						topten[count++] = newcell;
   1770 					}
   1771 				}
   1772 				if (count == ARRAY_SIZE(topten)) break;
   1773 			}
   1774 		}
   1775 
   1776 		if (count > 0) break;
   1777 	}
   1778 
   1779 	if (count > 0) {
   1780 		return(topten[(Frame+locationmod) % count]);
   1781 	}
   1782 	return(0);
   1783 }
   1784 
   1785 
   1786 /***********************************************************************************************
   1787  * MapClass::Base_Region -- Finds the owner and base zone for specified cell.                  *
   1788  *                                                                                             *
   1789  *    This routine is used to determine what base the specified cell is close to and what      *
   1790  *    zone of that base the cell lies in. This routine is particularly useful in letting the   *
   1791  *    computer know when the player targets a destination near a computer's base.              *
   1792  *                                                                                             *
   1793  * INPUT:   cell     -- The cell that is to be checked.                                        *
   1794  *                                                                                             *
   1795  *          house    -- Reference to the house type number. This value will be set if a base   *
   1796  *                      was found nearby the specified cell.                                   *
   1797  *                                                                                             *
   1798  *          zone     -- The zone that the cell is located in IF the cell is near a base.       *
   1799  *                                                                                             *
   1800  *                                                                                             *
   1801  * OUTPUT:  Was a base near the specified cell found? If not, then the 'house' and 'zone'      *
   1802  *          reference values are left in an undefined state and the return value will be       *
   1803  *          false.                                                                             *
   1804  *                                                                                             *
   1805  * WARNINGS:   none                                                                            *
   1806  *                                                                                             *
   1807  * HISTORY:                                                                                    *
   1808  *   10/05/1995 JLB : Created.                                                                 *
   1809  *=============================================================================================*/
   1810 bool MapClass::Base_Region(CELL cell, HousesType & house, ZoneType & zone) const
   1811 {
   1812 	if ((unsigned)cell < MAP_CELL_TOTAL && In_Radar(cell)) {
   1813 		for (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
   1814 			HouseClass * h = HouseClass::As_Pointer(house);
   1815 
   1816 			if (h && h->IsActive && !h->IsDefeated && h->Center) {
   1817 				zone = h->Which_Zone(cell);
   1818 				if (zone != ZONE_NONE) {
   1819 					return(true);
   1820 				}
   1821 			}
   1822 		}
   1823 	}
   1824 	return(false);
   1825 }
   1826 
   1827 
   1828 /***********************************************************************************************
   1829  * MapClass::Destroy_Bridge_At -- Destroyes the bridge at location specified.                  *
   1830  *                                                                                             *
   1831  *    This routine will destroy the bridge at the location specified.                          *
   1832  *                                                                                             *
   1833  * INPUT:   cell  -- A cell that can uniquely identify the bridge.                             *
   1834  *                                                                                             *
   1835  * OUTPUT:  bool; Was the bridge destroyed?                                                    *
   1836  *                                                                                             *
   1837  * WARNINGS:   none                                                                            *
   1838  *                                                                                             *
   1839  * HISTORY:                                                                                    *
   1840  *   07/29/1996 JLB : Created.                                                                 *
   1841  *=============================================================================================*/
   1842 
   1843 // Need to inform the server of the cell change so it can communicate with the clients - SKY
   1844 extern void On_Update_Map_Cell(int cell_x, int cell_y, const char* template_type_name);
   1845 
   1846 struct CellUpdateStruct
   1847 {
   1848 	const TemplateTypeClass* Type;
   1849 	CELL Cell;
   1850 };
   1851 
   1852 static const int MAX_UPDATES = 8;
   1853 
   1854 static void Add_Cell_Update(CellUpdateStruct* updates, int& count, TemplateType type, CELL cell)
   1855 {
   1856 	new TemplateClass(type, cell);
   1857 
   1858 	assert(count < MAX_UPDATES);
   1859 	if (count < MAX_UPDATES)
   1860 	{
   1861 		updates[count].Type = TemplateTypes.Ptr((int)type);
   1862 		updates[count].Cell = cell;
   1863 		count++;
   1864 	}
   1865 }
   1866 
   1867 bool MapClass::Destroy_Bridge_At(CELL cell)
   1868 {
   1869 	bool destroyed = false;
   1870 	if (In_Radar(cell) && !Special.IsCaptureTheFlag) {
   1871 		CellClass * cellptr = &(*this)[cell];
   1872 		TemplateType ttype = cellptr->TType;
   1873 
   1874 		CellUpdateStruct cell_updates[MAX_UPDATES];
   1875 		int update_count = 0;
   1876 
   1877 		if (ttype == TEMPLATE_BRIDGE1 || ttype == TEMPLATE_BRIDGE2) {
   1878 			int icon = cellptr->TIcon;
   1879 			int w = TemplateTypeClass::As_Reference(ttype).Width;
   1880 			int h = TemplateTypeClass::As_Reference(ttype).Height;
   1881 
   1882 			cell -= icon % w;
   1883 			cell -= MAP_CELL_W * (icon / w);
   1884 
   1885 			if (ttype == TEMPLATE_BRIDGE1) {
   1886 				Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE1H, cell);
   1887 			} else {
   1888 				Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE2H, cell);
   1889 			}
   1890 
   1891 			new AnimClass(ANIM_NAPALM3, Cell_Coord(cell + w/2 + (h/2)*MAP_CELL_W));
   1892 		}
   1893 
   1894 		if (ttype == TEMPLATE_BRIDGE1H || ttype == TEMPLATE_BRIDGE2H) {
   1895 			int icon = cellptr->TIcon;
   1896 			int bridge_w = TemplateTypeClass::As_Reference(ttype).Width;
   1897 			int bridge_h = TemplateTypeClass::As_Reference(ttype).Height;
   1898 
   1899 			cell -= icon % bridge_w;
   1900 			cell -= MAP_CELL_W * (icon / bridge_w);
   1901 
   1902 			if (ttype == TEMPLATE_BRIDGE1H) {
   1903 				Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE1D, cell);
   1904 			} else {
   1905 				Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE2D, cell);
   1906 			}
   1907 
   1908 			Scen.BridgeCount--;
   1909 			Scen.IsBridgeChanged = true;
   1910 			new AnimClass(ANIM_NAPALM3, Cell_Coord(cell + bridge_w/2 + (bridge_h/2)*MAP_CELL_W));
   1911 			Map.Zone_Reset(MZONEF_ALL);
   1912 
   1913 			/*
   1914 			** Now, loop through all the bridge cells and find anyone standing
   1915 			** on a destroyed part (which is now river), and nuke them.
   1916 			*/
   1917 			CELL cell2 = cell;
   1918 			for (int y = 0; y < bridge_h; y++) {
   1919 				for (int x = 0; x < bridge_w; x++) {
   1920 					CellClass * bridge_cell = &(*this)[cell2];
   1921 					if (bridge_cell->TType == ttype) {
   1922 
   1923 						/*
   1924 						**	Any unit that is firing on the bridge at this location, will stop
   1925 						**	firing because the bridge has been destroyed.
   1926 						*/
   1927 						Detach_This_From_All(As_Target(cell2), true);
   1928 
   1929 						ObjectClass * obj = bridge_cell->Cell_Occupier();
   1930 						while (obj != NULL) {
   1931 							ObjectClass * next = obj->Next;
   1932 							if (obj->Is_Techno()) {
   1933 								int damage = obj->Strength;
   1934 								obj->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
   1935 							}
   1936 							obj = next;
   1937 						}
   1938 					}
   1939 					cell2++;
   1940 				}
   1941 				cell2 += MAP_CELL_W - bridge_w;
   1942 			}
   1943 			Shake_The_Screen(3);
   1944 
   1945 			destroyed = true;
   1946 		} else {
   1947 			/*
   1948 			** All this code is for the multi-part bridges.
   1949 			*/
   1950 			if (ttype >= TEMPLATE_BRIDGE_1A && ttype <= TEMPLATE_BRIDGE_3E) {
   1951 				int icon = cellptr->TIcon;
   1952 				int w = TemplateTypeClass::As_Reference(ttype).Width;
   1953 				int h = TemplateTypeClass::As_Reference(ttype).Height;
   1954 
   1955 				cell -= icon % w;
   1956 				cell -= MAP_CELL_W * (icon / w);
   1957 				switch (ttype) {
   1958 					case TEMPLATE_BRIDGE_1A:
   1959 					case TEMPLATE_BRIDGE_1B:
   1960 					case TEMPLATE_BRIDGE_2A:
   1961 					case TEMPLATE_BRIDGE_2B:
   1962 					case TEMPLATE_BRIDGE_3A:
   1963 					case TEMPLATE_BRIDGE_3B:
   1964 						ttype++;
   1965 						Add_Cell_Update(cell_updates, update_count, ttype, cell);
   1966 						break;
   1967 		 		}
   1968 
   1969 				/*
   1970 				** If we were a middle piece that just got blown up, update the
   1971 				** adjoining pieces to make sure they're shaped properly.
   1972 				*/
   1973 				if (ttype == TEMPLATE_BRIDGE_3C) {
   1974 					// check the template below us, at x-1, y+1
   1975 					CELL cell2 = cell + (MAP_CELL_W - 1);
   1976 					CellClass * celptr = &(*this)[cell2];
   1977 					if (celptr->TType == TEMPLATE_BRIDGE_3C) {
   1978 						// It was also destroyed.  Update us and it.
   1979 						Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3D, cell);
   1980 						Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3E, cell2);
   1981 					}
   1982 
   1983 					// Now check the template above us, at x+1, y-1.
   1984 					cell2 = cell - (MAP_CELL_W - 1);
   1985 					celptr = &(*this)[cell2];
   1986 					if (celptr->TType == TEMPLATE_BRIDGE_3C) {
   1987 						if (cellptr->TType == TEMPLATE_BRIDGE_3D) {
   1988 							// if we're already one-sided, turn us to all water
   1989 							Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3F, cell);
   1990 						} else {
   1991 							Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3E, cell);
   1992 						}
   1993 						Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3D, cell2);
   1994 					}
   1995 					Map.Zone_Reset(MZONEF_ALL);
   1996 				}
   1997 
   1998 				/*
   1999 				** If we're an end bridge piece, update the adjoining piece to
   2000 				** be the proper shape.
   2001 				*/
   2002 				if (cellptr->TType == TEMPLATE_BRIDGE_1C) {
   2003 					Scen.BridgeCount--;
   2004 					Scen.IsBridgeChanged = true;
   2005 
   2006 					// Point to the template below us, x-1, y+2
   2007 					CELL cell2 = cell + (MAP_CELL_W * 2) - 1;
   2008 					switch ((*this)[cell2].TType) {
   2009 						case TEMPLATE_BRIDGE_3A:
   2010 						case TEMPLATE_BRIDGE_3B:
   2011 						case TEMPLATE_BRIDGE_3C:
   2012 							Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3E, cell2);
   2013 							break;
   2014 						case TEMPLATE_BRIDGE_3D:
   2015 							Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3F, cell2);
   2016 							break;
   2017 					}
   2018 				} else {
   2019 					if (cellptr->TType == TEMPLATE_BRIDGE_2C) {
   2020 						// Point to the template above us, x+2, y-1
   2021 						CELL cell2 = cell - (MAP_CELL_W - 2);
   2022 						switch ((*this)[cell2].TType) {
   2023 							case TEMPLATE_BRIDGE_3A:
   2024 							case TEMPLATE_BRIDGE_3B:
   2025 							case TEMPLATE_BRIDGE_3C:
   2026 								Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3D, cell2);
   2027 								break;
   2028 							case TEMPLATE_BRIDGE_3E:
   2029 								Add_Cell_Update(cell_updates, update_count, TEMPLATE_BRIDGE_3F, cell2);
   2030 								break;
   2031 						}
   2032 					}
   2033 				}
   2034 				if (cellptr->TType == TEMPLATE_BRIDGE_1C ||
   2035 					cellptr->TType == TEMPLATE_BRIDGE_2C ||
   2036 				  (cellptr->TType >= TEMPLATE_BRIDGE_3C && cellptr->TType <= TEMPLATE_BRIDGE_3E)) {
   2037 					int x, y, tdata = 0;
   2038 					for (y = 0; y < h; y++) {
   2039 						for (x = 0; x < w; x++) {
   2040 							CellClass * ptr = &(*this)[(CELL)(cell + x)];
   2041 							if (ptr->TType == cellptr->TType || ptr->Land_Type() == LAND_RIVER || ptr->Land_Type() == LAND_WATER) {
   2042 								Detach_This_From_All(As_Target((CELL)(cell+tdata)), true);
   2043 
   2044 								ObjectClass * obj = ptr->Cell_Occupier();
   2045 								while (obj != NULL) {
   2046 									ObjectClass * next = obj->Next;
   2047 									if (obj->Is_Techno()) {
   2048 										int damage = obj->Strength;
   2049 										obj->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
   2050 									}
   2051 									obj = next;
   2052 								}
   2053 
   2054 							}
   2055 							tdata++;
   2056 						}
   2057 						cell += MAP_CELL_W;
   2058 					}
   2059 					Map.Zone_Reset(MZONEF_ALL);
   2060 					destroyed = true;
   2061 				}
   2062 				Shake_The_Screen(3);
   2063 			}
   2064 		}
   2065 
   2066 		int cell_index = 0;
   2067 		char cell_name[_MAX_PATH] = { 0 };
   2068 		char icon_number[32] = { 0 };
   2069 		int icon = 0;
   2070 		void *image_data = 0;
   2071 		for (int i = 0; i < update_count; i++) {
   2072 			const TemplateTypeClass* type = cell_updates[i].Type;
   2073 			CELL cell = cell_updates[i].Cell;
   2074 			for (int y = 0; y < type->Height; y++) {
   2075 				for (int x = 0; x < type->Width; x++) {
   2076 					CELL newcell = cell + y * MAP_CELL_W + x;
   2077 					if (Map.In_Radar(newcell)) {
   2078 						CellClass * newcellptr = &Map[newcell];
   2079 						if (newcellptr->Get_Template_Info(cell_name, icon, image_data)) {
   2080 							itoa(icon, icon_number, 10);
   2081 							strncat(cell_name, "_i", 32);
   2082 							strncat(cell_name, icon_number, 32);
   2083 							strncat(cell_name, ".tga", 32);
   2084 							On_Update_Map_Cell(Cell_X(newcell), Cell_Y(newcell), cell_name);
   2085 						}
   2086 					}
   2087 				}
   2088 			}
   2089 		}
   2090 	}
   2091 	return(destroyed);
   2092 }
   2093 
   2094 
   2095 /***********************************************************************************************
   2096  * MapClass::Detach -- Remove specified object from map references.                            *
   2097  *                                                                                             *
   2098  *    This routine will take the object (represented by a target value) and remove all         *
   2099  *    references to it from the map. Typically, this is used to remove trigger reference.      *
   2100  *                                                                                             *
   2101  * INPUT:   target   -- The target object to remove from the map.                              *
   2102  *                                                                                             *
   2103  * OUTPUT:  none                                                                               *
   2104  *                                                                                             *
   2105  * WARNINGS:   none                                                                            *
   2106  *                                                                                             *
   2107  * HISTORY:                                                                                    *
   2108  *   07/28/1996 JLB : Created.                                                                 *
   2109  *=============================================================================================*/
   2110 void MapClass::Detach(TARGET target, bool)
   2111 {
   2112 	/*
   2113 	**	Remove this trigger from the map zone/line tracking list.
   2114 	*/
   2115 	if (Is_Target_Trigger(target)) {
   2116 		for (int index = 0; index < MapTriggers.Count(); index++) {
   2117 			if (MapTriggers[index] == As_Trigger(target)) {
   2118 				MapTriggers.Delete(index);
   2119 				break;
   2120 			}
   2121 		}
   2122 
   2123 		/*
   2124 		**	Loop through all cells; remove any reference to this trigger
   2125 		*/
   2126 		for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   2127 			if ((*this)[cell].Trigger == As_Trigger(target)) {
   2128 				(*this)[cell].Trigger = NULL;
   2129 			}
   2130 		}
   2131 	}
   2132 }
   2133 
   2134 
   2135 /***********************************************************************************************
   2136  * MapClass::Intact_Bridge_Count -- Determine the number of intact bridges.                    *
   2137  *                                                                                             *
   2138  *    This will examine the entire map and return the number of bridges that are intact. An    *
   2139  *    intact bridge is one that units can travel over.                                         *
   2140  *                                                                                             *
   2141  * INPUT:   none                                                                               *
   2142  *                                                                                             *
   2143  * OUTPUT:  Returns with the number of intact bridges on the map.                              *
   2144  *                                                                                             *
   2145  * WARNINGS:   none                                                                            *
   2146  *                                                                                             *
   2147  * HISTORY:                                                                                    *
   2148  *   07/28/1996 JLB : Created.                                                                 *
   2149  *=============================================================================================*/
   2150 int MapClass::Intact_Bridge_Count(void) const
   2151 {
   2152 	/*
   2153 	**	Count all non-destroyed bridges on the map.
   2154 	*/
   2155 	int count = 0;
   2156 	CellClass const * cellptr = &(*this)[(CELL)0];
   2157 	for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   2158 		switch (cellptr->TType) {
   2159 			case TEMPLATE_BRIDGE1:
   2160 			case TEMPLATE_BRIDGE1H:
   2161 			case TEMPLATE_BRIDGE2:
   2162 			case TEMPLATE_BRIDGE2H:
   2163 			case TEMPLATE_BRIDGE_1A:
   2164 			case TEMPLATE_BRIDGE_1B:
   2165 				if (cellptr->TIcon == 6) {
   2166 					count++;
   2167 				}
   2168 				break;
   2169 
   2170 			default:
   2171 				break;
   2172 		}
   2173 
   2174 		cellptr++;
   2175 	}
   2176 
   2177 	return(count);
   2178 }
   2179 
   2180 
   2181 /***********************************************************************************************
   2182  * MapClass::Pick_Random_Location -- Picks a random location on the map.                       *
   2183  *                                                                                             *
   2184  *    This routine will pick a random location on the map. It performs no legality checking    *
   2185  *    other than forcing the cell to be on the map proper.                                     *
   2186  *                                                                                             *
   2187  * INPUT:   none                                                                               *
   2188  *                                                                                             *
   2189  * OUTPUT:  Returns with a cell that is within the map.                                        *
   2190  *                                                                                             *
   2191  * WARNINGS:   none                                                                            *
   2192  *                                                                                             *
   2193  * HISTORY:                                                                                    *
   2194  *   09/25/1996 JLB : Created.                                                                 *
   2195  *=============================================================================================*/
   2196 CELL MapClass::Pick_Random_Location(void) const
   2197 {
   2198 	int x = Map.MapCellX + Random_Pick(0, Map.MapCellWidth-1);
   2199 	int y = Map.MapCellY + Random_Pick(0, Map.MapCellHeight-1);
   2200 
   2201 	return(XY_Cell(x, y));
   2202 }
   2203 
   2204 
   2205 #if (1)
   2206 
   2207 /***********************************************************************************************
   2208  * MapClass::Shroud_The_Map -- cover the whole map in darkness (usually from blackout crate)	  *
   2209  *                                                                                             *
   2210  * INPUT:   House to shroud                                                                    *
   2211  *                                                                                             *
   2212  * OUTPUT:  None
   2213  *                                                                                             *
   2214  * WARNINGS:   none                                                                            *
   2215  *                                                                                             *
   2216  * HISTORY:                                                                                    *
   2217  *   10/19/1996 BWG : Created.                                                                 *
   2218  *   08/12/2019  ST : Updated for client/server multiplayer                                    *
   2219  *=============================================================================================*/
   2220 void MapClass::Shroud_The_Map(HouseClass *house)
   2221 {
   2222 	for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   2223 		CellClass * cellptr = &Map[cell];
   2224 		if (cellptr->Is_Mapped(house) || cellptr->Is_Visible(house)) {
   2225 			
   2226 			cellptr->Redraw_Objects();
   2227 			
   2228 			/*
   2229 			** BG: remove "ring of darkness" around edge of map.
   2230 			*/
   2231 			int x = Cell_X(cell);
   2232 			int y = Cell_Y(cell);
   2233 			if (x >= Map.MapCellX && x < (Map.MapCellX + Map.MapCellWidth) &&
   2234 				y >= Map.MapCellY && y < (Map.MapCellY + Map.MapCellHeight)) {
   2235 				cellptr->Set_Mapped(house, false);
   2236 				cellptr->Set_Visible(house, false);
   2237 			}
   2238 		}
   2239 	}
   2240 	for (int obj_index = 0; obj_index < DisplayClass::Layer[LAYER_GROUND].Count(); obj_index++) {
   2241 		ObjectClass * layer_object = DisplayClass::Layer[LAYER_GROUND][obj_index];
   2242 		if (layer_object && layer_object->Is_Techno() && ((TechnoClass *)layer_object)->House == house) {
   2243 			layer_object->Look();
   2244 		}
   2245 	}
   2246 	Flag_To_Redraw(true);
   2247 }
   2248 
   2249 
   2250 #else
   2251 
   2252 //
   2253 // Old code for posterity. ST - 8/12/2019 11:34AM
   2254 //
   2255 
   2256 /***********************************************************************************************
   2257  * MapClass::Shroud_The_Map -- cover the whole map in darkness (usually from blackout crate)	  *
   2258  *                                                                                             *
   2259  * INPUT:   none                                                                               *
   2260  *                                                                                             *
   2261  * OUTPUT:  Returns with a cell that is within the map.                                        *
   2262  *                                                                                             *
   2263  * WARNINGS:   none                                                                            *
   2264  *                                                                                             *
   2265  * HISTORY:                                                                                    *
   2266  *   10/19/1996 BWG : Created.                                                                 *
   2267  *=============================================================================================*/
   2268 void MapClass::Shroud_The_Map(void)
   2269 {
   2270 	for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   2271 		CellClass * cellptr = &Map[cell];
   2272 		if (cellptr->IsMapped || cellptr->IsVisible) {
   2273 			cellptr->Redraw_Objects();
   2274 			/*
   2275 			** BG: remove "ring of darkness" around edge of map.
   2276 			*/
   2277 			int x = Cell_X(cell);
   2278 			int y = Cell_Y(cell);
   2279 			if (x >= Map.MapCellX && x < (Map.MapCellX + Map.MapCellWidth) &&
   2280 				y >= Map.MapCellY && y < (Map.MapCellY + Map.MapCellHeight)) {
   2281 				cellptr->IsMapped = false;
   2282 				cellptr->IsVisible = false;
   2283 			}
   2284 		}
   2285 	}
   2286 	for (int obj_index = 0; obj_index < DisplayClass::Layer[LAYER_GROUND].Count(); obj_index++) {
   2287 		ObjectClass * layer_object = DisplayClass::Layer[LAYER_GROUND][obj_index];
   2288 		if (layer_object && layer_object->Is_Techno() && ((TechnoClass *)layer_object)->House == PlayerPtr) {
   2289 			layer_object->Look();
   2290 		}
   2291 	}
   2292 	Flag_To_Redraw(true);
   2293 }
   2294 #endif