CnC_Remastered_Collection

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

HOUSE.CPP (344526B)


      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/HOUSE.CPP 4     3/13/97 7:11p Steve_tall $ */
     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 : HOUSE.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : May 21, 1994                                                 *
     28  *                                                                                             *
     29  *                  Last Update : November 4, 1996 [JLB]                                       *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   HouseClass::AI -- Process house logic.                                                    *
     34  *   HouseClass::AI_Aircraft -- Determines what aircraft to build next.                        *
     35  *   HouseClass::AI_Attack -- Handles offensive attack logic.                                  *
     36  *   HouseClass::AI_Base_Defense -- Handles maintaining a strong base defense.                 *
     37  *   HouseClass::AI_Building -- Determines what building to build.                             *
     38  *   HouseClass::AI_Fire_Sale -- Check for and perform a fire sale.                            *
     39  *   HouseClass::AI_Infantry -- Determines the infantry unit to build.                         *
     40  *   HouseClass::AI_Money_Check -- Handles money production logic.                             *
     41  *   HouseClass::AI_Power_Check -- Handle the power situation.                                 *
     42  *   HouseClass::AI_Unit -- Determines what unit to build next.                                *
     43  *   HouseClass::Abandon_Production -- Abandons production of item type specified.             *
     44  *   HouseClass::Active_Add -- Add an object to active duty for this house.                    *
     45  *   HouseClass::Active_Remove -- Remove this object from active duty for this house.          *
     46  *   HouseClass::Adjust_Capacity -- Adjusts the house Tiberium storage capacity.               *
     47  *   HouseClass::Adjust_Drain -- Adjust the power drain value of the house.                    *
     48  *   HouseClass::Adjust_Power -- Adjust the power value of the house.                          *
     49  *   HouseClass::Adjust_Threat -- Adjust threat for the region specified.                      *
     50  *   HouseClass::As_Pointer -- Converts a house number into a house object pointer.            *
     51  *   HouseClass::Assign_Handicap -- Assigns the specified handicap rating to the house.        *
     52  *   HouseClass::Attacked -- Lets player know if base is under attack.                         *
     53  *   HouseClass::Available_Money -- Fetches the total credit worth of the house.               *
     54  *   HouseClass::Begin_Production -- Starts production of the specified object type.           *
     55  *   HouseClass::Blowup_All -- blows up everything                                             *
     56  *   HouseClass::Can_Build -- General purpose build legality checker.                          *
     57  *   HouseClass::Clobber_All -- removes all objects for this house                             *
     58  *   HouseClass::Computer_Paranoid -- Cause the computer players to becom paranoid.            *
     59  *   HouseClass::Debug_Dump -- Dumps the house status data to the mono screen.                 *
     60  *   HouseClass::Detach -- Removes specified object from house tracking systems.               *
     61  *   HouseClass::Do_All_To_Hunt -- Send all units to hunt.                                     *
     62  *   HouseClass::Does_Enemy_Building_Exist -- Checks for enemy building of specified type.     *
     63  *   HouseClass::Expert_AI -- Handles expert AI processing.                                    *
     64  *   HouseClass::Factory_Count -- Fetches the number of factories for specified type.          *
     65  *   HouseClass::Factory_Counter -- Fetches a pointer to the factory counter value.            *
     66  *   HouseClass::Fetch_Factory -- Finds the factory associated with the object type specified. *
     67  *   HouseClass::Find_Build_Location -- Finds a suitable building location.                    *
     68  *   HouseClass::Find_Building -- Finds a building of specified type.                          *
     69  *   HouseClass::Find_Cell_In_Zone -- Finds a legal placement cell within the zone.            *
     70  *   HouseClass::Find_Juicy_Target -- Finds a suitable field target.                           *
     71  *   HouseClass::Fire_Sale -- Cause all buildings to be sold.                                  *
     72  *   HouseClass::Flag_Attach -- Attach flag to specified cell (or thereabouts).                *
     73  *   HouseClass::Flag_Attach -- Attaches the house flag the specified unit.                    *
     74  *   HouseClass::Flag_Remove -- Removes the flag from the specified target.                    *
     75  *   HouseClass::Flag_To_Die -- Flags the house to blow up soon.                               *
     76  *   HouseClass::Flag_To_Lose -- Flags the house to die soon.                                  *
     77  *   HouseClass::Flag_To_Win -- Flags the house to win soon.                                   *
     78  *   HouseClass::Get_Quantity -- Fetches the total number of aircraft of the specified type.   *
     79  *   HouseClass::Get_Quantity -- Gets the quantity of the building type specified.             *
     80  *   HouseClass::Harvested -- Adds Tiberium to the harvest storage.                            *
     81  *   HouseClass::HouseClass -- Constructor for a house object.                                 *
     82  *   HouseClass::Init -- init's in preparation for new scenario                                *
     83  *   HouseClass::Init_Data -- Initializes the multiplayer color data.                          *
     84  *   HouseClass::Is_Allowed_To_Ally -- Determines if this house is allied to make allies.      *
     85  *   HouseClass::Is_Ally -- Checks to see if the object is an ally.                            *
     86  *   HouseClass::Is_Ally -- Determines if the specified house is an ally.                      *
     87  *   HouseClass::Is_Hack_Prevented -- Is production of the specified type and id prohibted?    *
     88  *   HouseClass::Is_No_YakMig -- Determines if no more yaks or migs should be allowed.         *
     89  *   HouseClass::MPlayer_Defeated -- multiplayer; house is defeated                            *
     90  *   HouseClass::Make_Ally -- Make the specified house an ally.                                *
     91  *   HouseClass::Make_Enemy -- Make an enemy of the house specified.                           *
     92  *   HouseClass::Manual_Place -- Inform display system of building placement mode.             *
     93  *   HouseClass::One_Time -- Handles one time initialization of the house array.               *
     94  *   HouseClass::Place_Object -- Places the object (building) at location specified.           *
     95  *   HouseClass::Place_Special_Blast -- Place a special blast effect at location specified.    *
     96  *   HouseClass::Power_Fraction -- Fetches the current power output rating.                    *
     97  *   HouseClass::Production_Begun -- Records that production has begun.                        *
     98  *   HouseClass::Read_INI -- Reads house specific data from INI.                               *
     99  *   HouseClass::Recalc_Attributes -- Recalcs all houses existence bits.                       *
    100  *   HouseClass::Recalc_Center -- Recalculates the center point of the base.                   *
    101  *   HouseClass::Refund_Money -- Refunds money to back to the house.                           *
    102  *   HouseClass::Remap_Table -- Fetches the remap table for this house object.                 *
    103  *   HouseClass::Sell_Wall -- Tries to sell the wall at the specified location.                *
    104  *   HouseClass::Set_Factory -- Assign specified factory to house tracking.                    *
    105  *   HouseClass::Silo_Redraw_Check -- Flags silos to be redrawn if necessary.                  *
    106  *   HouseClass::Special_Weapon_AI -- Fires special weapon.                                    *
    107  *   HouseClass::Spend_Money -- Removes money from the house.                                  *
    108  *   HouseClass::Suggest_New_Building -- Examines the situation and suggests a building.       *
    109  *   HouseClass::Suggest_New_Object -- Determine what would the next buildable object be.      *
    110  *   HouseClass::Suggested_New_Team -- Determine what team should be created.                  *
    111  *   HouseClass::Super_Weapon_Handler -- Handles the super weapon charge and discharge logic.  *
    112  *   HouseClass::Suspend_Production -- Temporarily puts production on hold.                    *
    113  *   HouseClass::Tally_Score -- Fills in the score system for this round                       *
    114  *   HouseClass::Tiberium_Fraction -- Calculates the tiberium fraction of capacity.            *
    115  *   HouseClass::Tracking_Add -- Informs house of new inventory item.                          *
    116  *   HouseClass::Tracking_Remove -- Remove object from house tracking system.                  *
    117  *   HouseClass::Where_To_Go -- Determines where the object should go and wait.                *
    118  *   HouseClass::Which_Zone -- Determines what zone a coordinate lies in.                      *
    119  *   HouseClass::Which_Zone -- Determines which base zone the specified cell lies in.          *
    120  *   HouseClass::Which_Zone -- Determines which base zone the specified object lies in.        *
    121  *   HouseClass::Write_INI -- Writes the house data to the INI database.                       *
    122  *   HouseClass::Zone_Cell -- Finds the cell closest to the center of the zone.                *
    123  *   HouseClass::delete -- Deallocator function for a house object.                            *
    124  *   HouseClass::new -- Allocator for a house class.                                           *
    125  *   HouseClass::operator HousesType -- Conversion to HousesType operator.                     *
    126  *   HouseClass::~HouseClass -- Default destructor for a house object.                         *
    127  *   HouseStaticClass::HouseStaticClass -- Default constructor for house static class.         *
    128  *   HouseClass::AI_Raise_Power -- Try to raise power levels by selling off buildings.         *
    129  *   HouseClass::AI_Raise_Money -- Raise emergency cash by selling buildings.                  *
    130  *   HouseClass::Random_Cell_In_Zone -- Find a (technically) legal cell in the zone specified. *
    131  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    132 
    133 #include	"function.h"
    134 #include	"vortex.h"
    135 
    136 //#include "WolDebug.h"
    137 
    138 /*
    139 ** New sidebar for GlyphX multiplayer. ST - 8/7/2019 10:10AM
    140 */
    141 #include "SidebarGlyphx.h"
    142 
    143 TFixedIHeapClass<HouseClass::BuildChoiceClass> HouseClass::BuildChoice;
    144 
    145 int TFixedIHeapClass<HouseClass::BuildChoiceClass>::Save(Pipe &) const
    146 {
    147 	return(true);
    148 }
    149 
    150 int TFixedIHeapClass<HouseClass::BuildChoiceClass>::Load(Straw &)
    151 {
    152 	return(0);
    153 }
    154 
    155 void TFixedIHeapClass<HouseClass::BuildChoiceClass>::Code_Pointers(void)
    156 {
    157 }
    158 
    159 void TFixedIHeapClass<HouseClass::BuildChoiceClass>::Decode_Pointers(void)
    160 {
    161 }
    162 
    163 extern bool RedrawOptionsMenu;
    164 
    165 /***********************************************************************************************
    166  * HouseClass::operator HousesType -- Conversion to HousesType operator.                       *
    167  *                                                                                             *
    168  *    This operator will automatically convert from a houses class object into the HousesType  *
    169  *    enumerated value.                                                                        *
    170  *                                                                                             *
    171  * INPUT:   none                                                                               *
    172  *                                                                                             *
    173  * OUTPUT:  Returns with the object's HousesType value.                                        *
    174  *                                                                                             *
    175  * WARNINGS:   none                                                                            *
    176  *                                                                                             *
    177  * HISTORY:                                                                                    *
    178  *   01/23/1995 JLB : Created.                                                                 *
    179  *=============================================================================================*/
    180 HouseClass::operator HousesType(void) const
    181 {
    182 	assert(Houses.ID(this) == ID);
    183 
    184 	return(Class->House);
    185 }
    186 
    187 
    188 /***********************************************************************************************
    189  * HouseClass::Tiberium_Fraction -- Calculates the tiberium fraction of capacity.              *
    190  *                                                                                             *
    191  *    This will calculate the current tiberium (gold) load as a ratio of the maximum storage   *
    192  *    capacity.                                                                                *
    193  *                                                                                             *
    194  * INPUT:   none                                                                               *
    195  *                                                                                             *
    196  * OUTPUT:  Returns the current tiberium storage situation as a ratio of load over capacity.   *
    197  *                                                                                             *
    198  * WARNINGS:   none                                                                            *
    199  *                                                                                             *
    200  * HISTORY:                                                                                    *
    201  *   07/31/1996 JLB : Created.                                                                 *
    202  *=============================================================================================*/
    203 fixed HouseClass::Tiberium_Fraction(void) const
    204 {
    205 	if (Tiberium == 0) {
    206 		return(0);
    207 	}
    208 	return(fixed(Tiberium, Capacity));
    209 }
    210 
    211 
    212 /***********************************************************************************************
    213  * HouseClass::As_Pointer -- Converts a house number into a house object pointer.              *
    214  *                                                                                             *
    215  *    Use this routine to convert a house number into the house pointer that it represents.    *
    216  *    A simple index into the Houses template array is not sufficient, since the array order   *
    217  *    is arbitrary. An actual scan through the house object is required in order to find the   *
    218  *    house object desired.                                                                    *
    219  *                                                                                             *
    220  * INPUT:   house -- The house type number to look up.                                         *
    221  *                                                                                             *
    222  * OUTPUT:  Returns with a pointer to the house object that the house number represents.       *
    223  *                                                                                             *
    224  * WARNINGS:   none                                                                            *
    225  *                                                                                             *
    226  * HISTORY:                                                                                    *
    227  *   01/23/1995 JLB : Created.                                                                 *
    228  *=============================================================================================*/
    229 HouseClass * HouseClass::As_Pointer(HousesType house)
    230 {
    231 	if (house != HOUSE_NONE) {
    232 		for (int index = 0; index < Houses.Count(); index++) {
    233 			if (Houses.Ptr(index)->Class->House == house) {
    234 				return(Houses.Ptr(index));
    235 			}
    236 		}
    237 	}
    238 	return(0);
    239 }
    240 
    241 
    242 /***********************************************************************************************
    243  * HouseClass::One_Time -- Handles one time initialization of the house array.                 *
    244  *                                                                                             *
    245  *    This basically calls the constructor for each of the houses in the game. All other       *
    246  *    data specific to the house is initialized when the scenario is loaded.                   *
    247  *                                                                                             *
    248  * INPUT:   none                                                                               *
    249  *                                                                                             *
    250  * OUTPUT:  none                                                                               *
    251  *                                                                                             *
    252  * WARNINGS:   Only call this ONCE at the beginning of the game.                               *
    253  *                                                                                             *
    254  * HISTORY:                                                                                    *
    255  *   12/09/1994 JLB : Created.                                                                 *
    256  *=============================================================================================*/
    257 void HouseClass::One_Time(void)
    258 {
    259 	BuildChoice.Set_Heap(STRUCT_COUNT);
    260 }
    261 
    262 
    263 /***********************************************************************************************
    264  * HouseClass::Assign_Handicap -- Assigns the specified handicap rating to the house.          *
    265  *                                                                                             *
    266  *    The handicap rating will affect combat, movement, and production for the house. It can   *
    267  *    either make it more or less difficult for the house (controlled by the handicap value).  *
    268  *                                                                                             *
    269  * INPUT:   handicap -- The handicap value to assign to this house. The default value for      *
    270  *                      a house is DIFF_NORMAL.                                                *
    271  *                                                                                             *
    272  * OUTPUT:  Returns with the old handicap value.                                               *
    273  *                                                                                             *
    274  * WARNINGS:   none                                                                            *
    275  *                                                                                             *
    276  * HISTORY:                                                                                    *
    277  *   07/09/1996 JLB : Created.                                                                 *
    278  *   10/22/1996 JLB : Uses act like value for multiplay only.                                  *
    279  *=============================================================================================*/
    280 DiffType HouseClass::Assign_Handicap(DiffType handicap)
    281 {
    282 	DiffType old = Difficulty;
    283 	Difficulty = handicap;
    284 
    285 	if (Session.Type != GAME_NORMAL) {
    286 		HouseTypeClass const * hptr = &HouseTypeClass::As_Reference(ActLike);
    287 		FirepowerBias = hptr->FirepowerBias * Rule.Diff[handicap].FirepowerBias;
    288 		GroundspeedBias = hptr->GroundspeedBias * Rule.Diff[handicap].GroundspeedBias * Rule.GameSpeedBias;
    289 		AirspeedBias = hptr->AirspeedBias * Rule.Diff[handicap].AirspeedBias * Rule.GameSpeedBias;
    290 		ArmorBias = hptr->ArmorBias * Rule.Diff[handicap].ArmorBias;
    291 		ROFBias = hptr->ROFBias * Rule.Diff[handicap].ROFBias;
    292 		CostBias = hptr->CostBias * Rule.Diff[handicap].CostBias;
    293 		RepairDelay = Rule.Diff[handicap].RepairDelay;
    294 		BuildDelay = Rule.Diff[handicap].BuildDelay;
    295 		BuildSpeedBias = hptr->BuildSpeedBias * Rule.Diff[handicap].BuildSpeedBias * Rule.GameSpeedBias;
    296 	} else {
    297 		FirepowerBias = Rule.Diff[handicap].FirepowerBias;
    298 		GroundspeedBias = Rule.Diff[handicap].GroundspeedBias * Rule.GameSpeedBias;
    299 		AirspeedBias = Rule.Diff[handicap].AirspeedBias * Rule.GameSpeedBias;
    300 		ArmorBias = Rule.Diff[handicap].ArmorBias;
    301 		ROFBias = Rule.Diff[handicap].ROFBias;
    302 		CostBias = Rule.Diff[handicap].CostBias;
    303 		RepairDelay = Rule.Diff[handicap].RepairDelay;
    304 		BuildDelay = Rule.Diff[handicap].BuildDelay;
    305 		BuildSpeedBias = Rule.Diff[handicap].BuildSpeedBias * Rule.GameSpeedBias;
    306 	}
    307 
    308 	return(old);
    309 }
    310 
    311 
    312 
    313 #ifdef CHEAT_KEYS
    314 
    315 void HouseClass::Print_Zone_Stats(int x, int y, ZoneType zone, MonoClass * mono) const
    316 {
    317 	mono->Set_Cursor(x, y);
    318 	mono->Printf("A:%-5d I:%-5d V:%-5d", ZoneInfo[zone].AirDefense, ZoneInfo[zone].InfantryDefense, ZoneInfo[zone].ArmorDefense);
    319 }
    320 
    321 
    322 /***********************************************************************************************
    323  * HouseClass::Debug_Dump -- Dumps the house status data to the mono screen.                   *
    324  *                                                                                             *
    325  *    This utility function will output the current status of the house class to the mono      *
    326  *    screen. Through this information bugs may be fixed or detected.                          *
    327  *                                                                                             *
    328  * INPUT:   none                                                                               *
    329  *                                                                                             *
    330  * OUTPUT:  none                                                                               *
    331  *                                                                                             *
    332  * WARNINGS:   none                                                                            *
    333  *                                                                                             *
    334  * HISTORY:                                                                                    *
    335  *   05/31/1994 JLB : Created.                                                                 *
    336  *=============================================================================================*/
    337 void HouseClass::Debug_Dump(MonoClass * mono) const
    338 {
    339 	mono->Set_Cursor(0, 0);
    340 	mono->Print(Text_String(TXT_DEBUG_HOUSE));
    341 
    342 	mono->Set_Cursor(1, 1);mono->Printf("[%d]%14.14s", Class->House, Name());
    343 	mono->Set_Cursor(20, 1);mono->Printf("[%d]%13.13s", ActLike, HouseTypeClass::As_Reference(ActLike).Name());
    344 	mono->Set_Cursor(39, 1);mono->Printf("%2d", Control.TechLevel);
    345 	mono->Set_Cursor(45, 1);mono->Printf("%2d", Difficulty);
    346 	mono->Set_Cursor(52, 1);mono->Printf("%2d", State);
    347 	mono->Set_Cursor(58, 1);mono->Printf("%2d", Blockage);
    348 	mono->Set_Cursor(65, 1);mono->Printf("%2d", IQ);
    349 	mono->Set_Cursor(72, 1);mono->Printf("%5d", (long)RepairTimer);
    350 
    351 	mono->Set_Cursor(1, 3);mono->Printf("%08X", AScan);
    352 	mono->Set_Cursor(10, 3);mono->Printf("%8.8s", (BuildAircraft == AIRCRAFT_NONE) ? " " : AircraftTypeClass::As_Reference(BuildAircraft).Graphic_Name());
    353 	mono->Set_Cursor(21, 3);mono->Printf("%3d", CurAircraft);
    354 	mono->Set_Cursor(27, 3);mono->Printf("%8d", Credits);
    355 	mono->Set_Cursor(37, 3);mono->Printf("%5d", Power);
    356 	mono->Set_Cursor(45, 3);mono->Printf("%04X", RadarSpied);
    357 	mono->Set_Cursor(52, 3);mono->Printf("%5d", PointTotal);
    358 	mono->Set_Cursor(62, 3);mono->Printf("%5d", (long)TeamTime);
    359 	mono->Set_Cursor(71, 3);mono->Printf("%5d", (long)AlertTime);
    360 
    361 	mono->Set_Cursor(1, 5);mono->Printf("%08X", BScan);
    362 	mono->Set_Cursor(10, 5);mono->Printf("%8.8s", (BuildStructure == STRUCT_NONE) ? " " : BuildingTypeClass::As_Reference(BuildStructure).Graphic_Name());
    363 	mono->Set_Cursor(21, 5);mono->Printf("%3d", CurBuildings);
    364 	mono->Set_Cursor(27, 5);mono->Printf("%8d", Tiberium);
    365 	mono->Set_Cursor(37, 5);mono->Printf("%5d", Drain);
    366 	mono->Set_Cursor(44, 5);mono->Printf("%16.16s", QuarryName[PreferredTarget]);
    367 	mono->Set_Cursor(62, 5);mono->Printf("%5d", (long)TriggerTime);
    368 	mono->Set_Cursor(71, 5);mono->Printf("%5d", (long)BorrowedTime);
    369 
    370 	mono->Set_Cursor(1, 7);mono->Printf("%08X", UScan);
    371 	mono->Set_Cursor(10, 7);mono->Printf("%8.8s", (BuildUnit == UNIT_NONE) ? " " : UnitTypeClass::As_Reference(BuildUnit).Graphic_Name());
    372 	mono->Set_Cursor(21, 7);mono->Printf("%3d", CurUnits);
    373 	mono->Set_Cursor(27, 7);mono->Printf("%8d", Control.InitialCredits);
    374 	mono->Set_Cursor(38, 7);mono->Printf("%5d", UnitsLost);
    375 	mono->Set_Cursor(44, 7);mono->Printf("%08X", Allies);
    376 	mono->Set_Cursor(71, 7);mono->Printf("%5d", (long)Attack);
    377 
    378 	mono->Set_Cursor(1, 9);mono->Printf("%08X", IScan);
    379 	mono->Set_Cursor(10, 9);mono->Printf("%8.8s", (BuildInfantry == INFANTRY_NONE) ? " " : InfantryTypeClass::As_Reference(BuildInfantry).Graphic_Name());
    380 	mono->Set_Cursor(21, 9);mono->Printf("%3d", CurInfantry);
    381 	mono->Set_Cursor(27, 9);mono->Printf("%8d", Capacity);
    382 	mono->Set_Cursor(38, 9);mono->Printf("%5d", BuildingsLost);
    383 	mono->Set_Cursor(45, 9);mono->Printf("%4d", Radius / CELL_LEPTON_W);
    384 	mono->Set_Cursor(71, 9);mono->Printf("%5d", (long)AITimer);
    385 
    386 	mono->Set_Cursor(1, 11);mono->Printf("%08X", VScan);
    387 	mono->Set_Cursor(10, 11);mono->Printf("%8.8s", (BuildVessel == VESSEL_NONE) ? " " : VesselTypeClass::As_Reference(BuildVessel).Graphic_Name());
    388 	mono->Set_Cursor(21, 11);mono->Printf("%3d", CurVessels);
    389 	mono->Set_Cursor(54, 11);mono->Printf("%04X", Coord_Cell(Center));
    390 	mono->Set_Cursor(71, 11);mono->Printf("%5d", (long)DamageTime);
    391 
    392 
    393 	for (int index = 0; index < ARRAY_SIZE(Scen.GlobalFlags); index++) {
    394 		mono->Set_Cursor(1+index, 15);
    395 		if (Scen.GlobalFlags[index] != 0) {
    396 			mono->Print("1");
    397 		} else {
    398 			mono->Print("0");
    399 		}
    400 		if (index >= 24) break;
    401 	}
    402 	if (Enemy != HOUSE_NONE) {
    403 		char const * name = "";
    404 		name = HouseClass::As_Pointer(Enemy)->Name();
    405 		mono->Set_Cursor(53, 15);mono->Printf("[%d]%21.21s", Enemy, HouseTypeClass::As_Reference(Enemy).Name());
    406 	}
    407 
    408 	Print_Zone_Stats(27, 11, ZONE_NORTH, mono);
    409 	Print_Zone_Stats(27, 13, ZONE_CORE, mono);
    410 	Print_Zone_Stats(27, 15, ZONE_SOUTH, mono);
    411 	Print_Zone_Stats(1, 13, ZONE_WEST, mono);
    412 	Print_Zone_Stats(53, 13, ZONE_EAST, mono);
    413 
    414 	mono->Fill_Attrib(1, 17, 12, 1, IsActive ? MonoClass::INVERSE : MonoClass::NORMAL);
    415 	mono->Fill_Attrib(1, 18, 12, 1, IsHuman ? MonoClass::INVERSE : MonoClass::NORMAL);
    416 	mono->Fill_Attrib(1, 19, 12, 1, IsPlayerControl ? MonoClass::INVERSE : MonoClass::NORMAL);
    417 	mono->Fill_Attrib(1, 20, 12, 1, IsAlerted ? MonoClass::INVERSE : MonoClass::NORMAL);
    418 	mono->Fill_Attrib(1, 21, 12, 1, IsDiscovered ? MonoClass::INVERSE : MonoClass::NORMAL);
    419 	mono->Fill_Attrib(1, 22, 12, 1, IsMaxedOut ? MonoClass::INVERSE : MonoClass::NORMAL);
    420 
    421 	mono->Fill_Attrib(14, 17, 12, 1, IsDefeated ? MonoClass::INVERSE : MonoClass::NORMAL);
    422 	mono->Fill_Attrib(14, 18, 12, 1, IsToDie ? MonoClass::INVERSE : MonoClass::NORMAL);
    423 	mono->Fill_Attrib(14, 19, 12, 1, IsToWin ? MonoClass::INVERSE : MonoClass::NORMAL);
    424 	mono->Fill_Attrib(14, 20, 12, 1, IsToLose ? MonoClass::INVERSE : MonoClass::NORMAL);
    425 	mono->Fill_Attrib(14, 21, 12, 1, IsCivEvacuated ? MonoClass::INVERSE : MonoClass::NORMAL);
    426 	mono->Fill_Attrib(14, 22, 12, 1, IsRecalcNeeded ? MonoClass::INVERSE : MonoClass::NORMAL);
    427 
    428 	mono->Fill_Attrib(27, 17, 12, 1, IsVisionary ? MonoClass::INVERSE : MonoClass::NORMAL);
    429 	mono->Fill_Attrib(27, 18, 12, 1, IsTiberiumShort ? MonoClass::INVERSE : MonoClass::NORMAL);
    430 	mono->Fill_Attrib(27, 19, 12, 1, IsSpied ? MonoClass::INVERSE : MonoClass::NORMAL);
    431 	mono->Fill_Attrib(27, 20, 12, 1, IsThieved ? MonoClass::INVERSE : MonoClass::NORMAL);
    432 	mono->Fill_Attrib(27, 21, 12, 1, IsGPSActive ? MonoClass::INVERSE : MonoClass::NORMAL);
    433 	mono->Fill_Attrib(27, 22, 12, 1, IsStarted ? MonoClass::INVERSE : MonoClass::NORMAL);
    434 
    435 	mono->Fill_Attrib(40, 17, 12, 1, IsResigner ? MonoClass::INVERSE : MonoClass::NORMAL);
    436 	mono->Fill_Attrib(40, 18, 12, 1, IsGiverUpper ? MonoClass::INVERSE : MonoClass::NORMAL);
    437 	mono->Fill_Attrib(40, 19, 12, 1, IsBuiltSomething ? MonoClass::INVERSE : MonoClass::NORMAL);
    438 	mono->Fill_Attrib(40, 20, 12, 1, IsBaseBuilding ? MonoClass::INVERSE : MonoClass::NORMAL);
    439 }
    440 #endif
    441 
    442 
    443 /***********************************************************************************************
    444  * HouseClass::new -- Allocator for a house class.                                             *
    445  *                                                                                             *
    446  *    This is the allocator for a house class. Since there can be only                         *
    447  *    one of each type of house, this is allocator has restricted                              *
    448  *    functionality. Any attempt to allocate a house structure for a                           *
    449  *    house that already exists, just returns a pointer to the previously                      *
    450  *    allocated house.                                                                         *
    451  *                                                                                             *
    452  * INPUT:   house -- The house to allocate a class object for.                                 *
    453  *                                                                                             *
    454  * OUTPUT:  Returns with a pointer to the allocated class object.                              *
    455  *                                                                                             *
    456  * WARNINGS:   none                                                                            *
    457  *                                                                                             *
    458  * HISTORY:                                                                                    *
    459  *   05/22/1994 JLB : Created.                                                                 *
    460  *=============================================================================================*/
    461 void * HouseClass::operator new(size_t)
    462 {
    463 	void * ptr = Houses.Allocate();
    464 	if (ptr) {
    465 		((HouseClass *)ptr)->IsActive = true;
    466 	}
    467 	return(ptr);
    468 }
    469 
    470 
    471 /***********************************************************************************************
    472  * HouseClass::delete -- Deallocator function for a house object.                              *
    473  *                                                                                             *
    474  *    This function marks the house object as "deallocated". Such a                            *
    475  *    house object is available for reallocation later.                                        *
    476  *                                                                                             *
    477  * INPUT:   ptr   -- Pointer to the house object to deallocate.                                *
    478  *                                                                                             *
    479  * OUTPUT:  none                                                                               *
    480  *                                                                                             *
    481  * WARNINGS:   none                                                                            *
    482  *                                                                                             *
    483  * HISTORY:                                                                                    *
    484  *   05/22/1994 JLB : Created.                                                                 *
    485  *=============================================================================================*/
    486 void HouseClass::operator delete(void * ptr)
    487 {
    488 	if (ptr) {
    489 		((HouseClass *)ptr)->IsActive = false;
    490 	}
    491 	Houses.Free((HouseClass *)ptr);
    492 }
    493 
    494 
    495 /***********************************************************************************************
    496  * HouseClass::HouseClass -- Constructor for a house object.                                   *
    497  *                                                                                             *
    498  *    This function is the constructor and it marks the house object                           *
    499  *    as being allocated.                                                                      *
    500  *                                                                                             *
    501  * INPUT:   none                                                                               *
    502  *                                                                                             *
    503  * OUTPUT:  none                                                                               *
    504  *                                                                                             *
    505  * WARNINGS:   none                                                                            *
    506  *                                                                                             *
    507  * HISTORY:                                                                                    *
    508  *   05/22/1994 JLB : Created.                                                                 *
    509  *=============================================================================================*/
    510 #define 	VOX_NOT_READY	VOX_NONE
    511 HouseClass::HouseClass(HousesType house) :
    512 	RTTI(RTTI_HOUSE),
    513 	ID(Houses.ID(this)),
    514 	Class(HouseTypes.Ptr(house)),
    515 	Difficulty(Scen.CDifficulty),
    516 	FirepowerBias(1),
    517 	GroundspeedBias(1),
    518 	AirspeedBias(1),
    519 	ArmorBias(1),
    520 	ROFBias(1),
    521 	CostBias(1),
    522 	BuildSpeedBias(1),
    523 	RepairDelay(0),
    524 	BuildDelay(0),
    525 	ActLike(Class->House),
    526 	IsHuman(false),
    527 	WasHuman(false),
    528 	IsPlayerControl(false),
    529 	IsStarted(false),
    530 	IsAlerted(false),
    531 	IsBaseBuilding(false),
    532 	IsDiscovered(false),
    533 	IsMaxedOut(false),
    534 	IsDefeated(false),
    535 	IsToDie(false),
    536 	IsToLose(false),
    537 	IsToWin(false),
    538 	IsCivEvacuated(false),
    539 	IsRecalcNeeded(true),
    540 	IsVisionary(false),
    541 	IsTiberiumShort(false),
    542 	IsSpied(false),
    543 	IsThieved(false),
    544 	IsGPSActive(false),
    545 	IsBuiltSomething(false),
    546 	IsResigner(false),
    547 	IsGiverUpper(false),
    548 	IsParanoid(false),
    549 	IsToLook(true),
    550 	IsQueuedMovementToggle(false),
    551 	DidRepair(false),
    552 	IQ(Control.IQ),
    553 	State(STATE_BUILDUP),
    554 	JustBuiltStructure(STRUCT_NONE),
    555 	JustBuiltInfantry(INFANTRY_NONE),
    556 	JustBuiltUnit(UNIT_NONE),
    557 	JustBuiltAircraft(AIRCRAFT_NONE),
    558 	JustBuiltVessel(VESSEL_NONE),
    559 	Blockage(0),
    560 	RepairTimer(0),
    561 	AlertTime(0),
    562 	BorrowedTime(0),
    563 	BScan(0),
    564 	ActiveBScan(0),
    565 	OldBScan(0),
    566 	UScan(0),
    567 	ActiveUScan(0),
    568 	OldUScan(0),
    569 	IScan(0),
    570 	ActiveIScan(0),
    571 	OldIScan(0),
    572 	AScan(0),
    573 	ActiveAScan(0),
    574 	OldAScan(0),
    575 	VScan(0),
    576 	ActiveVScan(0),
    577 	OldVScan(0),
    578 	CreditsSpent(0),
    579 	HarvestedCredits(0),
    580 	StolenBuildingsCredits(0),
    581 	CurUnits(0),
    582 	CurBuildings(0),
    583 	CurInfantry(0),
    584 	CurVessels(0),
    585 	CurAircraft(0),
    586 	Tiberium(0),
    587 	Credits(0),
    588 	Capacity(0),
    589 	AircraftTotals(NULL),
    590 	InfantryTotals(NULL),
    591 	UnitTotals(NULL),
    592 	BuildingTotals(NULL),
    593 	VesselTotals(NULL),
    594 	DestroyedAircraft(NULL),
    595 	DestroyedInfantry(NULL),
    596 	DestroyedUnits(NULL),
    597 	DestroyedBuildings(NULL),
    598 	DestroyedVessels(NULL),
    599 	CapturedBuildings(NULL),
    600 	TotalCrates(NULL),
    601 	AircraftFactories(0),
    602 	InfantryFactories(0),
    603 	UnitFactories(0),
    604 	BuildingFactories(0),
    605 	VesselFactories(0),
    606 	Power(0),
    607 	Drain(0),
    608 	AircraftFactory(-1),
    609 	InfantryFactory(-1),
    610 	UnitFactory(-1),
    611 	BuildingFactory(-1),
    612 	VesselFactory(-1),
    613 	Radar(RADAR_NONE),
    614 	FlagLocation(TARGET_NONE),
    615 	FlagHome(0),
    616 	UnitsLost(0),
    617 	BuildingsLost(0),
    618 	WhoLastHurtMe(house),
    619 	StartLocationOverride(-1),
    620 	Center(0),
    621 	Radius(0),
    622 	LATime(0),
    623 	LAType(RTTI_NONE),
    624 	LAZone(ZONE_NONE),
    625 	LAEnemy(HOUSE_NONE),
    626 	ToCapture(TARGET_NONE),
    627 	RadarSpied(0),
    628 	PointTotal(0),
    629 	PreferredTarget(QUARRY_ANYTHING),
    630 	ScreenShakeTime(0),
    631 	Attack(0),
    632 	Enemy(HOUSE_NONE),
    633 	AITimer(0),
    634 	UnitToTeleport(0),
    635 	BuildStructure(STRUCT_NONE),
    636 	BuildUnit(UNIT_NONE),
    637 	BuildInfantry(INFANTRY_NONE),
    638 	BuildAircraft(AIRCRAFT_NONE),
    639 	BuildVessel(VESSEL_NONE),
    640 	NukeDest(0),
    641 	Allies(0),
    642 	DamageTime(TICKS_PER_MINUTE * Rule.DamageDelay),
    643 	TeamTime(TICKS_PER_MINUTE * Rule.TeamDelay),
    644 	TriggerTime(0),
    645 	SpeakAttackDelay(1),
    646 	SpeakPowerDelay(1),
    647 	SpeakMoneyDelay(1),
    648 	SpeakMaxedDelay(1),
    649 	RemapColor(Class->RemapColor),
    650 	DebugUnlockBuildables(false)
    651 {
    652 	/*
    653 	**	Explicit in-place construction of the super weapons is
    654 	**	required here because the default constructor for super
    655 	**	weapons must serve as a no-initialization constructor (save/load reasons).
    656 	*/
    657 	new (&SuperWeapon[SPC_NUCLEAR_BOMB]) SuperClass(TICKS_PER_MINUTE * Rule.NukeTime, true, VOX_ABOMB_PREPPING, VOX_ABOMB_READY, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);
    658 	new (&SuperWeapon[SPC_SONAR_PULSE]) SuperClass(TICKS_PER_MINUTE * Rule.SonarTime, false, VOX_NONE, VOX_SONAR_AVAILABLE, VOX_NOT_READY, VOX_NOT_READY);
    659 	new (&SuperWeapon[SPC_CHRONOSPHERE]) SuperClass(TICKS_PER_MINUTE * Rule.ChronoTime, true, VOX_CHRONO_CHARGING, VOX_CHRONO_READY, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);
    660 	new (&SuperWeapon[SPC_PARA_BOMB]) SuperClass(TICKS_PER_MINUTE * Rule.ParaBombTime, false, VOX_NONE, VOX_NONE, VOX_NOT_READY, VOX_NOT_READY);
    661 	new (&SuperWeapon[SPC_PARA_INFANTRY]) SuperClass(TICKS_PER_MINUTE * Rule.ParaInfantryTime, false, VOX_NONE, VOX_NONE, VOX_NOT_READY, VOX_NOT_READY);
    662 	new (&SuperWeapon[SPC_SPY_MISSION]) SuperClass(TICKS_PER_MINUTE * Rule.SpyTime, false, VOX_NONE, VOX_SPY_PLANE, VOX_NOT_READY, VOX_NOT_READY);
    663 	new (&SuperWeapon[SPC_IRON_CURTAIN]) SuperClass(TICKS_PER_MINUTE * Rule.IronCurtainTime, true, VOX_IRON_CHARGING, VOX_IRON_READY, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);
    664 	new (&SuperWeapon[SPC_GPS]) SuperClass(TICKS_PER_MINUTE * Rule.GPSTime, true, VOX_NONE, VOX_NONE, VOX_NOT_READY, VOX_INSUFFICIENT_POWER);
    665 
    666 	memset(UnitsKilled, '\0', sizeof(UnitsKilled));
    667 	memset(BuildingsKilled, '\0', sizeof(BuildingsKilled));
    668 	memset(BQuantity, '\0', sizeof(BQuantity));
    669 	memset(UQuantity, '\0', sizeof(UQuantity));
    670 	memset(IQuantity, '\0', sizeof(IQuantity));
    671 	memset(AQuantity, '\0', sizeof(AQuantity));
    672 	memset(VQuantity, '\0', sizeof(VQuantity));
    673 	strcpy(IniName, Text_String(TXT_COMPUTER));	// Default computer name.
    674 	HouseTriggers[house].Clear();
    675 	memset((void *)&Regions[0], 0x00, sizeof(Regions));
    676 	Make_Ally(house);
    677 	Assign_Handicap(Scen.CDifficulty);
    678 
    679 	/*
    680 	**	Set the time of the first AI attack.
    681 	*/
    682 	Attack = Rule.AttackDelay * Random_Pick(TICKS_PER_MINUTE/2, TICKS_PER_MINUTE*2);
    683 
    684 	Init_Unit_Trackers();
    685 }
    686 
    687 
    688 /***********************************************************************************************
    689  * HouseClass::~HouseClass -- House class destructor                                           *
    690  *                                                                                             *
    691  *                                                                                             *
    692  *                                                                                             *
    693  * INPUT:    Nothing                                                                           *
    694  *                                                                                             *
    695  * OUTPUT:   Nothing                                                                           *
    696  *                                                                                             *
    697  * WARNINGS: None                                                                              *
    698  *                                                                                             *
    699  * HISTORY:                                                                                    *
    700  *    8/6/96 4:48PM ST : Created                                                               *
    701  *=============================================================================================*/
    702 HouseClass::~HouseClass (void)
    703 {
    704 	Class = 0;
    705 
    706 	Free_Unit_Trackers();
    707 }
    708 
    709 
    710 /***********************************************************************************************
    711  * HouseStaticClass::HouseStaticClass -- Default constructor for house static class.           *
    712  *                                                                                             *
    713  *    This is the default constructor that initializes all the values to their default         *
    714  *    settings.                                                                                *
    715  *                                                                                             *
    716  * INPUT:   none                                                                               *
    717  *                                                                                             *
    718  * OUTPUT:  none                                                                               *
    719  *                                                                                             *
    720  * WARNINGS:   none                                                                            *
    721  *                                                                                             *
    722  * HISTORY:                                                                                    *
    723  *   07/31/1996 JLB : Created.                                                                 *
    724  *=============================================================================================*/
    725 HouseStaticClass::HouseStaticClass(void) :
    726 	IQ(0),
    727 	TechLevel(1),
    728 	Allies(0),
    729 	MaxUnit(Rule.UnitMax/6),
    730 	MaxBuilding(Rule.BuildingMax/6),
    731 	MaxInfantry(Rule.InfantryMax/6),
    732 	MaxVessel(Rule.VesselMax/6),
    733 	MaxAircraft(Rule.UnitMax/6),
    734 	InitialCredits(0),
    735 	Edge(SOURCE_NORTH)
    736 {
    737 }
    738 
    739 
    740 /***********************************************************************************************
    741  * HouseClass::Can_Build -- General purpose build legality checker.                            *
    742  *                                                                                             *
    743  *    This routine is called when it needs to be determined if the specified object type can   *
    744  *    be built by this house. Production and sidebar maintenance use this routine heavily.     *
    745  *                                                                                             *
    746  * INPUT:   type  -- Pointer to the type of object that legality is to be checked for.         *
    747  *                                                                                             *
    748  *          house -- This is the house to check for legality against. Note that this might     *
    749  *                   not be 'this' house since the check could be from a captured factory.     *
    750  *                   Captured factories build what the original owner of them could build.     *
    751  *                                                                                             *
    752  * OUTPUT:  Can the specified object be built?                                                 *
    753  *                                                                                             *
    754  * WARNINGS:   none                                                                            *
    755  *                                                                                             *
    756  * HISTORY:                                                                                    *
    757  *   07/04/1995 JLB : Created.                                                                 *
    758  *   08/12/1995 JLB : Updated for GDI building sandbag walls in #9.                            *
    759  *   10/23/1996 JLB : Hack to allow Tanya to both sides in multiplay.                          *
    760  *   11/04/1996 JLB : Computer uses prerequisite record.                                       *
    761  *=============================================================================================*/
    762 bool HouseClass::Can_Build(ObjectTypeClass const * type, HousesType house) const
    763 {
    764 	assert(Houses.ID(this) == ID);
    765 	assert(type != NULL);
    766 
    767 	/*
    768 	**	An object with a prohibited tech level availability will never be allowed, regardless
    769 	**	of who requests it.
    770 	*/
    771 	if (((TechnoTypeClass const *)type)->Level == -1) return(false);
    772 
    773 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    774 	/*
    775 	** If this is a CounterStrike II-only unit, and we're playing a multiplayer
    776 	** game in 'downshifted' mode against CounterStrike or Red Alert, then
    777 	** don't allow building this unit.
    778 	*/
    779 	if (!NewUnitsEnabled) {
    780 		switch(type->What_Am_I()) {
    781 			case RTTI_INFANTRYTYPE:
    782 				if ( ((InfantryTypeClass *)type)->ID >= INFANTRY_RA_COUNT)
    783 					return(false);
    784 				break;
    785 			case RTTI_UNITTYPE:
    786 				if ( ((UnitTypeClass *)type)->ID >= UNIT_RA_COUNT)
    787 					return(false);
    788 				break;
    789 			case RTTI_VESSELTYPE:
    790 				if ( ((VesselTypeClass *)type)->ID >= VESSEL_RA_COUNT)
    791 					return(false);
    792 				break;
    793 			default:
    794 				break;
    795 		}
    796 	}
    797 #endif
    798 
    799 	/*
    800 	**	The computer can always build everything.
    801 	*/
    802 	if (!IsHuman && Session.Type == GAME_NORMAL) return(true);
    803 
    804 	/*
    805 	**	Special hack to get certain objects to exist for both sides in the game.
    806 	*/
    807 	int own = type->Get_Ownable();
    808 
    809 	/*
    810 	**	Check to see if this owner can build the object type specified.
    811 	*/
    812 	if (((1L << house) & own) == 0) {
    813 		return(false);
    814 	}
    815 
    816 	/*
    817 	**	Perform some equivalency fixups for the building existence flags.
    818 	*/
    819 	long flags = ActiveBScan;
    820 
    821 	/*
    822 	**	The computer records prerequisite buildings because it can't relay on the
    823 	**	sidebar to keep track of this information.
    824 	*/
    825 	if (!IsHuman) {
    826 		flags = OldBScan;
    827 	}
    828 
    829 	int pre = ((TechnoTypeClass const *)type)->Prerequisite;
    830 
    831 	/*
    832 	**	Advanced power also serves as a prerequisite for normal power.
    833 	*/
    834 	if (flags & STRUCTF_ADVANCED_POWER) flags |= STRUCTF_POWER;
    835 
    836 	/*
    837 	**	Either tech center counts as a prerequisite.
    838 	*/
    839 	if (Session.Type != GAME_NORMAL) {
    840 		if ((flags & (STRUCTF_SOVIET_TECH|STRUCTF_ADVANCED_TECH)) != 0) flags |= STRUCTF_SOVIET_TECH|STRUCTF_ADVANCED_TECH;
    841 	}
    842 
    843 	int level = Control.TechLevel;
    844 #ifdef CHEAT_KEYS
    845 	if (Debug_Cheat) {
    846 		level = 98;
    847 		pre = 0;
    848 	}
    849 #endif
    850 
    851 	// ST - 8/23/2019 4:53PM
    852 	if (DebugUnlockBuildables) {
    853 		level = 98;
    854 		pre = 0;
    855 	}			
    856 
    857 	/*
    858 	**	See if the prerequisite requirements have been met.
    859 	*/
    860 	return((pre & flags) == pre && ((TechnoTypeClass const *)type)->Level <= (unsigned)level);
    861 }
    862 
    863 
    864 /***************************************************************************
    865  * HouseClass::Init -- init's in preparation for new scenario              *
    866  *                                                                         *
    867  * INPUT:                                                                  *
    868  *      none.                                                              *
    869  *                                                                         *
    870  * OUTPUT:                                                                 *
    871  *      none.                                                              *
    872  *                                                                         *
    873  * WARNINGS:                                                               *
    874  *      none.                                                              *
    875  *                                                                         *
    876  * HISTORY:                                                                *
    877  *   12/07/1994 BR : Created.                                              *
    878  *   12/17/1994 JLB : Resets tracker bits.                                 *
    879  *=========================================================================*/
    880 void HouseClass::Init(void)
    881 {
    882 	Houses.Free_All();
    883 
    884 	for (HousesType index = HOUSE_FIRST; index < HOUSE_COUNT; index++) {
    885 		HouseTriggers[index].Clear();
    886 	}
    887 }
    888 
    889 // Object selection list is switched with player context for GlyphX. ST - 8/7/2019 10:11AM
    890 extern void Logic_Switch_Player_Context(HouseClass *house);
    891 extern bool MPSuperWeaponDisable;
    892 
    893 /***********************************************************************************************
    894  * HouseClass::AI -- Process house logic.                                                      *
    895  *                                                                                             *
    896  *    This handles the AI for the house object. It should be called once per house per game    *
    897  *    tick. It processes all house global tasks such as low power damage accumulation and      *
    898  *    house specific trigger events.                                                           *
    899  *                                                                                             *
    900  * INPUT:   none                                                                               *
    901  *                                                                                             *
    902  * OUTPUT:  none                                                                               *
    903  *                                                                                             *
    904  * WARNINGS:   none                                                                            *
    905  *                                                                                             *
    906  * HISTORY:                                                                                    *
    907  *   12/27/1994 JLB : Created.                                                                 *
    908  *   07/17/1995 JLB : Limits EVA speaking unless the player can do something.                  *
    909  *=============================================================================================*/
    910 extern void Recalculate_Placement_Distances();
    911 
    912 void HouseClass::AI(void)
    913 {
    914 	assert(Houses.ID(this) == ID);
    915 
    916 	// Set PlayerPtr to be this house. ST - 8/7/2019 10:12AM
    917 	Logic_Switch_Player_Context(this);
    918 
    919 	/*
    920 	**	If base building has been turned on by a trigger, then force the house to begin
    921 	**	production and team creation as well. This is also true if the IQ is high enough to
    922 	**	being base building.
    923 	*/
    924 	if (!IsHuman && (IsBaseBuilding || IQ >= Rule.IQProduction)) {
    925 		IsBaseBuilding = true;
    926 		IsStarted = true;
    927 		IsAlerted = true;
    928 	}
    929 
    930 	/*
    931 	**	Check to see if the house wins.
    932 	*/
    933 	if (Session.Type == GAME_NORMAL && IsToWin && BorrowedTime == 0 && Blockage <= 0) {
    934 		IsToWin = false;
    935 		if (this == PlayerPtr) {
    936 			PlayerWins = true;
    937 		} else {
    938 			PlayerLoses = true;
    939 		}
    940 	}
    941 
    942 	/*
    943 	**	Check to see if the house loses.
    944 	*/
    945 	if (Session.Type == GAME_NORMAL && IsToLose && BorrowedTime == 0) {
    946 		IsToLose = false;
    947 		if (this == PlayerPtr) {
    948 			PlayerLoses = true;
    949 		} else {
    950 			PlayerWins = true;
    951 		}
    952 	}
    953 
    954 	/*
    955 	**	Check to see if all objects of this house should be blown up.
    956 	*/
    957 	if (IsToDie && BorrowedTime == 0) {
    958 		IsToDie = false;
    959 		Blowup_All();
    960 		if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
    961 			MPlayer_Defeated();
    962 		}
    963 	}
    964 
    965 	/*
    966 	**	Double check power values to correct illegal conditions. It is possible to
    967 	**	get a power output of negative (one usually) as a result of damage sustained
    968 	**	and the fixed point fractional math involved with power adjustments. If the
    969 	**	power rating drops below zero, then make it zero.
    970 	*/
    971 	Power = max(Power, 0);
    972 	Drain = max(Drain, 0);
    973 
    974 	/*
    975 	**	If the base has been alerted to the enemy and should be attacking, then
    976 	**	see if the attack timer has expired. If it has, then create the attack
    977 	**	teams.
    978 	*/
    979 	if (IsAlerted && AlertTime == 0) {
    980 
    981 		/*
    982 		**	Adjusted to reduce maximum number of teams created.
    983 		*/
    984 		int maxteams = Random_Pick(2, (int)(((Control.TechLevel-1)/3)+1));
    985 		for (int index = 0; index < maxteams; index++) {
    986 			TeamTypeClass const * ttype = Suggested_New_Team(true);
    987 			if (ttype != NULL) {
    988 				ScenarioInit++;
    989 				ttype->Create_One_Of();
    990 				ScenarioInit--;
    991 			}
    992 		}
    993 		AlertTime = Rule.AutocreateTime * Random_Pick(TICKS_PER_MINUTE/2, TICKS_PER_MINUTE*2);
    994 //		int mintime = Rule.AutocreateTime * (TICKS_PER_MINUTE/2);
    995 //		int maxtime = Rule.AutocreateTime * (TICKS_PER_MINUTE*2);
    996 //		AlertTime = Random_Pick(mintime, maxtime);
    997 	}
    998 
    999 	/*
   1000 	**	If this house's flag waypoint is a valid cell, see if there's
   1001 	**	someone sitting on it.  If so, make the scatter.
   1002 	*/
   1003 	if (FlagHome != 0 && (Frame % TICKS_PER_SECOND) == 0) {
   1004 
   1005 		TechnoClass * techno = Map[FlagHome].Cell_Techno();
   1006 		if (techno != NULL) {
   1007 			bool moving = false;
   1008 			if (techno->Is_Foot()) {
   1009 				if (Target_Legal(((FootClass *)techno)->NavCom)) {
   1010 					moving = true;
   1011 				}
   1012 			}
   1013 
   1014 			if (!moving) {
   1015 				techno->Scatter(0, true, true);
   1016 			}
   1017 		}
   1018 	}
   1019 
   1020 	/*
   1021 	**	Create teams for this house if necessary.
   1022 	** (Use the same timer for some extra capture-the-flag logic.)
   1023 	*/
   1024 	if (!IsAlerted && !TeamTime) {
   1025 
   1026 		TeamTypeClass const * ttype = Suggested_New_Team(false);
   1027 		if (ttype) {
   1028 			ttype->Create_One_Of();
   1029 		}
   1030 
   1031 		TeamTime = Rule.TeamDelay * TICKS_PER_MINUTE;
   1032 	}
   1033 
   1034 	/*
   1035 	**	If there is insufficient power, then all buildings that are above
   1036 	**	half strength take a little bit of damage.
   1037 	*/
   1038 	if (DamageTime == 0) {
   1039 
   1040 		/*
   1041 		**	When the power is below required, then the buildings will take damage over
   1042 		**	time.
   1043 		*/
   1044 		if (Power_Fraction() < 1) {
   1045 			for (int index = 0; index < Buildings.Count(); index++) {
   1046 				BuildingClass & b = *Buildings.Ptr(index);
   1047 
   1048 				if (b.House == this && b.Health_Ratio() > Rule.ConditionYellow) {
   1049 					// BG: Only damage buildings that require power, to keep the
   1050 					//     land mines from blowing up under low-power conditions
   1051 					if (b.Class->Drain) {
   1052 						int damage = 1;
   1053 						b.Take_Damage(damage, 0, WARHEAD_AP, 0);
   1054 					}
   1055 				}
   1056 			}
   1057 		}
   1058 		DamageTime = TICKS_PER_MINUTE * Rule.DamageDelay;
   1059 	}
   1060 
   1061 	/*
   1062 	**	If there are no more buildings to sell, then automatically cancel the
   1063 	**	sell mode.
   1064 	*/
   1065 	if (PlayerPtr == this && !ActiveBScan && Map.IsSellMode) {
   1066 		Map.Sell_Mode_Control(0);
   1067 	}
   1068 
   1069 	/*
   1070 	**	Various base conditions may be announced to the player. Typically, this would be
   1071 	**	low tiberium capacity or low power.
   1072 	*/
   1073 	if (PlayerPtr == this) {
   1074 
   1075 		if (SpeakMaxedDelay == 0 && Available_Money() < 100 && UnitFactories+BuildingFactories+InfantryFactories > 0) {
   1076 			Speak(VOX_NEED_MO_MONEY);
   1077 			Map.Flash_Money();
   1078 			SpeakMaxedDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);
   1079 
   1080 			int text_id = TXT_INSUFFICIENT_FUNDS;
   1081 			char const * text = Text_String(TXT_INSUFFICIENT_FUNDS);
   1082 			if (text != NULL) {
   1083 				Session.Messages.Add_Message(NULL, text_id, text, PCOLOR_GREEN, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);
   1084 			}
   1085 		}
   1086 
   1087 		if (SpeakMaxedDelay == 0 && IsMaxedOut) {
   1088 			IsMaxedOut = false;
   1089 			if ((Capacity - Tiberium) < 300 && Capacity > 500 && (ActiveBScan & (STRUCTF_REFINERY | STRUCTF_CONST))) {
   1090  				Speak(VOX_NEED_MO_CAPACITY);
   1091 				SpeakMaxedDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);
   1092 			}
   1093 		}
   1094 		if (SpeakPowerDelay == 0 && Power_Fraction() < 1) {
   1095 			if (ActiveBScan & STRUCTF_CONST) {
   1096 				Speak(VOX_LOW_POWER);
   1097 				SpeakPowerDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay);
   1098 				Map.Flash_Power();
   1099 
   1100 				int text_id = -1;
   1101 				char const * text = NULL;
   1102 				if (BQuantity[STRUCT_AAGUN] > 0) {
   1103 					text = Text_String(TXT_POWER_AAGUN);
   1104 					text_id = TXT_POWER_AAGUN;
   1105 				}
   1106 				if (BQuantity[STRUCT_TESLA] > 0) {
   1107 					text = Text_String(TXT_POWER_TESLA);
   1108 					text_id = TXT_POWER_TESLA;
   1109 				}
   1110 				if (text == NULL) {
   1111 					text = Text_String(TXT_LOW_POWER);
   1112 					text_id = TXT_LOW_POWER;
   1113 				}
   1114 				if (text != NULL) {
   1115 					Session.Messages.Add_Message(NULL, text_id, text, PCOLOR_GREEN, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);
   1116 				}
   1117 			}
   1118 		}
   1119 	}
   1120 
   1121 	/*
   1122 	**	If there is a flag associated with this house, then mark it to be
   1123 	**	redrawn.
   1124 	*/
   1125 	if (Target_Legal(FlagLocation)) {
   1126 		UnitClass * unit = As_Unit(FlagLocation);
   1127 		if (unit) {
   1128 			unit->Mark(MARK_CHANGE);
   1129 		} else {
   1130 			CELL cell = As_Cell(FlagLocation);
   1131 			Map[cell].Flag_Update();
   1132 			Map[cell].Redraw_Objects();
   1133 		}
   1134 	}
   1135 
   1136 	bool is_time = false;
   1137 
   1138 	/*
   1139 	**	Triggers are only checked every so often. If the trigger timer has expired,
   1140 	**	then set the trigger processing flag.
   1141 	*/
   1142 	if (TriggerTime == 0 || IsBuiltSomething) {
   1143 		is_time = true;
   1144 		TriggerTime = TICKS_PER_MINUTE/10;
   1145 		IsBuiltSomething = false;
   1146 	}
   1147 
   1148 	/*
   1149 	**	Process any super weapon logic required.
   1150 	*/
   1151 
   1152 	if (Session.Type != GAME_GLYPHX_MULTIPLAYER || !MPSuperWeaponDisable) {
   1153 		Super_Weapon_Handler();
   1154 	}
   1155 
   1156 #ifdef FIXIT_VERSION_3			//	For endgame auto-sonar pulse.
   1157 	if( (Session.Type != GAME_NORMAL || !IsHuman) && Scen.AutoSonarTimer == 0 )
   1158 	{
   1159 		//	If house has nothing but subs left, do an automatic sonar pulse to reveal them.
   1160 		if( VQuantity[ VESSEL_SS ] > 0 )		//	Includes count of VESSEL_MISSILESUBs. ajw
   1161 		{
   1162 			int iCount = 0;
   1163 			int i;
   1164 			for( i = 0; i != STRUCT_COUNT-3; ++i )
   1165 			{
   1166 				iCount += BQuantity[ i ];
   1167 			}
   1168 			if( !iCount )
   1169 			{
   1170 				for( i = 0; i != UNIT_RA_COUNT-3; ++i )
   1171 				{
   1172 					iCount += UQuantity[ i ];
   1173 				}
   1174 				if( !iCount )
   1175 				{
   1176 					//	ajw - Found bug - house's civilians are not removed from IQuantity when they die.
   1177 					//	Workaround...
   1178 					for( i = 0; i <= INFANTRY_DOG; ++i )
   1179 					{
   1180 						iCount += IQuantity[ i ];
   1181 					}
   1182 					if( !iCount )
   1183 					{
   1184 						for( i = 0; i != AIRCRAFT_COUNT; ++i )
   1185 						{
   1186 							iCount += AQuantity[ i ];
   1187 						}
   1188 						if( !iCount )
   1189 						{
   1190 							for( i = 0; i != VESSEL_RA_COUNT; ++i )
   1191 							{
   1192 								if( i != VESSEL_SS )
   1193 									iCount += VQuantity[ i ];
   1194 							}
   1195 							if( !iCount )
   1196 							{
   1197 								//	Do the ping.
   1198 								for (int index = 0; index < Vessels.Count(); index++) {
   1199 									VesselClass * sub = Vessels.Ptr(index);
   1200 									if (*sub == VESSEL_SS || *sub == VESSEL_MISSILESUB) {
   1201 										sub->PulseCountDown = 15 * TICKS_PER_SECOND;
   1202 										sub->Do_Uncloak();
   1203 									}
   1204 								}
   1205 								bAutoSonarPulse = true;
   1206 							}
   1207 						}
   1208 					}
   1209 				}
   1210 			}
   1211 		}
   1212 	}
   1213 #endif
   1214 
   1215 	if (Session.Type != GAME_NORMAL) {
   1216 		Check_Pertinent_Structures();
   1217 	}
   1218 
   1219 	/*
   1220 	** Special win/lose check for multiplayer games; by-passes the
   1221 	** trigger system.  We must wait for non-zero frame, because init
   1222 	** may not properly set IScan etc for each house; you have to go
   1223 	** through each object's AI before it will be properly set.
   1224 	*/
   1225 	if (Session.Type != GAME_NORMAL && !IsDefeated &&
   1226 		!ActiveBScan && !ActiveAScan && !UScan && !ActiveIScan && !ActiveVScan && Frame > 0) {
   1227 		MPlayer_Defeated();
   1228 	}
   1229 
   1230 	/*
   1231 	**	Try to spring all events attached to this house. The triggers will check
   1232 	**	for themselves if they actually need to be sprung or not.
   1233 	*/
   1234 	for (int index = 0; index < HouseTriggers[Class->House].Count(); index++) {
   1235 		if (HouseTriggers[Class->House][index]->Spring() && index > 0) {
   1236 			index--;
   1237 			continue;
   1238 		}
   1239 	}
   1240 
   1241 	/*
   1242 	**	If a radar facility is not present, but the radar is active, then turn the radar off.
   1243 	**	The radar also is turned off when the power gets below 100% capacity.
   1244 	*/
   1245 	if (PlayerPtr == this) {
   1246 		bool jammed = true;
   1247 
   1248 		/*
   1249 		** Find if there are any radar facilities, and if they're jammed or not
   1250 		*/
   1251 
   1252 		if (IsGPSActive) {
   1253 			jammed = false;
   1254 		} else {
   1255 			for (int index = 0; index < Buildings.Count(); index++) {
   1256 				BuildingClass * building = Buildings.Ptr(index);
   1257 #ifdef FIXIT_RADAR_JAMMED
   1258 				if (building != NULL && !building->IsInLimbo && building->House == PlayerPtr) {
   1259 #else
   1260 				if (building && building->House == PlayerPtr) {
   1261 #endif
   1262 					if (*building == STRUCT_RADAR /* || *building == STRUCT_EYE */) {
   1263 						if (!building->IsJammed) {
   1264 							jammed = false;
   1265 							break;
   1266 						}
   1267 					}
   1268 				}
   1269 			}
   1270 		}
   1271 
   1272 		Map.Set_Jammed(this, jammed);
   1273 // Need to add in here where we activate it when only GPS is active.
   1274 		if (Map.Is_Radar_Active()) {
   1275 			if (ActiveBScan & STRUCTF_RADAR) {
   1276 				if (Power_Fraction() < 1 && !IsGPSActive) {
   1277 					Map.Radar_Activate(0);
   1278 				}
   1279 			} else {
   1280 				if (!IsGPSActive) {
   1281 					Map.Radar_Activate(0);
   1282 				}
   1283 			}
   1284 
   1285 		} else {
   1286 			if (IsGPSActive || (ActiveBScan & STRUCTF_RADAR)) {
   1287 				if (Power_Fraction() >= 1 || IsGPSActive) {
   1288 					Map.Radar_Activate(1);
   1289 				}
   1290 			} else {
   1291 				if (Map.Is_Radar_Existing()) {
   1292 					Map.Radar_Activate(4);
   1293 				}
   1294 			}
   1295 		}
   1296 		if (!IsGPSActive && !(ActiveBScan & STRUCTF_RADAR)) {
   1297 			Radar = RADAR_NONE;
   1298 		} else {
   1299 			Radar = (Map.Is_Radar_Active() || Map.Is_Radar_Activating()) ? RADAR_ON : RADAR_OFF;
   1300 		}
   1301 	}
   1302 
   1303 	VisibleCredits.AI(false, this, true);
   1304 
   1305 	/*
   1306 	**	Perform any expert system AI processing.
   1307 	*/
   1308 	if (IsBaseBuilding && AITimer == 0) {
   1309 		AITimer = Expert_AI();
   1310 	}
   1311 
   1312 	if (!IsBaseBuilding && State == STATE_ENDGAME) {
   1313 		Fire_Sale();
   1314 		Do_All_To_Hunt();
   1315 	}
   1316 
   1317 	AI_Building();
   1318 	AI_Unit();
   1319 	AI_Vessel();
   1320 	AI_Infantry();
   1321 	AI_Aircraft();
   1322 
   1323 
   1324 	/*
   1325 	**	If the production possibilities need to be recalculated, then do so now. This must
   1326 	**	occur after the scan bits have been properly updated.
   1327 	*/
   1328 	if (PlayerPtr == this && IsRecalcNeeded) {
   1329 		IsRecalcNeeded = false;
   1330 		Map.Recalc();
   1331 
   1332 		/*
   1333 		**	This placement might affect any prerequisite requirements for construction
   1334 		**	lists. Update the buildable options accordingly.
   1335 		*/
   1336 		for (int index = 0; index < Buildings.Count(); index++) {
   1337 			BuildingClass * building = Buildings.Ptr(index);
   1338 			if (building && building->Strength > 0 && building->Owner() == Class->House && building->Mission != MISSION_DECONSTRUCTION && building->MissionQueue != MISSION_DECONSTRUCTION) {
   1339 
   1340 				if (PlayerPtr == building->House) {
   1341 					building->Update_Buildables();
   1342 				}
   1343 			}
   1344 		}
   1345 
   1346 		Recalculate_Placement_Distances();
   1347 		Check_Pertinent_Structures();
   1348 	}
   1349 
   1350 	/*
   1351 	** See if it's time to re-set the can-repair flag
   1352 	*/
   1353 	if (DidRepair && RepairTimer == 0) {
   1354 		DidRepair = false;
   1355 	}
   1356 
   1357 	if (this == PlayerPtr && IsToLook) {
   1358 		IsToLook = false;
   1359 		Map.All_To_Look(PlayerPtr);
   1360 	}
   1361 }
   1362 
   1363 /***********************************************************************************************
   1364  * HouseClass::Super_Weapon_Handler -- Handles the super weapon charge and discharge logic.    *
   1365  *                                                                                             *
   1366  *    This handles any super weapons assigned to this house. It also performs any necessary    *
   1367  *    maintenance that the super weapons require.                                              *
   1368  *                                                                                             *
   1369  * INPUT:   none                                                                               *
   1370  *                                                                                             *
   1371  * OUTPUT:  none                                                                               *
   1372  *                                                                                             *
   1373  * WARNINGS:   none                                                                            *
   1374  *                                                                                             *
   1375  * HISTORY:                                                                                    *
   1376  *   09/17/1996 JLB : Created.                                                                 *
   1377  *=============================================================================================*/
   1378 void HouseClass::Super_Weapon_Handler(void)
   1379 {
   1380 	/*
   1381 	**	Perform all super weapon AI processing. This just checks to see if
   1382 	**	the graphic needs changing for the special weapon and updates the
   1383 	**	sidebar as necessary.
   1384 	*/
   1385 	for (SpecialWeaponType special = SPC_FIRST; special < SPC_COUNT; special++) {
   1386 		SuperClass * super = &SuperWeapon[special];
   1387 
   1388 		if (super->Is_Present()) {
   1389 
   1390 			/*
   1391 			**	Perform any charge-up logic for the super weapon. If the super
   1392 			**	weapon is owned by the player and a graphic change is detected, then
   1393 			**	flag the sidebar to be redrawn so the player will see the change.
   1394 			*/
   1395 			if (super->AI(this == PlayerPtr)) {
   1396 				if (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();
   1397 			}
   1398 
   1399 			/*
   1400 			**	Repeating super weapons that require power will be suspended if there
   1401 			**	is insufficient power available.
   1402 			*/
   1403 			if (!super->Is_Ready() && super->Is_Powered() && !super->Is_One_Time()) {
   1404 				super->Suspend(Power_Fraction() < 1);
   1405 			}
   1406 		}
   1407 	}
   1408 
   1409 	/*
   1410 	** Check to see if they have launched the GPS, but subsequently lost their
   1411 	** tech center.  If so, remove the GPS, and shroud the map.
   1412 	*/
   1413 	if (IsGPSActive && !(ActiveBScan & STRUCTF_ADVANCED_TECH) ) {
   1414 		IsGPSActive = false;
   1415 
   1416 		/*
   1417 		** Updated for client/server multiplayer. ST  - 8/12/2019 11:32AM
   1418 		*/
   1419 		if (Session.Type != GAME_GLYPHX_MULTIPLAYER) {
   1420 			if (IsPlayerControl) {
   1421 				Map.Shroud_The_Map(PlayerPtr);
   1422 			}
   1423 		
   1424 		} else {
   1425 			
   1426 			if (IsHuman) {
   1427 				Map.Shroud_The_Map(this);
   1428 			}
   1429 		}	
   1430 	}
   1431 
   1432 	/*
   1433 	**	Check to see if the GPS Satellite should be removed from the sidebar
   1434 	**	because of outside circumstances. The advanced technology facility
   1435 	**	being destroyed is a good example of this.  Having fired the satellite
   1436 	** is another good example, because it's a one-shot item.
   1437 	*/
   1438 	if (SuperWeapon[SPC_GPS].Is_Present()) {
   1439 		if (!(ActiveBScan & STRUCTF_ADVANCED_TECH) || IsGPSActive || IsDefeated) {
   1440 			/*
   1441 			**	Remove the missile capability when there is no advanced tech facility.
   1442 			*/
   1443 			if (SuperWeapon[SPC_GPS].Remove()) {
   1444 				if (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();
   1445 				IsRecalcNeeded = true;
   1446 			}
   1447 		} else {
   1448 			/*
   1449 			** Auto-fire the GPS satellite if it's charged up.
   1450 			*/
   1451 			if (SuperWeapon[SPC_GPS].Is_Ready()) {
   1452 				SuperWeapon[SPC_GPS].Discharged(this == PlayerPtr);
   1453 				if (SuperWeapon[SPC_GPS].Remove()) {
   1454 					if (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();
   1455 				}
   1456 				IsRecalcNeeded = true;
   1457 				for (int index = 0; index < Buildings.Count(); index++) {
   1458 					BuildingClass * bldg = Buildings.Ptr(index);
   1459 					if (*bldg == STRUCT_ADVANCED_TECH && bldg->House == this) {
   1460 						bldg->HasFired = true;
   1461 						bldg->Assign_Mission(MISSION_MISSILE);
   1462 						break;
   1463 					}
   1464 				}
   1465 			}
   1466 		}
   1467 	} else {
   1468 		/*
   1469 		**	If there is no GPS satellite present, but there is a GPS satellite
   1470 		**	facility available, then make the GPS satellite available as well.
   1471 		*/
   1472 		if ((ActiveBScan & STRUCTF_ADVANCED_TECH) != 0 &&
   1473 			!IsGPSActive &&
   1474 			Control.TechLevel >= Rule.GPSTechLevel &&
   1475 			(IsHuman || IQ >= Rule.IQSuperWeapons)) {
   1476 
   1477 			bool canfire = false;
   1478 			for (int index = 0; index < Buildings.Count(); index++) {
   1479 				BuildingClass * bldg = Buildings.Ptr(index);
   1480 				if (*bldg == STRUCT_ADVANCED_TECH && bldg->House == this && !bldg->IsInLimbo) {
   1481 					if (!bldg->HasFired) {
   1482 						canfire = true;
   1483 						break;
   1484 					}
   1485 				}
   1486 			}
   1487 
   1488 			if (canfire) {
   1489 				SuperWeapon[SPC_GPS].Enable(false, this == PlayerPtr, Power_Fraction() < 1);
   1490 
   1491 				/*
   1492 				**	Flag the sidebar to be redrawn if necessary.
   1493 				*/
   1494 				// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM
   1495 				if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   1496 					if (IsHuman) {
   1497 						Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_GPS, this);
   1498 					}
   1499 				} else {
   1500 					if (this == PlayerPtr) {
   1501 						Map.Add(RTTI_SPECIAL, SPC_GPS);
   1502 						Map.Column[1].Flag_To_Redraw();
   1503 					}
   1504 				}
   1505 			}
   1506 		}
   1507 	}
   1508 
   1509 	/*
   1510 	**	Check to see if the chronosphere should be removed from the sidebar
   1511 	**	because of outside circumstances. The chronosphere facility
   1512 	**	being destroyed is a good example of this.
   1513 	*/
   1514 	if (SuperWeapon[SPC_CHRONOSPHERE].Is_Present()) {
   1515 		if ( (!(ActiveBScan & STRUCTF_CHRONOSPHERE) && !SuperWeapon[SPC_CHRONOSPHERE].Is_One_Time()) || IsDefeated) {
   1516 
   1517 			/*
   1518 			**	Remove the chronosphere when there is no chronosphere facility.
   1519 			**	Note that this will not remove the one time created chronosphere.
   1520 			*/
   1521 			if (SuperWeapon[SPC_CHRONOSPHERE].Remove()) {
   1522 				if (this == PlayerPtr) {
   1523 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   1524 					if (Map.IsTargettingMode == SPC_CHRONOSPHERE || Map.IsTargettingMode == SPC_CHRONO2) {
   1525 						if (Map.IsTargettingMode == SPC_CHRONO2) {
   1526 							TechnoClass * tech = (TechnoClass *)::As_Object(UnitToTeleport);
   1527 							if (tech && tech->IsActive && tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_CHRONOTANK) {
   1528 							} else {
   1529 								 Map.IsTargettingMode = SPC_NONE;
   1530 							}
   1531 						} else {
   1532 							Map.IsTargettingMode = SPC_NONE;
   1533 						}
   1534 					}
   1535 #else
   1536 					if (Map.IsTargettingMode == SPC_CHRONOSPHERE ||
   1537 						 Map.IsTargettingMode == SPC_CHRONO2) {
   1538 						 Map.IsTargettingMode = SPC_NONE;
   1539 					}
   1540 #endif
   1541 					Map.Column[1].Flag_To_Redraw();
   1542 				}
   1543 				IsRecalcNeeded = true;
   1544 			}
   1545 		}
   1546 	} else {
   1547 		/*
   1548 		**	If there is no chronosphere present, but there is a chronosphere
   1549 		**	facility available, then make the chronosphere available as well.
   1550 		*/
   1551 		if ((ActiveBScan & STRUCTF_CHRONOSPHERE) &&
   1552 //			(ActLike == HOUSE_GOOD || Session.Type != GAME_NORMAL) &&
   1553 			(unsigned)Control.TechLevel >= BuildingTypeClass::As_Reference(STRUCT_CHRONOSPHERE).Level &&
   1554 //			Control.TechLevel >= Rule.ChronoTechLevel &&
   1555 			(IsHuman || IQ >= Rule.IQSuperWeapons)) {
   1556 
   1557 			SuperWeapon[SPC_CHRONOSPHERE].Enable(false, this == PlayerPtr, Power_Fraction() < 1);
   1558 
   1559 			/*
   1560 			**	Flag the sidebar to be redrawn if necessary.
   1561 			*/
   1562 			// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM
   1563 			if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   1564 				if (IsHuman) {
   1565 					Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_CHRONOSPHERE, this);
   1566 				}
   1567 			} else {
   1568 				if (this == PlayerPtr) {
   1569 					Map.Add(RTTI_SPECIAL, SPC_CHRONOSPHERE);
   1570 					Map.Column[1].Flag_To_Redraw();
   1571 				}
   1572 			}
   1573 		}
   1574 	}
   1575 
   1576 	/*
   1577 	**	Check to see if the iron curtain should be removed from the sidebar
   1578 	**	because of outside circumstances. The iron curtain facility
   1579 	**	being destroyed is a good example of this.
   1580 	*/
   1581 	if (SuperWeapon[SPC_IRON_CURTAIN].Is_Present()) {
   1582 		if ( (!(ActiveBScan & STRUCTF_IRON_CURTAIN) && !SuperWeapon[SPC_IRON_CURTAIN].Is_One_Time())  || IsDefeated) {
   1583 
   1584 			/*
   1585 			**	Remove the iron curtain when there is no iron curtain facility.
   1586 			**	Note that this will not remove the one time created iron curtain.
   1587 			*/
   1588 			if (SuperWeapon[SPC_IRON_CURTAIN].Remove()) {
   1589 				if (this == PlayerPtr) {
   1590 					if (Map.IsTargettingMode == SPC_IRON_CURTAIN) {
   1591 						 Map.IsTargettingMode = SPC_NONE;
   1592 					}
   1593 					Map.Column[1].Flag_To_Redraw();
   1594 				}
   1595 				IsRecalcNeeded = true;
   1596 			}
   1597 		}
   1598 	} else {
   1599 		/*
   1600 		**	If there is no iron curtain present, but there is an iron curtain
   1601 		**	facility available, then make the iron curtain available as well.
   1602 		*/
   1603 		if ((ActiveBScan & STRUCTF_IRON_CURTAIN) &&
   1604 			(ActLike == HOUSE_USSR || ActLike == HOUSE_UKRAINE || Session.Type != GAME_NORMAL) &&
   1605 			(IsHuman || IQ >= Rule.IQSuperWeapons)) {
   1606 
   1607 			SuperWeapon[SPC_IRON_CURTAIN].Enable(false, this == PlayerPtr, Power_Fraction() < 1);
   1608 
   1609 			/*
   1610 			**	Flag the sidebar to be redrawn if necessary.
   1611 			*/
   1612 			// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM
   1613 			if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   1614 				if (IsHuman) {
   1615 					Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_IRON_CURTAIN, this);
   1616 				}
   1617 			} else {
   1618 				if (this == PlayerPtr) {
   1619 					Map.Add(RTTI_SPECIAL, SPC_IRON_CURTAIN);
   1620 					Map.Column[1].Flag_To_Redraw();
   1621 				}
   1622 			}
   1623 		}
   1624 	}
   1625 
   1626 	/*
   1627 	**	Check to see if the sonar pulse should be removed from the sidebar
   1628 	**	because of outside circumstances. The spied-upon enemy sub pen
   1629 	**	being destroyed is a good example of this.
   1630 	*/
   1631 	if (SuperWeapon[SPC_SONAR_PULSE].Is_Present()) {
   1632 		int usspy = 1 << (Class->House);
   1633 		bool present = false;
   1634 		bool powered = false;
   1635 		for (int q = 0; q < Buildings.Count() && !powered; q++) {
   1636 			BuildingClass * bldg = Buildings.Ptr(q);
   1637 			if ((*bldg == STRUCT_SUB_PEN) && (bldg->House->Class->House != Class->House) && (bldg->Spied_By() & usspy) ) {
   1638 				present = true;
   1639 				powered = !(bldg->House->Power_Fraction() < 1);
   1640 			}
   1641 		}
   1642 		if ( (!present && !SuperWeapon[SPC_SONAR_PULSE].Is_One_Time())  || IsDefeated) {
   1643 
   1644 			/*
   1645 			**	Remove the sonar pulse when there is no spied-upon enemy sub pen.
   1646 			**	Note that this will not remove the one time created sonar pulse.
   1647 			*/
   1648 			if (SuperWeapon[SPC_SONAR_PULSE].Remove()) {
   1649 				if (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();
   1650 				IsRecalcNeeded = true;
   1651 			}
   1652 		}
   1653 	}
   1654 
   1655 	/*
   1656 	**	Check to see if the nuclear weapon should be removed from the sidebar
   1657 	**	because of outside circumstances. The missile silos
   1658 	**	being destroyed is a good example of this.
   1659 	*/
   1660 	if (SuperWeapon[SPC_NUCLEAR_BOMB].Is_Present()) {
   1661 		if ( (!(ActiveBScan & STRUCTF_MSLO) && !SuperWeapon[SPC_NUCLEAR_BOMB].Is_One_Time()) || IsDefeated) {
   1662 
   1663 			/*
   1664 			**	Remove the nuke when there is no missile silo.
   1665 			**	Note that this will not remove the one time created nuke.
   1666 			*/
   1667 			if (SuperWeapon[SPC_NUCLEAR_BOMB].Remove()) {
   1668 				if (this == PlayerPtr) {
   1669 					if (Map.IsTargettingMode == SPC_NUCLEAR_BOMB) {
   1670 						 Map.IsTargettingMode = SPC_NONE;
   1671 					}
   1672 					Map.Column[1].Flag_To_Redraw();
   1673 				}
   1674 				IsRecalcNeeded = true;
   1675 			}
   1676 		} else {
   1677 			/*
   1678 			**	Allow the computer to fire the nuclear weapon when the weapon is
   1679 			**	ready and the owner is the computer.
   1680 			*/
   1681 			if (SuperWeapon[SPC_NUCLEAR_BOMB].Is_Ready() && !IsHuman) {
   1682 				Special_Weapon_AI(SPC_NUCLEAR_BOMB);
   1683 			}
   1684 		}
   1685 
   1686 	} else {
   1687 		/*
   1688 		**	If there is no nuclear missile present, but there is a missile
   1689 		**	silo available, then make the missile available as well.
   1690 		*/
   1691 		if ((ActiveBScan & STRUCTF_MSLO) &&
   1692 			((ActLike != HOUSE_USSR && ActLike != HOUSE_UKRAINE) || Session.Type != GAME_NORMAL) &&
   1693 			(IsHuman || IQ >= Rule.IQSuperWeapons)) {
   1694 
   1695 			SuperWeapon[SPC_NUCLEAR_BOMB].Enable(false, this == PlayerPtr, Power_Fraction() < 1);
   1696 
   1697 			/*
   1698 			**	Flag the sidebar to be redrawn if necessary.
   1699 			*/
   1700 			// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM
   1701 			if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   1702 				if (IsHuman) {
   1703 					Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB, this);
   1704 				}
   1705 			} else {
   1706 				if (this == PlayerPtr) {
   1707 					Map.Add(RTTI_SPECIAL, SPC_NUCLEAR_BOMB);
   1708 					Map.Column[1].Flag_To_Redraw();
   1709 				}
   1710 			}
   1711 		}
   1712 	}
   1713 
   1714 
   1715 	if (SuperWeapon[SPC_SPY_MISSION].Is_Present()) {
   1716 		if ((ActiveBScan & STRUCTF_AIRSTRIP) == 0) {
   1717 			if (SuperWeapon[SPC_SPY_MISSION].Remove()) {
   1718 				if (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();
   1719 				IsRecalcNeeded = true;
   1720 			}
   1721 		} else {
   1722 			if (this == PlayerPtr && !SuperWeapon[SPC_SPY_MISSION].Is_Ready()) {
   1723 				Map.Column[1].Flag_To_Redraw();
   1724 			}
   1725 			if (SuperWeapon[SPC_SPY_MISSION].Is_Ready() && !IsHuman) {
   1726 				Special_Weapon_AI(SPC_SPY_MISSION);
   1727 			}
   1728 		}
   1729 	} else {
   1730 		if ((ActiveBScan & STRUCTF_AIRSTRIP) != 0 && !Scen.IsNoSpyPlane && Control.TechLevel >= Rule.SpyPlaneTechLevel) {
   1731 			SuperWeapon[SPC_SPY_MISSION].Enable(false, this == PlayerPtr, false);
   1732 			// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM
   1733 			if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   1734 				if (IsHuman) {
   1735 					Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_SPY_MISSION, this);
   1736 				}
   1737 			} else {
   1738 				if (this == PlayerPtr) {
   1739 					Map.Add(RTTI_SPECIAL, SPC_SPY_MISSION);
   1740 					Map.Column[1].Flag_To_Redraw();
   1741 				}
   1742 			}
   1743 		}
   1744 	}
   1745 
   1746 	if (SuperWeapon[SPC_PARA_BOMB].Is_Present()) {
   1747 		if ((ActiveBScan & STRUCTF_AIRSTRIP) == 0) {
   1748 			if (SuperWeapon[SPC_PARA_BOMB].Remove()) {
   1749 				if (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();
   1750 				IsRecalcNeeded = true;
   1751 			}
   1752 		} else {
   1753 			if (SuperWeapon[SPC_PARA_BOMB].Is_Ready() && !IsHuman) {
   1754 				Special_Weapon_AI(SPC_PARA_BOMB);
   1755 			}
   1756 		}
   1757 	} else {
   1758 		if ((ActiveBScan & STRUCTF_AIRSTRIP) != 0 && Control.TechLevel >= Rule.ParaBombTechLevel && Session.Type == GAME_NORMAL) {
   1759 			SuperWeapon[SPC_PARA_BOMB].Enable(false, this == PlayerPtr, false);
   1760 			// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM
   1761 			if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   1762 				if (IsHuman) {
   1763 					Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_PARA_BOMB, this);
   1764 				}
   1765 			} else {
   1766 				if (this == PlayerPtr) {
   1767 					Map.Add(RTTI_SPECIAL, SPC_PARA_BOMB);
   1768 					Map.Column[1].Flag_To_Redraw();
   1769 				}
   1770 			}
   1771 		}
   1772 	}
   1773 
   1774 	if (SuperWeapon[SPC_PARA_INFANTRY].Is_Present()) {
   1775 		if ((ActiveBScan & STRUCTF_AIRSTRIP) == 0) {
   1776 			if (SuperWeapon[SPC_PARA_INFANTRY].Remove()) {
   1777 				if (this == PlayerPtr) Map.Column[1].Flag_To_Redraw();
   1778 				IsRecalcNeeded = true;
   1779 			}
   1780 		} else {
   1781 			if (SuperWeapon[SPC_PARA_INFANTRY].Is_Ready() && !IsHuman) {
   1782 				Special_Weapon_AI(SPC_PARA_INFANTRY);
   1783 			}
   1784 		}
   1785 	} else {
   1786 		if ((ActiveBScan & STRUCTF_AIRSTRIP) != 0 && Control.TechLevel >= Rule.ParaInfantryTechLevel) {
   1787 			SuperWeapon[SPC_PARA_INFANTRY].Enable(false, this == PlayerPtr, false);
   1788 			// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM
   1789 			if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   1790 				if (IsHuman) {
   1791 					Sidebar_Glyphx_Add(RTTI_SPECIAL, SPC_PARA_INFANTRY, this);
   1792 				}
   1793 			} else {
   1794 				if (this == PlayerPtr) {
   1795 					Map.Add(RTTI_SPECIAL, SPC_PARA_INFANTRY);
   1796 					Map.Column[1].Flag_To_Redraw();
   1797 				}
   1798 			}
   1799 		}
   1800 	}
   1801 }
   1802 
   1803 
   1804 /***********************************************************************************************
   1805  * HouseClass::Attacked -- Lets player know if base is under attack.                           *
   1806  *                                                                                             *
   1807  *    Call this function whenever a building is attacked (with malice). This function will     *
   1808  *    then announce to the player that his base is under attack. It checks to make sure that   *
   1809  *    this is referring to the player's house rather than the enemy's.                         *
   1810  *                                                                                             *
   1811  * INPUT:   none                                                                               *
   1812  *                                                                                             *
   1813  * OUTPUT:  none                                                                               *
   1814  *                                                                                             *
   1815  * WARNINGS:   none                                                                            *
   1816  *                                                                                             *
   1817  * HISTORY:                                                                                    *
   1818  *   12/27/1994 JLB : Created.                                                                 *
   1819  *=============================================================================================*/
   1820 void HouseClass::Attacked(BuildingClass* source)
   1821 {
   1822 	assert(Houses.ID(this) == ID);
   1823 
   1824 #ifdef FIXIT_BASE_ANNOUNCE
   1825 	if (SpeakAttackDelay == 0 && ((Session.Type == GAME_NORMAL && IsPlayerControl) || PlayerPtr->Class->House == Class->House)) {
   1826 #else
   1827 	if (SpeakAttackDelay == 0 && PlayerPtr->Class->House == Class->House) {
   1828 #endif
   1829 		if (Session.Type == GAME_NORMAL) {
   1830 			Speak(VOX_BASE_UNDER_ATTACK, NULL, source ? source->Center_Coord() : 0);
   1831 		} else {
   1832 			Speak(VOX_BASE_UNDER_ATTACK, this);
   1833 		}
   1834 
   1835 		// MBL 06.13.2020 - Timing change from 2 minute cooldown, per https://jaas.ea.com/browse/TDRA-6784
   1836 		// SpeakAttackDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay); // 2 minutes
   1837 		// SpeakAttackDelay = Options.Normalize_Delay(TICKS_PER_MINUTE/2); // 30 seconds as requested
   1838 		SpeakAttackDelay = Options.Normalize_Delay( (TICKS_PER_MINUTE/2)+(TICKS_PER_SECOND*5) ); // Tweaked for accuracy
   1839 
   1840 		/*
   1841 		**	If there is a trigger event associated with being attacked, process it
   1842 		**	now.
   1843 		*/
   1844 		for (int index = 0; index < HouseTriggers[Class->House].Count(); index++) {
   1845 			HouseTriggers[Class->House][index]->Spring(TEVENT_ATTACKED);
   1846 		}
   1847 	}
   1848 }
   1849 
   1850 
   1851 /***********************************************************************************************
   1852  * HouseClass::Harvested -- Adds Tiberium to the harvest storage.                              *
   1853  *                                                                                             *
   1854  *    Use this routine whenever Tiberium is harvested. The Tiberium is stored equally between  *
   1855  *    all storage capable buildings for the house. Harvested Tiberium adds to the credit       *
   1856  *    value of the house, but only up to the maximum storage capacity that the house can       *
   1857  *    currently maintain.                                                                      *
   1858  *                                                                                             *
   1859  * INPUT:   tiberium -- The number of Tiberium credits to add to the House's total.            *
   1860  *                                                                                             *
   1861  * OUTPUT:  none                                                                               *
   1862  *                                                                                             *
   1863  * WARNINGS:   none                                                                            *
   1864  *                                                                                             *
   1865  * HISTORY:                                                                                    *
   1866  *   01/25/1995 JLB : Created.                                                                 *
   1867  *=============================================================================================*/
   1868 void HouseClass::Harvested(unsigned tiberium)
   1869 {
   1870 	assert(Houses.ID(this) == ID);
   1871 
   1872 	long oldtib = Tiberium;
   1873 
   1874 	Tiberium += tiberium;
   1875 	if (Tiberium > Capacity) {
   1876 		Tiberium = Capacity;
   1877 		IsMaxedOut = true;
   1878 	}
   1879 	HarvestedCredits += tiberium;
   1880 	Silo_Redraw_Check(oldtib, Capacity);
   1881 }
   1882 
   1883 
   1884 /***********************************************************************************************
   1885  * HouseClass::Stole -- Accounts for the value of a captured building.								  *
   1886  *                                                                                             *
   1887  *    Use this routine whenever a building is captured.  It keeps track of the cost of the     *
   1888  *    building for use in the scoring routine, because you get an 'economy' boost for the      *
   1889  *    value of the stolen building (but you don't get the credit value for it.)                *
   1890  *                                                                                             *
   1891  * INPUT:   worth -- The worth of the building we captured (stole).            					  *
   1892  *                                                                                             *
   1893  * OUTPUT:  none                                                                               *
   1894  *                                                                                             *
   1895  * WARNINGS:   none                                                                            *
   1896  *                                                                                             *
   1897  * HISTORY:                                                                                    *
   1898  *   09/05/1996 BWG : Created.                                                                 *
   1899  *=============================================================================================*/
   1900 void HouseClass::Stole(unsigned worth)
   1901 {
   1902 	assert(Houses.ID(this) == ID);
   1903 
   1904 	StolenBuildingsCredits += worth;
   1905 }
   1906 
   1907 
   1908 /***********************************************************************************************
   1909  * HouseClass::Available_Money -- Fetches the total credit worth of the house.                 *
   1910  *                                                                                             *
   1911  *    Use this routine to determine the total credit value of the house. This is the sum of    *
   1912  *    the harvested Tiberium in storage and the initial unspent cash reserves.                 *
   1913  *                                                                                             *
   1914  * INPUT:   none                                                                               *
   1915  *                                                                                             *
   1916  * OUTPUT:  Returns with the total credit value of the house.                                  *
   1917  *                                                                                             *
   1918  * WARNINGS:   none                                                                            *
   1919  *                                                                                             *
   1920  * HISTORY:                                                                                    *
   1921  *   01/25/1995 JLB : Created.                                                                 *
   1922  *=============================================================================================*/
   1923 long HouseClass::Available_Money(void) const
   1924 {
   1925 	assert(Houses.ID(this) == ID);
   1926 
   1927 	return(Tiberium + Credits);
   1928 }
   1929 
   1930 
   1931 /***********************************************************************************************
   1932  * HouseClass::Spend_Money -- Removes money from the house.                                    *
   1933  *                                                                                             *
   1934  *    Use this routine to extract money from the house. Typically, this is a result of         *
   1935  *    production spending. The money is extracted from available cash reserves first. When     *
   1936  *    cash reserves are exhausted, then Tiberium is consumed.                                  *
   1937  *                                                                                             *
   1938  * INPUT:   money -- The amount of money to spend.                                             *
   1939  *                                                                                             *
   1940  * OUTPUT:  none                                                                               *
   1941  *                                                                                             *
   1942  * WARNINGS:   none                                                                            *
   1943  *                                                                                             *
   1944  * HISTORY:                                                                                    *
   1945  *   01/25/1995 JLB : Created.                                                                 *
   1946  *   06/20/1995 JLB : Spends Tiberium before spending cash.                                    *
   1947  *=============================================================================================*/
   1948 void HouseClass::Spend_Money(unsigned money)
   1949 {
   1950 	assert(Houses.ID(this) == ID);
   1951 
   1952 	long oldtib = Tiberium;
   1953 	if (money > (unsigned)Tiberium) {
   1954 		money -= (unsigned)Tiberium;
   1955 		Tiberium = 0;
   1956 		Credits -= money;
   1957 	} else {
   1958 		Tiberium -= money;
   1959 	}
   1960 	Silo_Redraw_Check(oldtib, Capacity);
   1961 	CreditsSpent += money;
   1962 }
   1963 
   1964 
   1965 /***********************************************************************************************
   1966  * HouseClass::Refund_Money -- Refunds money to back to the house.                             *
   1967  *                                                                                             *
   1968  *    Use this routine when money needs to be refunded back to the house. This can occur when  *
   1969  *    construction is aborted. At this point, the exact breakdown of Tiberium or initial       *
   1970  *    credits used for the orignal purchase is lost. Presume as much of the money is in the    *
   1971  *    form of Tiberium as storage capacity will allow.                                         *
   1972  *                                                                                             *
   1973  * INPUT:   money -- The number of credits to refund back to the house.                        *
   1974  *                                                                                             *
   1975  * OUTPUT:  none                                                                               *
   1976  *                                                                                             *
   1977  * WARNINGS:   none                                                                            *
   1978  *                                                                                             *
   1979  * HISTORY:                                                                                    *
   1980  *   01/25/1995 JLB : Created.                                                                 *
   1981  *   06/01/1995 JLB : Refunded money is never lost                                             *
   1982  *=============================================================================================*/
   1983 void HouseClass::Refund_Money(unsigned money)
   1984 {
   1985 	assert(Houses.ID(this) == ID);
   1986 
   1987 	Credits += money;
   1988 }
   1989 
   1990 
   1991 /***********************************************************************************************
   1992  * HouseClass::Adjust_Capacity -- Adjusts the house Tiberium storage capacity.                 *
   1993  *                                                                                             *
   1994  *    Use this routine to adjust the maximum storage capacity for the house. This storage      *
   1995  *    capacity will limit the number of Tiberium credits that can be stored at any one time.   *
   1996  *                                                                                             *
   1997  * INPUT:   adjust   -- The adjustment to the Tiberium storage capacity.                       *
   1998  *                                                                                             *
   1999  *          inanger  -- Is this a forced adjustment to capacity due to some hostile event?     *
   2000  *                                                                                             *
   2001  * OUTPUT:  Returns with the number of Tiberium credits lost.                                  *
   2002  *                                                                                             *
   2003  * WARNINGS:   none                                                                            *
   2004  *                                                                                             *
   2005  * HISTORY:                                                                                    *
   2006  *   01/25/1995 JLB : Created.                                                                 *
   2007  *=============================================================================================*/
   2008 int HouseClass::Adjust_Capacity(int adjust, bool inanger)
   2009 {
   2010 	assert(Houses.ID(this) == ID);
   2011 
   2012 	long oldcap = Capacity;
   2013 	int retval = 0;
   2014 
   2015 	Capacity += adjust;
   2016 	Capacity = max(Capacity, 0L);
   2017 	if (Tiberium > Capacity) {
   2018 		retval = Tiberium - Capacity;
   2019 		Tiberium = Capacity;
   2020 		if (!inanger) {
   2021 			Refund_Money(retval);
   2022 			retval = 0;
   2023 		} else {
   2024 			IsMaxedOut = true;
   2025 		}
   2026 	}
   2027 	Silo_Redraw_Check(Tiberium, oldcap);
   2028 	return(retval);
   2029 }
   2030 
   2031 
   2032 /***********************************************************************************************
   2033  * HouseClass::Silo_Redraw_Check -- Flags silos to be redrawn if necessary.                    *
   2034  *                                                                                             *
   2035  *    Call this routine when either the capacity or tiberium levels change for a house. This   *
   2036  *    routine will determine if the aggregate tiberium storage level will result in the        *
   2037  *    silos changing their imagery. If this is detected, then all the silos for this house     *
   2038  *    are flagged to be redrawn.                                                               *
   2039  *                                                                                             *
   2040  * INPUT:   oldtib   -- Pre-change tiberium level.                                             *
   2041  *                                                                                             *
   2042  *          oldcap   -- Pre-change tiberium storage capacity.                                  *
   2043  *                                                                                             *
   2044  * OUTPUT:  none                                                                               *
   2045  *                                                                                             *
   2046  * WARNINGS:   none                                                                            *
   2047  *                                                                                             *
   2048  * HISTORY:                                                                                    *
   2049  *   02/02/1995 JLB : Created.                                                                 *
   2050  *=============================================================================================*/
   2051 void HouseClass::Silo_Redraw_Check(long oldtib, long oldcap)
   2052 {
   2053 	assert(Houses.ID(this) == ID);
   2054 
   2055 	int oldratio = 0;
   2056 	if (oldcap) oldratio = (oldtib * 5) / oldcap;
   2057 	int newratio = 0;
   2058 	if (Capacity) newratio = (Tiberium * 5) / Capacity;
   2059 
   2060 	if (oldratio != newratio) {
   2061 		for (int index = 0; index < Buildings.Count(); index++) {
   2062 			BuildingClass * b = Buildings.Ptr(index);
   2063 			if (b && !b->IsInLimbo && b->House == this && *b == STRUCT_STORAGE) {
   2064 				b->Mark(MARK_CHANGE);
   2065 			}
   2066 		}
   2067 	}
   2068 }
   2069 
   2070 
   2071 /***********************************************************************************************
   2072  * HouseClass::Is_Ally -- Determines if the specified house is an ally.                        *
   2073  *                                                                                             *
   2074  *    This routine will determine if the house number specified is a ally to this house.       *
   2075  *                                                                                             *
   2076  * INPUT:   house -- The house number to check to see if it is an ally.                        *
   2077  *                                                                                             *
   2078  * OUTPUT:  Is the house an ally?                                                              *
   2079  *                                                                                             *
   2080  * WARNINGS:   none                                                                            *
   2081  *                                                                                             *
   2082  * HISTORY:                                                                                    *
   2083  *   05/08/1995 JLB : Created.                                                                 *
   2084  *=============================================================================================*/
   2085 bool HouseClass::Is_Ally(HousesType house) const
   2086 {
   2087 	assert(Houses.ID(this) == ID);
   2088 
   2089 	if (house != HOUSE_NONE) {
   2090 		return(((1<<house) & Allies) != 0);
   2091 	}
   2092 	return(false);
   2093 }
   2094 
   2095 
   2096 /***********************************************************************************************
   2097  * HouseClass::Is_Ally -- Determines if the specified house is an ally.                        *
   2098  *                                                                                             *
   2099  *    This routine will examine the specified house and determine if it is an ally.            *
   2100  *                                                                                             *
   2101  * INPUT:   house -- Pointer to the house object to check for ally relationship.               *
   2102  *                                                                                             *
   2103  * OUTPUT:  Is the specified house an ally?                                                    *
   2104  *                                                                                             *
   2105  * WARNINGS:   none                                                                            *
   2106  *                                                                                             *
   2107  * HISTORY:                                                                                    *
   2108  *   05/08/1995 JLB : Created.                                                                 *
   2109  *=============================================================================================*/
   2110 bool HouseClass::Is_Ally(HouseClass const * house) const
   2111 {
   2112 	assert(Houses.ID(this) == ID);
   2113 
   2114 	if (house) {
   2115 		return(Is_Ally(house->Class->House));
   2116 	}
   2117 	return(false);
   2118 }
   2119 
   2120 
   2121 /***********************************************************************************************
   2122  * HouseClass::Is_Ally -- Checks to see if the object is an ally.                              *
   2123  *                                                                                             *
   2124  *    This routine will examine the specified object and return whether it is an ally or not.  *
   2125  *                                                                                             *
   2126  * INPUT:   object   -- The object to examine to see if it is an ally.                         *
   2127  *                                                                                             *
   2128  * OUTPUT:  Is the specified object an ally?                                                   *
   2129  *                                                                                             *
   2130  * WARNINGS:   none                                                                            *
   2131  *                                                                                             *
   2132  * HISTORY:                                                                                    *
   2133  *   05/08/1995 JLB : Created.                                                                 *
   2134  *=============================================================================================*/
   2135 bool HouseClass::Is_Ally(ObjectClass const * object) const
   2136 {
   2137 	assert(Houses.ID(this) == ID);
   2138 
   2139 	if (object) {
   2140 		return(Is_Ally(object->Owner()));
   2141 	}
   2142 	return(false);
   2143 }
   2144 
   2145 
   2146 /***********************************************************************************************
   2147  * HouseClass::Make_Ally -- Make the specified house an ally.                                  *
   2148  *                                                                                             *
   2149  *    This routine will make the specified house an ally to this house. An allied house will   *
   2150  *    not be considered a threat or potential target.                                          *
   2151  *                                                                                             *
   2152  * INPUT:   house -- The house to make an ally of this house.                                  *
   2153  *                                                                                             *
   2154  * OUTPUT:  none                                                                               *
   2155  *                                                                                             *
   2156  * WARNINGS:   none                                                                            *
   2157  *                                                                                             *
   2158  * HISTORY:                                                                                    *
   2159  *   05/08/1995 JLB : Created.                                                                 *
   2160  *   08/08/1995 JLB : Breaks off combat when ally commences.                                   *
   2161  *   10/17/1995 JLB : Added reveal base when allied.                                           *
   2162  *=============================================================================================*/
   2163 void HouseClass::Make_Ally(HousesType house)
   2164 {
   2165 	assert(Houses.ID(this) == ID);
   2166 
   2167 	if (Is_Allowed_To_Ally(house)) {
   2168 
   2169 		Allies |= (1L << house);
   2170 
   2171 		/*
   2172 		**	Don't consider the newfound ally to be an enemy -- of course.
   2173 		*/
   2174 		if (Enemy == house) {
   2175 			Enemy = HOUSE_NONE;
   2176 		}
   2177 
   2178 		if (ScenarioInit) {
   2179 			Control.Allies |= (1L << house);
   2180 		}
   2181 
   2182 		if (Session.Type != GAME_NORMAL && !ScenarioInit) {
   2183 			HouseClass * hptr = HouseClass::As_Pointer(house);
   2184 
   2185 			/*
   2186 			**	An alliance with another human player will cause the computer
   2187 			**	players (if present) to become paranoid.
   2188 			*/
   2189 			if (hptr != NULL && IsHuman && Rule.IsComputerParanoid) {
   2190 //			if (hptr != NULL && hptr->IsHuman) {
   2191 //				if (!hptr->IsHuman) {
   2192 //					hptr->Make_Ally(Class->House);
   2193 //				}
   2194 				Computer_Paranoid();
   2195 			}
   2196 
   2197 			char buffer[80];
   2198 
   2199 			/*
   2200 			**	Sweep through all techno objects and perform a cheeseball tarcom clear to ensure
   2201 			**	that fighting will most likely stop when the cease fire begins.
   2202 			*/
   2203 			for (int index = 0; index < Logic.Count(); index++) {
   2204 				ObjectClass * object = Logic[index];
   2205 
   2206 				if (object != NULL && object->Is_Techno() && !object->IsInLimbo && object->Owner() == Class->House) {
   2207 					TARGET target = ((TechnoClass *)object)->TarCom;
   2208 					if (Target_Legal(target) && As_Techno(target) != NULL) {
   2209 						if (Is_Ally(As_Techno(target))) {
   2210 							((TechnoClass *)object)->Assign_Target(TARGET_NONE);
   2211 						}
   2212 					}
   2213 				}
   2214 			}
   2215 
   2216 			/*
   2217 			**	Cause all structures to be revealed to the house that has been
   2218 			**	allied with.
   2219 			*/
   2220 			if (Rule.IsAllyReveal && house == PlayerPtr->Class->House) {
   2221 				for (int index = 0; index < Buildings.Count(); index++) {
   2222 					BuildingClass const * b = Buildings.Ptr(index);
   2223 
   2224 					if (b && !b->IsInLimbo && (HouseClass *)b->House == this) {
   2225 						Map.Sight_From(Coord_Cell(b->Center_Coord()), b->Class->SightRange, PlayerPtr, false);
   2226 					}
   2227 				}
   2228 			}
   2229 
   2230 			if (IsHuman) {
   2231 				sprintf(buffer, Text_String(TXT_HAS_ALLIED), IniName, HouseClass::As_Pointer(house)->IniName);
   2232 //				sprintf(buffer, Text_String(TXT_HAS_ALLIED), Session.Players[Class->House - HOUSE_MULTI1]->Name, Session.Players[((HouseClass::As_Pointer(house))->Class->House) - HOUSE_MULTI1]->Name);
   2233 				Session.Messages.Add_Message(NULL, 0, buffer, RemapColor, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, TICKS_PER_MINUTE * Rule.MessageDelay);
   2234 			}
   2235 
   2236 #if(TEN)
   2237 			//
   2238 			// Notify the TEN server of the new alliance
   2239 			//
   2240 			if (this == PlayerPtr && hptr != NULL && Session.Type == GAME_TEN) {
   2241 				Send_TEN_Alliance(hptr->IniName, 1);
   2242 			}
   2243 #endif	// TEN
   2244 
   2245 #if(MPATH)
   2246 			//
   2247 			// Notify the MPATH server of the new alliance
   2248 			//
   2249 			//if (this == PlayerPtr && hptr != NULL && Session.Type == GAME_MPATH) {
   2250 				//Send_MPATH_Alliance(hptr->IniName, 1);
   2251 			//}
   2252 #endif	// MPATH
   2253 
   2254 			Map.Flag_To_Redraw(false);
   2255 		}
   2256 	}
   2257 }
   2258 
   2259 
   2260 /***********************************************************************************************
   2261  * HouseClass::Make_Enemy -- Make an enemy of the house specified.                             *
   2262  *                                                                                             *
   2263  *    This routine will flag the house specified so that it will be an enemy to this house.    *
   2264  *    Enemy houses are legal targets for attack.                                               *
   2265  *                                                                                             *
   2266  * INPUT:   house -- The house to make an enemy of this house.                                 *
   2267  *                                                                                             *
   2268  * OUTPUT:  none                                                                               *
   2269  *                                                                                             *
   2270  * WARNINGS:   none                                                                            *
   2271  *                                                                                             *
   2272  * HISTORY:                                                                                    *
   2273  *   05/08/1995 JLB : Created.                                                                 *
   2274  *   07/27/1995 JLB : Making war is a bilateral action.                                        *
   2275  *=============================================================================================*/
   2276 void HouseClass::Make_Enemy(HousesType house)
   2277 {
   2278 	assert(Houses.ID(this) == ID);
   2279 
   2280 	if (house != HOUSE_NONE && Is_Ally(house)) {
   2281 		HouseClass * enemy = HouseClass::As_Pointer(house);
   2282 		Allies &= ~(1L << house);
   2283 
   2284 		if (ScenarioInit) {
   2285 			Control.Allies &= !(1L << house);
   2286 		}
   2287 
   2288 		/*
   2289 		**	Breaking an alliance is a bilateral event.
   2290 		*/
   2291 		if (enemy != NULL && enemy->Is_Ally(this)) {
   2292 			enemy->Allies &= ~(1L << Class->House);
   2293 
   2294 			if (ScenarioInit) {
   2295 				Control.Allies &= ~(1L << Class->House);
   2296 			}
   2297 		}
   2298 
   2299 		if ((Debug_Flag || Session.Type != GAME_NORMAL) && !ScenarioInit && IsHuman) {
   2300 			char buffer[80];
   2301 
   2302 			sprintf(buffer, Text_String(TXT_AT_WAR), IniName, HouseClass::As_Pointer(house)->IniName);
   2303 //			sprintf(buffer, Text_String(TXT_AT_WAR), Session.Players[Class->House - HOUSE_MULTI1]->Name, Session.Players[enemy->Class->House - HOUSE_MULTI1]->Name);
   2304 			Session.Messages.Add_Message(NULL, 0, buffer, RemapColor, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, TICKS_PER_MINUTE * Rule.MessageDelay);
   2305 			Map.Flag_To_Redraw(false);
   2306 
   2307 #if(TEN)
   2308 			//
   2309 			// Notify the TEN server of the broken alliance
   2310 			//
   2311 			if (this == PlayerPtr && enemy != NULL && Session.Type == GAME_TEN) {
   2312 				Send_TEN_Alliance(enemy->IniName, 0);
   2313 			}
   2314 #endif	// TEN
   2315 
   2316 #if(MPATH)
   2317 			//
   2318 			// Notify the MPATH server of the broken alliance
   2319 			//
   2320 			//if (this == PlayerPtr && enemy != NULL && Session.Type == GAME_MPATH) {
   2321 				//Send_MPATH_Alliance(enemy->IniName, 0);
   2322 			//}
   2323 #endif	// MPATH
   2324 
   2325 		}
   2326 	}
   2327 }
   2328 
   2329 
   2330 /***********************************************************************************************
   2331  * HouseClass::Remap_Table -- Fetches the remap table for this house object.                   *
   2332  *                                                                                             *
   2333  *    This routine will return with the remap table to use when displaying an object owned     *
   2334  *    by this house. If the object is blushing (flashing), then the lightening remap table is  *
   2335  *    always used. The "unit" parameter allows proper remap selection for those houses that    *
   2336  *    have a different remap table for buildings or units.                                     *
   2337  *                                                                                             *
   2338  * INPUT:   blushing -- Is the object blushing (flashing)?                                     *
   2339  *                                                                                             *
   2340  *          remap    -- The remap control value to use.                                        *
   2341  *                      REMAP_NONE     No remap pointer returned at all.                       *
   2342  *                      REMAP_NORMAL   Return the remap pointer for this house.                *
   2343  *                      REMAP_ALTERNATE   (Nod solo play only -- forces red remap).            *
   2344  *                                        Multiplay returns same as REMAP_NORMAL               *
   2345  *                                                                                             *
   2346  * OUTPUT:  Returns with a pointer to the remap table to use when drawing this object.         *
   2347  *                                                                                             *
   2348  * WARNINGS:   none                                                                            *
   2349  *                                                                                             *
   2350  * HISTORY:                                                                                    *
   2351  *   05/08/1995 JLB : Created.                                                                 *
   2352  *   10/25/1995 JLB : Uses remap control value.                                                *
   2353  *=============================================================================================*/
   2354 unsigned char const * HouseClass::Remap_Table(bool blushing, RemapType remap) const
   2355 {
   2356 	assert(Houses.ID(this) == ID);
   2357 
   2358 	if (blushing) return(&Map.FadingLight[0]);
   2359 
   2360 	if (remap == REMAP_NONE) return(0);
   2361 
   2362 	return(ColorRemaps[RemapColor].RemapTable);
   2363 }
   2364 
   2365 
   2366 /***********************************************************************************************
   2367  * HouseClass::Suggested_New_Team -- Determine what team should be created.                    *
   2368  *                                                                                             *
   2369  *    This routine examines the house condition and returns with the team that it thinks       *
   2370  *    should be created. The units that are not currently a member of a team are examined      *
   2371  *    to determine the team needed.                                                            *
   2372  *                                                                                             *
   2373  * INPUT:   alertcheck  -- Select from the auto-create team list.                              *
   2374  *                                                                                             *
   2375  * OUTPUT:  Returns with a pointer to the team type that should be created. If no team should  *
   2376  *          be created, then NULL is returned.                                                 *
   2377  *                                                                                             *
   2378  * WARNINGS:   none                                                                            *
   2379  *                                                                                             *
   2380  * HISTORY:                                                                                    *
   2381  *   05/08/1995 JLB : Created.                                                                 *
   2382  *=============================================================================================*/
   2383 TeamTypeClass const * HouseClass::Suggested_New_Team(bool alertcheck)
   2384 {
   2385 	assert(Houses.ID(this) == ID);
   2386 
   2387 	return(TeamTypeClass::Suggested_New_Team(this, AScan, UScan, IScan, VScan, alertcheck));
   2388 }
   2389 
   2390 
   2391 /***********************************************************************************************
   2392  * HouseClass::Adjust_Threat -- Adjust threat for the region specified.                        *
   2393  *                                                                                             *
   2394  *    This routine is called when the threat rating for a region needs to change. The region   *
   2395  *    and threat adjustment are provided.                                                      *
   2396  *                                                                                             *
   2397  * INPUT:   region   -- The region that adjustment is to occur on.                             *
   2398  *                                                                                             *
   2399  *          threat   -- The threat adjustment to perform.                                      *
   2400  *                                                                                             *
   2401  * OUTPUT:  none                                                                               *
   2402  *                                                                                             *
   2403  * WARNINGS:   none                                                                            *
   2404  *                                                                                             *
   2405  * HISTORY:                                                                                    *
   2406  *   05/08/1995 JLB : Created.                                                                 *
   2407  *=============================================================================================*/
   2408 void HouseClass::Adjust_Threat(int region, int threat)
   2409 {
   2410 	assert(Houses.ID(this) == ID);
   2411 
   2412 	static int _val[] = {
   2413 		-MAP_REGION_WIDTH - 1,	-MAP_REGION_WIDTH, -MAP_REGION_WIDTH + 1,
   2414 		-1,							0,						 1,
   2415 		MAP_REGION_WIDTH -1,		MAP_REGION_WIDTH,	 MAP_REGION_WIDTH +1
   2416 	};
   2417 	static int _thr[] = {
   2418 		2, 1, 2,
   2419 		1, 0, 1,
   2420 		2, 1,	2
   2421 	};
   2422 	int neg;
   2423 	int * val = &_val[0];
   2424 	int * thr = &_thr[0];
   2425 
   2426 	if (threat < 0) {
   2427 		threat = -threat;
   2428 		neg = true;
   2429 	} else {
   2430 		neg = false;
   2431 	}
   2432 
   2433 	for (int lp = 0; lp < 9; lp ++) {
   2434 		Regions[region + *val].Adjust_Threat(threat >> *thr, neg);
   2435 		val++;
   2436 		thr++;
   2437 	}
   2438 }
   2439 
   2440 
   2441 /***********************************************************************************************
   2442  * HouseClass::Begin_Production -- Starts production of the specified object type.             *
   2443  *                                                                                             *
   2444  *    This routine is called from the event system. It will start production for the object    *
   2445  *    type specified. This will be reflected in the sidebar as well as the house factory       *
   2446  *    tracking variables.                                                                      *
   2447  *                                                                                             *
   2448  * INPUT:   type  -- The type of object to begin production on.                                *
   2449  *                                                                                             *
   2450  *          id    -- The subtype of object.                                                    *
   2451  *                                                                                             *
   2452  * OUTPUT:  Returns with the reason why, or why not, production was started.                   *
   2453  *                                                                                             *
   2454  * WARNINGS:   none                                                                            *
   2455  *                                                                                             *
   2456  * HISTORY:                                                                                    *
   2457  *   05/08/1995 JLB : Created.                                                                 *
   2458  *   10/21/1996 JLB : Handles max object case.                                                 *
   2459  *=============================================================================================*/
   2460 ProdFailType HouseClass::Begin_Production(RTTIType type, int id)
   2461 {
   2462 	assert(Houses.ID(this) == ID);
   2463 	int result = true;
   2464 	bool initial_start = false;
   2465 	FactoryClass * fptr;
   2466 	TechnoTypeClass const * tech = Fetch_Techno_Type(type, id);
   2467 
   2468 	fptr = Fetch_Factory(type);
   2469 
   2470 	/*
   2471 	**	If the house is already busy producing the requested object, then
   2472 	**	return with this failure code, unless we are restarting production.
   2473 	*/
   2474 	if (fptr != NULL) {
   2475 		if (fptr->Is_Building()) {
   2476 			return(PROD_CANT);
   2477 		}
   2478 	} else {
   2479 		fptr = new FactoryClass();
   2480 		if (!fptr) return(PROD_CANT);
   2481 		Set_Factory(type, fptr);
   2482 		result = fptr->Set(*tech, *this);
   2483 		initial_start = true;
   2484 
   2485 		/*
   2486 		** If set failed, we probably reached the production cap. Don't let the factory linger, preventing further production attempts.
   2487 		** ST - 3/17/2020 2:03PM
   2488 		*/
   2489 		if (!result) {
   2490 			Set_Factory(type, NULL);
   2491 			delete fptr;
   2492 			fptr = NULL;
   2493 		}
   2494 	}
   2495 
   2496 	if (result) {
   2497 		fptr->Start();
   2498 
   2499 		/*
   2500 		**	Link this factory to the sidebar so that proper graphic feedback
   2501 		**	can take place.
   2502 		*/
   2503 		// Handle Glyphx multiplayer sidebar. ST - 8/14/2019 1:26PM
   2504 		if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   2505 			if (IsHuman) {
   2506 				Sidebar_Glyphx_Factory_Link(fptr->ID, type, id, this);
   2507 			}
   2508 		} else {		 
   2509 			if (PlayerPtr == this) {
   2510 				Map.Factory_Link(fptr->ID, type, id);
   2511 			}
   2512 		}
   2513 
   2514 		return(PROD_OK);
   2515 	}
   2516 
   2517 	delete fptr;
   2518 	return(PROD_CANT);
   2519 }
   2520 
   2521 
   2522 /***********************************************************************************************
   2523  * HouseClass::Suspend_Production -- Temporarily puts production on hold.                      *
   2524  *                                                                                             *
   2525  *    This routine is called from the event system whenever the production of the specified    *
   2526  *    type needs to be suspended. The suspended production will be reflected in the sidebar    *
   2527  *    as well as in the house control structure.                                               *
   2528  *                                                                                             *
   2529  * INPUT:   type  -- The type of object that production is being suspended for.                *
   2530  *                                                                                             *
   2531  * OUTPUT:  Returns why, or why not, production was suspended.                                 *
   2532  *                                                                                             *
   2533  * WARNINGS:   none                                                                            *
   2534  *                                                                                             *
   2535  * HISTORY:                                                                                    *
   2536  *   05/08/1995 JLB : Created.                                                                 *
   2537  *=============================================================================================*/
   2538 ProdFailType HouseClass::Suspend_Production(RTTIType type)
   2539 {
   2540 	assert(Houses.ID(this) == ID);
   2541 
   2542 	FactoryClass * fptr = Fetch_Factory(type);
   2543 
   2544 	/*
   2545 	**	If the house is already busy producing the requested object, then
   2546 	**	return with this failure code.
   2547 	*/
   2548 	if (fptr == NULL) return(PROD_CANT);
   2549 
   2550 	/*
   2551 	**	Actually suspend the production.
   2552 	*/
   2553 	fptr->Suspend();
   2554 
   2555 	/*
   2556 	**	Tell the sidebar that it needs to be redrawn because of this.
   2557 	*/
   2558 	if (PlayerPtr == this) {
   2559 		Map.SidebarClass::IsToRedraw = true;
   2560 		if (!RunningAsDLL) {		// Don't force a redraw when running under GlyphX. PlayerPtr==this will always be true in this case, and we don't want to force a redraw even for AI players
   2561 			Map.Flag_To_Redraw(false);
   2562 		}
   2563 	}
   2564 
   2565 	return(PROD_OK);
   2566 }
   2567 
   2568 
   2569 /***********************************************************************************************
   2570  * HouseClass::Abandon_Production -- Abandons production of item type specified.               *
   2571  *                                                                                             *
   2572  *    This routine is called from the event system whenever production must be abandoned for   *
   2573  *    the type specified. This will remove the factory and pending object from the sidebar as  *
   2574  *    well as from the house factory record.                                                   *
   2575  *                                                                                             *
   2576  * INPUT:   type  -- The object type that production is being suspended for.                   *
   2577  *                                                                                             *
   2578  * OUTPUT:  Returns the reason why or why not, production was suspended.                       *
   2579  *                                                                                             *
   2580  * WARNINGS:   none                                                                            *
   2581  *                                                                                             *
   2582  * HISTORY:                                                                                    *
   2583  *   05/08/1995 JLB : Created.                                                                 *
   2584  *=============================================================================================*/
   2585 ProdFailType HouseClass::Abandon_Production(RTTIType type)
   2586 {
   2587 	assert(Houses.ID(this) == ID);
   2588 
   2589 	FactoryClass * fptr = Fetch_Factory(type);
   2590 
   2591 	/*
   2592 	**	If there is no factory to abandon, then return with a failure code.
   2593 	*/
   2594 	if (fptr == NULL) return(PROD_CANT);
   2595 
   2596 	/*
   2597 	**	Tell the sidebar that it needs to be redrawn because of this.
   2598 	*/
   2599 	// Handle Glyphx multiplayer sidebar. ST - 8/7/2019 10:18AM
   2600 	if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   2601 		if (IsHuman) {
   2602 			Sidebar_Glyphx_Abandon_Production(type, fptr->ID, this);
   2603 			
   2604 			// Need to clear pending object here if legacy renderer enabled
   2605 
   2606 			if (type == RTTI_BUILDINGTYPE || type == RTTI_BUILDING && Map.PendingObjectPtr) {
   2607 				Map.PendingObjectPtr = 0;
   2608 				Map.PendingObject = 0;
   2609 				Map.PendingHouse = HOUSE_NONE;
   2610 				Map.Set_Cursor_Shape(0);
   2611 			}
   2612 		}
   2613 	} else {
   2614 		if (PlayerPtr == this) {
   2615 			Map.Abandon_Production(type, fptr->ID);
   2616 
   2617 			if (type == RTTI_BUILDINGTYPE || type == RTTI_BUILDING) {
   2618 				Map.PendingObjectPtr = 0;
   2619 				Map.PendingObject = 0;
   2620 				Map.PendingHouse = HOUSE_NONE;
   2621 				Map.Set_Cursor_Shape(0);
   2622 			}
   2623 		}
   2624 	}
   2625 
   2626 	/*
   2627 	**	Abandon production of the object.
   2628 	*/
   2629 	fptr->Abandon();
   2630 	Set_Factory(type, NULL);
   2631 	delete fptr;
   2632 
   2633 	return(PROD_OK);
   2634 }
   2635 
   2636 
   2637 /***********************************************************************************************
   2638  * HouseClass::Special_Weapon_AI -- Fires special weapon.                                      *
   2639  *                                                                                             *
   2640  *    This routine will pick a good target to fire the special weapon specified.               *
   2641  *                                                                                             *
   2642  * INPUT:   id -- The special weapon id to fire.                                               *
   2643  *                                                                                             *
   2644  * OUTPUT:  none                                                                               *
   2645  *                                                                                             *
   2646  * WARNINGS:   none                                                                            *
   2647  *                                                                                             *
   2648  * HISTORY:                                                                                    *
   2649  *   06/24/1995 PWG : Created.                                                                 *
   2650  *=============================================================================================*/
   2651 void HouseClass::Special_Weapon_AI(SpecialWeaponType id)
   2652 {
   2653 	assert(Houses.ID(this) == ID);
   2654 
   2655 	/*
   2656 	** Loop through all of the building objects on the map
   2657 	** and see which ones are available.
   2658  	*/
   2659 	BuildingClass * bestptr = NULL;
   2660 	int best = -1;
   2661 
   2662 	for (int index = 0; index < Buildings.Count(); index++) {
   2663 		BuildingClass * b = Buildings.Ptr(index);
   2664 
   2665 		/*
   2666 		** If the building is valid, not in limbo, not in the process of
   2667 		** being destroyed and not our ally, then we can consider it.
   2668 		*/
   2669 		if (b != NULL && !b->IsInLimbo && b->Strength && !Is_Ally(b)) {
   2670 			if (Percent_Chance(90) && (b->Value() > best || best == -1)) {
   2671 				best = b->Value();
   2672 				bestptr = b;
   2673 			}
   2674 		}
   2675 	}
   2676 
   2677 	if (bestptr) {
   2678 		CELL cell = Coord_Cell(bestptr->Center_Coord());
   2679 		Place_Special_Blast(id, cell);
   2680 	}
   2681 }
   2682 
   2683 
   2684 /***********************************************************************************************
   2685  * HouseClass::Place_Special_Blast -- Place a special blast effect at location specified.      *
   2686  *                                                                                             *
   2687  *    This routine will create a blast effect at the cell specified. This is the result of     *
   2688  *    the special weapons.                                                                     *
   2689  *                                                                                             *
   2690  * INPUT:   id    -- The special weapon id number.                                             *
   2691  *                                                                                             *
   2692  *          cell  -- The location where the special weapon attack is to occur.                 *
   2693  *                                                                                             *
   2694  * OUTPUT:  Was the special weapon successfully fired at the location specified?               *
   2695  *                                                                                             *
   2696  * WARNINGS:   none                                                                            *
   2697  *                                                                                             *
   2698  * HISTORY:                                                                                    *
   2699  *   05/18/1995 JLB : commented.                                                               *
   2700  *   07/25/1995 JLB : Added scatter effect for nuclear bomb.                                   *
   2701  *   07/28/1995 JLB : Revamped to use super weapon class controller.                           *
   2702  *=============================================================================================*/
   2703 extern void Logic_Switch_Player_Context(ObjectClass *object);
   2704 extern void Logic_Switch_Player_Context(HouseClass *object);
   2705 extern void On_Special_Weapon_Targetting(const HouseClass* player_ptr, SpecialWeaponType weapon_type);
   2706 
   2707 bool HouseClass::Place_Special_Blast(SpecialWeaponType id, CELL cell)
   2708 {
   2709 	assert(Houses.ID(this) == ID);
   2710 
   2711 	// Added. ST - 12/2/2019 11:26AM
   2712 	bool fired = false;
   2713 	const char *what = NULL;
   2714 
   2715 	BuildingClass * launchsite = 0;
   2716 	AnimClass * anim = 0;
   2717 	switch (id) {
   2718 		case SPC_SONAR_PULSE:
   2719 			// Automatically discharge the sonar pulse and uncloak all subs.
   2720 			if (SuperWeapon[SPC_SONAR_PULSE].Is_Ready()) {
   2721 				SuperWeapon[SPC_SONAR_PULSE].Discharged(this == PlayerPtr);
   2722 				if (this == PlayerPtr) {
   2723 					Map.Column[1].Flag_To_Redraw();
   2724 					Map.Activate_Pulse();
   2725 				}
   2726 				Sound_Effect(VOC_SONAR);
   2727 				IsRecalcNeeded = true;
   2728 				fired = true;
   2729 				what = "SONAR";
   2730 				for (int index = 0; index < Vessels.Count(); index++) {
   2731 					VesselClass * sub = Vessels.Ptr(index);
   2732 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2733 					if (*sub == VESSEL_SS || *sub == VESSEL_MISSILESUB) {
   2734 #else
   2735 					if (*sub == VESSEL_SS) {
   2736 #endif
   2737 						sub->PulseCountDown = 15 * TICKS_PER_SECOND;
   2738 						sub->Do_Uncloak();
   2739 					}
   2740 				}
   2741 			}
   2742 			break;
   2743 
   2744 		case SPC_NUCLEAR_BOMB:
   2745 			if (SuperWeapon[SPC_NUCLEAR_BOMB].Is_Ready()) {
   2746 				if (SuperWeapon[SPC_NUCLEAR_BOMB].Is_One_Time()) {
   2747 					BulletClass * bullet = new BulletClass(BULLET_NUKE_DOWN, ::As_Target(cell), 0, 200, WARHEAD_NUKE, MPH_VERY_FAST);
   2748 					if (bullet) {
   2749 						int celly = Cell_Y(cell);
   2750 						celly -= 15;
   2751 						if (celly < 1) celly = 1;
   2752 						COORDINATE start = Cell_Coord(XY_Cell(Cell_X(cell), celly));
   2753 						if (!bullet->Unlimbo(start, DIR_S)) {
   2754 							delete bullet;
   2755 						}
   2756 						SuperWeapon[SPC_NUCLEAR_BOMB].Discharged(this == PlayerPtr);
   2757 						IsRecalcNeeded = true;
   2758 						fired = true;
   2759 						what = "NUKE";
   2760 						if (this == PlayerPtr) {
   2761 							Map.Column[1].Flag_To_Redraw();
   2762 							Map.IsTargettingMode = SPC_NONE;
   2763 						}
   2764 					}
   2765 				} else {
   2766 
   2767 					/*
   2768 					**	Search for a suitable launch site for this missile.
   2769 					*/
   2770 					launchsite = Find_Building(STRUCT_MSLO);
   2771 
   2772 					/*
   2773 					**	If a launch site was found, then proceed with the normal launch
   2774 					**	sequence.
   2775 					*/
   2776 					if (launchsite) {
   2777 						launchsite->Assign_Mission(MISSION_MISSILE);
   2778 						launchsite->Commence();
   2779 						NukeDest = cell;
   2780 					}
   2781 					if (this == PlayerPtr) {
   2782 						Map.IsTargettingMode = SPC_NONE;
   2783 					}
   2784 					SuperWeapon[SPC_NUCLEAR_BOMB].Discharged(this == PlayerPtr);
   2785 					IsRecalcNeeded = true;
   2786 					fired = true;
   2787 					what = "NUKE";
   2788 				}
   2789 			}
   2790 			break;
   2791 
   2792 		case SPC_PARA_INFANTRY:
   2793 			if (SuperWeapon[SPC_PARA_INFANTRY].Is_Ready()) {
   2794 
   2795 				TeamTypeClass * ttype = TeamTypeClass::As_Pointer("@PINF");
   2796 				if (ttype == NULL) {
   2797 					ttype = new TeamTypeClass;
   2798 					if (ttype != NULL) {
   2799 						strcpy(ttype->IniName, "@PINF");
   2800 						ttype->IsTransient = true;
   2801 						ttype->IsPrebuilt = false;
   2802 						ttype->IsReinforcable = false;
   2803 						ttype->Origin = WAYPT_SPECIAL;
   2804 						ttype->MissionCount = 1;
   2805 						ttype->MissionList[0].Mission = TMISSION_ATT_WAYPT;
   2806 						ttype->MissionList[0].Data.Value = WAYPT_SPECIAL;
   2807 						ttype->ClassCount = 2;
   2808 						ttype->Members[0].Quantity = AircraftTypeClass::As_Reference(AIRCRAFT_BADGER).Max_Passengers();
   2809 						ttype->Members[0].Class = &InfantryTypeClass::As_Reference(INFANTRY_E1);
   2810 						ttype->Members[1].Quantity = 1;
   2811 						ttype->Members[1].Class = &AircraftTypeClass::As_Reference(AIRCRAFT_BADGER);
   2812 					}
   2813 				}
   2814 
   2815 				if (ttype != NULL) {
   2816 					ttype->House = Class->House;
   2817 					Scen.Waypoint[WAYPT_SPECIAL] = Map.Nearby_Location(cell, SPEED_FOOT);
   2818 					Do_Reinforcements(ttype);
   2819 				}
   2820 
   2821 //				Create_Air_Reinforcement(this, AIRCRAFT_BADGER, 1, MISSION_HUNT, ::As_Target(cell), TARGET_NONE, INFANTRY_E1);
   2822 				if (this == PlayerPtr) {
   2823 					Map.IsTargettingMode = SPC_NONE;
   2824 				}
   2825 				SuperWeapon[SPC_PARA_INFANTRY].Discharged(this == PlayerPtr);
   2826 				IsRecalcNeeded = true;
   2827 				fired = true;
   2828 				what = "PARA";
   2829 			}
   2830 			break;
   2831 
   2832 		case SPC_SPY_MISSION:
   2833 			if (SuperWeapon[SPC_SPY_MISSION].Is_Ready()) {
   2834 				Create_Air_Reinforcement(this, AIRCRAFT_U2, 1, MISSION_HUNT, ::As_Target(cell), ::As_Target(cell));
   2835 				if (this == PlayerPtr) {
   2836 					Map.IsTargettingMode = SPC_NONE;
   2837 				}
   2838 				SuperWeapon[SPC_SPY_MISSION].Discharged(this == PlayerPtr);
   2839 				IsRecalcNeeded = true;
   2840 				fired = true;
   2841 				what = "SPY";
   2842 			}
   2843 			break;
   2844 
   2845 		case SPC_PARA_BOMB:
   2846 			if (SuperWeapon[SPC_PARA_BOMB].Is_Ready()) {
   2847 				Create_Air_Reinforcement(this, AIRCRAFT_BADGER, Rule.BadgerBombCount, MISSION_HUNT, ::As_Target(cell), TARGET_NONE);
   2848 				if (this == PlayerPtr) {
   2849 					Map.IsTargettingMode = SPC_NONE;
   2850 				}
   2851 				SuperWeapon[SPC_PARA_BOMB].Discharged(this == PlayerPtr);
   2852 				IsRecalcNeeded = true;
   2853 				fired = true;
   2854 				what = "PARABOMB";
   2855 			}
   2856 			break;
   2857 
   2858 		case SPC_IRON_CURTAIN:
   2859 			if (SuperWeapon[SPC_IRON_CURTAIN].Is_Ready()) {
   2860 				int x = Keyboard->MouseQX - Map.TacPixelX;
   2861 				int y = Keyboard->MouseQY - Map.TacPixelY;
   2862 				TechnoClass * tech = Map[cell].Cell_Techno(x, y);
   2863 				if (tech) {
   2864 					switch (tech->What_Am_I()) {
   2865 						case RTTI_UNIT:
   2866 						case RTTI_BUILDING:
   2867 						case RTTI_VESSEL:
   2868 						case RTTI_AIRCRAFT:
   2869 							tech->IronCurtainCountDown = Rule.IronCurtainDuration * TICKS_PER_MINUTE;
   2870 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2871 							if (tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_DEMOTRUCK) {
   2872 								tech->IronCurtainCountDown = Rule.IronCurtainDuration * TICKS_PER_SECOND;
   2873 							}
   2874 #endif
   2875 							tech->Mark(MARK_CHANGE);
   2876 							Sound_Effect(VOC_IRON1, tech->Center_Coord());
   2877 							if (this == PlayerPtr) {
   2878 								Map.IsTargettingMode = SPC_NONE;
   2879 							}
   2880 							SuperWeapon[SPC_IRON_CURTAIN].Discharged(this == PlayerPtr);
   2881 							break;
   2882 						default:
   2883 							break;
   2884 					}
   2885 				}
   2886 
   2887 				IsRecalcNeeded = true;
   2888 				fired = true;
   2889 				what = "IRON";
   2890 			}
   2891 			break;
   2892 
   2893 		case SPC_CHRONOSPHERE:
   2894 			if (SuperWeapon[SPC_CHRONOSPHERE].Is_Ready()) {
   2895 				int x = Keyboard->MouseQX - Map.TacPixelX;
   2896 				int y = Keyboard->MouseQY - Map.TacPixelY;
   2897 				TechnoClass * tech = Map[cell].Cell_Techno(x, y);
   2898 				if (tech && Is_Ally(tech)) {
   2899 					if (tech->What_Am_I() == RTTI_UNIT ||
   2900 						tech->What_Am_I() == RTTI_INFANTRY ||
   2901 #ifdef FIXIT_CARRIER	//	checked - ajw 9/28/98
   2902 						(tech->What_Am_I() == RTTI_VESSEL && (*((VesselClass *)tech) != VESSEL_TRANSPORT && *((VesselClass *)tech) != VESSEL_CARRIER) )) {
   2903 #else
   2904 						(tech->What_Am_I() == RTTI_VESSEL && *((VesselClass *)tech) != VESSEL_TRANSPORT)) {
   2905 #endif
   2906 
   2907 						if (tech->What_Am_I() != RTTI_UNIT || !((UnitClass *)tech)->IsDeploying) {
   2908 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2909 	bool porthim = true;
   2910 	if(tech->What_Am_I() == RTTI_UNIT && ((UnitClass *)tech)->Class->Type == UNIT_CHRONOTANK) {
   2911 		porthim = false;
   2912 	}
   2913 	if (porthim) {
   2914 #endif
   2915 							HouseClass* old_player_ptr = PlayerPtr;
   2916 							Logic_Switch_Player_Context(this);
   2917 							Map.IsTargettingMode = SPC_CHRONO2;
   2918 							On_Special_Weapon_Targetting(PlayerPtr, Map.IsTargettingMode);
   2919 							Logic_Switch_Player_Context(old_player_ptr);
   2920 							UnitToTeleport = tech->As_Target();
   2921 							fired = true;
   2922 							what = "CHRONO";
   2923 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2924 	}
   2925 #endif
   2926 						}
   2927 					}
   2928 				}
   2929 			}
   2930 			break;
   2931 
   2932 		case SPC_CHRONO2:
   2933 			{
   2934 				TechnoClass * tech = (TechnoClass *)::As_Object(UnitToTeleport);
   2935 				CELL oldcell = cell;
   2936 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2937 				if (tech != NULL && tech->IsActive && tech->Is_Foot() && tech->What_Am_I() != RTTI_AIRCRAFT) {
   2938 #else
   2939 				if (tech != NULL && tech->Is_Foot() && tech->What_Am_I() != RTTI_AIRCRAFT) {
   2940 #endif
   2941 					/*
   2942 					** Destroy any infantryman that gets teleported
   2943 					*/
   2944 					if (tech->What_Am_I() == RTTI_INFANTRY) {
   2945 						InfantryClass * inf = (InfantryClass *)tech;
   2946 						inf->Mark(MARK_UP);
   2947 						inf->Coord = Cell_Coord(cell);
   2948 						inf->Mark(MARK_DOWN);
   2949 						int damage = inf->Strength;
   2950 						inf->Take_Damage(damage, 0, WARHEAD_FIRE, 0, true);
   2951 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2952 					} else if(tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_DEMOTRUCK) {
   2953 						tech->Assign_Target(tech->As_Target());
   2954 #endif
   2955 					} else {
   2956 						/*
   2957 						**	Warp the unit to the new location.
   2958 						*/
   2959 						DriveClass * drive = (DriveClass *)tech;
   2960 						drive->MoebiusCell = Coord_Cell(drive->Coord);
   2961 						oldcell = drive->MoebiusCell;
   2962 						drive->Teleport_To(cell);
   2963 						drive->IsMoebius = true;
   2964 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2965 	if(tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_CHRONOTANK) {
   2966 		drive->IsMoebius = false;
   2967 	}
   2968 	drive->MoebiusCountDown = Rule.ChronoDuration * TICKS_PER_MINUTE;
   2969 	if (tech->What_Am_I() == RTTI_UNIT && *(UnitClass *)tech == UNIT_CHRONOTANK) {
   2970 		drive->MoebiusCountDown = ChronoTankDuration * TICKS_PER_MINUTE;
   2971 	}
   2972 #else
   2973 						drive->MoebiusCountDown = Rule.ChronoDuration * TICKS_PER_MINUTE;
   2974 #endif
   2975 						Scen.Do_BW_Fade();
   2976 						Sound_Effect(VOC_CHRONO, drive->Coord);
   2977 
   2978 						/*
   2979 						**	Set active animation on Chronospheres.
   2980 						*/
   2981 						for (int index = 0; index < Buildings.Count(); ++index) {
   2982 							BuildingClass* building = Buildings.Ptr(index);
   2983 							if (building != nullptr && building->IsActive && building->Owner() == Class->House && *building == STRUCT_CHRONOSPHERE) {
   2984 								building->Begin_Mode(BSTATE_ACTIVE);
   2985 							}
   2986 						}
   2987 					}
   2988 				}
   2989 				UnitToTeleport = TARGET_NONE;
   2990 				if (this == PlayerPtr) {
   2991 					Map.IsTargettingMode = SPC_NONE;
   2992 				}
   2993 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2994 	if(tech && tech->IsActive && (tech->What_Am_I() != RTTI_UNIT || *(UnitClass *)tech != UNIT_CHRONOTANK)) {
   2995 #endif
   2996 				SuperWeapon[SPC_CHRONOSPHERE].Discharged(this == PlayerPtr);
   2997 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   2998 	}
   2999 #endif
   3000 				IsRecalcNeeded = true;
   3001 				fired = true;
   3002 				what = "CHRONO2";
   3003 
   3004 				/*
   3005 				** Now set a percentage chance that a time quake will occur.
   3006 				*/
   3007 				if (!TimeQuake) {
   3008 					TimeQuake = Percent_Chance(Rule.QuakeChance * 100);
   3009 				}
   3010 
   3011 				/*
   3012 				** Now set a percentage chance that a chronal vortex will appear. It
   3013 				**	might appear where the object teleported to or it might appear
   3014 				**	where it teleported from -- random chance.
   3015 				*/
   3016 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   3017 // Don't allow a vortex if the teleportation was due to a chrono tank.
   3018 	if(tech && tech->IsActive && (tech->What_Am_I() != RTTI_UNIT || *(UnitClass *)tech != UNIT_CHRONOTANK))
   3019 #endif
   3020 				if (!ChronalVortex.Is_Active() && Percent_Chance(Rule.VortexChance * 100)) {
   3021 					int x = Random_Pick(0, Map.MapCellWidth-1);
   3022 					int y = Random_Pick(0, Map.MapCellHeight-1);
   3023 					ChronalVortex.Appear(Cell_Coord(XY_Cell(Map.MapCellX + x, Map.MapCellY + y)));
   3024 
   3025 //					if (Percent_Chance(50)) {
   3026 //						ChronalVortex.Appear(Cell_Coord(oldcell));
   3027 //					} else {
   3028 //						ChronalVortex.Appear(Cell_Coord(cell));
   3029 //					}
   3030 				}
   3031 
   3032 				break;
   3033 			}
   3034 	}
   3035 
   3036 	/*
   3037 	** Maybe trigger an achivement. ST - 12/2/2019 11:25AM
   3038 	*/
   3039 	if (IsHuman && fired && what) {
   3040 		On_Achievement_Event(this, "SUPERWEAPON_FIRED", what);
   3041 	}
   3042 
   3043 	return(true);
   3044 }
   3045 
   3046 
   3047 /***********************************************************************************************
   3048  * HouseClass::Place_Object -- Places the object (building) at location specified.             *
   3049  *                                                                                             *
   3050  *    This routine is called when a building has been produced and now must be placed on       *
   3051  *    the map. When the player clicks on the map, this routine is ultimately called when the   *
   3052  *    event passes through the event queue system.                                             *
   3053  *                                                                                             *
   3054  * INPUT:   type  -- The object type to place. The actual object is lifted from the sidebar.   *
   3055  *                                                                                             *
   3056  *                                                                                             *
   3057  *          cell  -- The location to place the object on the map.                              *
   3058  *                                                                                             *
   3059  * OUTPUT:  Was the placement successful?                                                      *
   3060  *                                                                                             *
   3061  * WARNINGS:   none                                                                            *
   3062  *                                                                                             *
   3063  * HISTORY:                                                                                    *
   3064  *   05/18/1995 JLB : Created.                                                                 *
   3065  *=============================================================================================*/
   3066 extern void On_Ping(const HouseClass* player_ptr, COORDINATE coord);
   3067 
   3068 bool HouseClass::Place_Object(RTTIType type, CELL cell)
   3069 {
   3070 	assert(Houses.ID(this) == ID);
   3071 
   3072 	TechnoClass * tech = 0;
   3073 	FactoryClass * factory = Fetch_Factory(type);
   3074 
   3075 	/*
   3076 	**	Only if there is a factory active for this type, can it be "placed".
   3077 	**	In the case of a missing factory, then this request is completely bogus --
   3078 	**	ignore it. This might occur if, between two events to exit the same
   3079 	**	object, the mouse was clicked on the sidebar to start building again.
   3080 	**	The second placement event should NOT try to place the object that is
   3081 	**	just starting construction.
   3082 	*/
   3083 	if (factory && factory->Has_Completed()) {
   3084 		tech = factory->Get_Object();
   3085 
   3086 		if (cell == -1) {
   3087 			TechnoClass * pending = factory->Get_Object();
   3088 			if (pending != NULL) {
   3089 
   3090 #ifdef FIXIT_HELI_LANDING
   3091 				/*
   3092 				**	Try to find a place for the object to appear from. For helicopters, it has the
   3093 				**	option of finding a nearby helipad if no helipads are free.
   3094 				*/
   3095 				TechnoClass * builder = pending->Who_Can_Build_Me(false, false);
   3096 				if (builder == NULL && pending->What_Am_I() == RTTI_AIRCRAFT && !((AircraftClass *)pending)->Class->IsFixedWing) {
   3097 					builder = pending->Who_Can_Build_Me(true, false);
   3098 
   3099 				}
   3100 #else
   3101 				bool intheory = false;
   3102 				if (pending->What_Am_I() == RTTI_AIRCRAFT) {
   3103 
   3104 					/*
   3105 					** BG hack - helicopters don't need a specific building to
   3106 					** emerge from, in fact, they'll land next to a building if
   3107 					** need be.
   3108 					*/
   3109 					if( !((AircraftClass *)pending)->Class->IsFixedWing) {
   3110 						intheory = true;
   3111 					}
   3112 				}
   3113 				TechnoClass * builder = pending->Who_Can_Build_Me(intheory, false);
   3114 #endif
   3115 				TechnoTypeClass const *object_type = pending->Techno_Type_Class();
   3116 				if (builder != NULL && builder->Exit_Object(pending)) {
   3117 
   3118 					/*
   3119 					**	Since the object has left the factory under its own power, delete
   3120 					**	the production manager tied to this slot in the sidebar. Its job
   3121 					**	has been completed.
   3122 					*/
   3123 					factory->Set_Is_Blocked(false);
   3124 					factory->Completed();
   3125 					Abandon_Production(type);
   3126 
   3127 					/*
   3128 					** Could be tied to an achievement. ST - 11/11/2019 11:56AM
   3129 					*/
   3130 					if (IsHuman) {
   3131 						if (object_type) {
   3132 							On_Achievement_Event(this, "UNIT_CONSTRUCTED", object_type->IniName);
   3133 						}
   3134 						if (pending->IsActive) {
   3135 							On_Ping(this, pending->Center_Coord());
   3136 						}
   3137 					}
   3138 
   3139 					switch (pending->What_Am_I()) {
   3140 						case RTTI_UNIT:
   3141 							JustBuiltUnit = ((UnitClass*)pending)->Class->Type;
   3142 							IsBuiltSomething = true;
   3143 							break;
   3144 
   3145 						case RTTI_VESSEL:
   3146 							JustBuiltVessel = ((VesselClass*)pending)->Class->Type;
   3147 							IsBuiltSomething = true;
   3148 							break;
   3149 
   3150 						case RTTI_INFANTRY:
   3151 							JustBuiltInfantry = ((InfantryClass*)pending)->Class->Type;
   3152 							IsBuiltSomething = true;
   3153 							break;
   3154 
   3155 						case RTTI_BUILDING:
   3156 							JustBuiltStructure = ((BuildingClass*)pending)->Class->Type;
   3157 							IsBuiltSomething = true;
   3158 							break;
   3159 
   3160 						case RTTI_AIRCRAFT:
   3161 							JustBuiltAircraft = ((AircraftClass*)pending)->Class->Type;
   3162 							IsBuiltSomething = true;
   3163 							break;
   3164 					}
   3165 				} else {
   3166 					/*
   3167 					**	The object could not leave under it's own power. Just wait
   3168 					**	until the player tries to place the object again.
   3169 					*/
   3170 					
   3171 					/*
   3172 					** Flag that it's blocked so we can re-try the exit later.
   3173 					** This would have been a bad idea under the old peer-peer code since it would have pumped events into
   3174 					** the queue too often. ST - 2/25/2020 11:56AM
   3175 					*/
   3176 					factory->Set_Is_Blocked(true);
   3177 					return(false);
   3178 				}
   3179 			}
   3180 
   3181 		} else {
   3182 			if (tech) {
   3183 				TechnoClass * builder = tech->Who_Can_Build_Me(false, false);
   3184 				if (builder) {
   3185 
   3186 					builder->Transmit_Message(RADIO_HELLO, tech);
   3187 					if (tech->Unlimbo(Cell_Coord(cell))) {
   3188 						factory->Completed();
   3189 						Abandon_Production(type);
   3190 
   3191 						if (PlayerPtr == this) {
   3192 							Sound_Effect(VOC_PLACE_BUILDING_DOWN);
   3193 							Map.Set_Cursor_Shape(0);
   3194 							Map.PendingObjectPtr = 0;
   3195 							Map.PendingObject = 0;
   3196 							Map.PendingHouse = HOUSE_NONE;
   3197 						}
   3198 						return(true);
   3199 					} else {
   3200 						if (this == PlayerPtr) {
   3201 							Speak(VOX_DEPLOY);
   3202 						}
   3203 					}
   3204 					builder->Transmit_Message(RADIO_OVER_OUT);
   3205 				}
   3206 				return(false);
   3207 
   3208 			} else {
   3209 
   3210 				// Play a bad sound here?
   3211 				return(false);
   3212 			}
   3213 		}
   3214 	}
   3215 
   3216 	return(true);
   3217 }
   3218 
   3219 
   3220 /***********************************************************************************************
   3221  * HouseClass::Manual_Place -- Inform display system of building placement mode.               *
   3222  *                                                                                             *
   3223  *    This routine will inform the display system that building placement mode has begun.      *
   3224  *    The cursor will be created that matches the layout of the building shape.                *
   3225  *                                                                                             *
   3226  * INPUT:   builder  -- The factory that is building this object.                              *
   3227  *                                                                                             *
   3228  *          object   -- The building that is going to be placed down on the map.               *
   3229  *                                                                                             *
   3230  * OUTPUT:  Was the building placement mode successfully initiated?                            *
   3231  *                                                                                             *
   3232  * WARNINGS:   This merely adjusts the cursor shape. Nothing that affects networked games      *
   3233  *             is affected.                                                                    *
   3234  *                                                                                             *
   3235  * HISTORY:                                                                                    *
   3236  *   05/04/1995 JLB : Created.                                                                 *
   3237  *   05/30/1995 JLB : Uses the Bib_And_Offset() function to determine bib size.                *
   3238  *=============================================================================================*/
   3239 bool HouseClass::Manual_Place(BuildingClass * builder,  BuildingClass * object)
   3240 {
   3241 	assert(Houses.ID(this) == ID);
   3242 
   3243 	if (this == PlayerPtr && !Map.PendingObject && builder && object) {
   3244 		/*
   3245 		**	Ensures that object selection doesn't remain when
   3246 		**	building placement takes place.
   3247 		*/
   3248 		Unselect_All();
   3249 
   3250 		Map.Repair_Mode_Control(0);
   3251 		Map.Sell_Mode_Control(0);
   3252 
   3253 		Map.PendingObject = object->Class;
   3254 		Map.PendingObjectPtr = object;
   3255 		Map.PendingHouse = Class->House;
   3256 
   3257 		Map.Set_Cursor_Shape(object->Occupy_List(true));
   3258 		Map.Set_Cursor_Pos(Coord_Cell(builder->Coord));
   3259 		builder->Mark(MARK_CHANGE);
   3260 		return(true);
   3261 	}
   3262 	return(false);
   3263 }
   3264 
   3265 
   3266 /***************************************************************************
   3267  * HouseClass::Clobber_All -- removes all objects for this house				*
   3268  *                                                                         *
   3269  * INPUT:                                                                  *
   3270  *      none.                                                              *
   3271  *                                                                         *
   3272  * OUTPUT:                                                                 *
   3273  *      none.                                                              *
   3274  *                                                                         *
   3275  * WARNINGS:                                                               *
   3276  *      This routine removes the house itself, so the multiplayer code		*
   3277  *		  must not rely on there being "empty" houses lying around.				*
   3278  *                                                                         *
   3279  * HISTORY:                                                                *
   3280  *   05/16/1995 BRR : Created.                                             *
   3281  *   06/09/1995 JLB : Handles aircraft.                                    *
   3282  *=========================================================================*/
   3283 void HouseClass::Clobber_All(void)
   3284 {
   3285 	assert(Houses.ID(this) == ID);
   3286 
   3287 	int i;
   3288 
   3289 	for (i = 0; i < ::Aircraft.Count(); i++) {
   3290 		if (::Aircraft.Ptr(i)->House == this) {
   3291 			delete ::Aircraft.Ptr(i);
   3292 			i--;
   3293 		}
   3294 	}
   3295 	for (i = 0; i < ::Units.Count(); i++) {
   3296 		if (::Units.Ptr(i)->House == this) {
   3297 			delete ::Units.Ptr(i);
   3298 			i--;
   3299 		}
   3300 	}
   3301 	for (i = 0; i < ::Vessels.Count(); i++) {
   3302 		if (::Vessels.Ptr(i)->House == this) {
   3303 			delete ::Vessels.Ptr(i);
   3304 			i--;
   3305 		}
   3306 	}
   3307 	for (i = 0; i < Infantry.Count(); i++) {
   3308 		if (Infantry.Ptr(i)->House == this) {
   3309 			delete Infantry.Ptr(i);
   3310 			i--;
   3311 		}
   3312 	}
   3313 	for (i = 0; i < Buildings.Count(); i++) {
   3314 		if (Buildings.Ptr(i)->House == this) {
   3315 			delete Buildings.Ptr(i);
   3316 			i--;
   3317 		}
   3318 	}
   3319 	for (i = 0; i < TeamTypes.Count(); i++) {
   3320 		if (TeamTypes.Ptr(i)->House == Class->House) {
   3321 			delete TeamTypes.Ptr(i);
   3322 			i--;
   3323 		}
   3324 	}
   3325 	for (i = 0; i < Triggers.Count(); i++) {
   3326 		if (Triggers.Ptr(i)->Class->House == Class->House) {
   3327 			delete Triggers.Ptr(i);
   3328 			i--;
   3329 		}
   3330 	}
   3331 	for (i = 0; i < TriggerTypes.Count(); i++) {
   3332 		if (TriggerTypes.Ptr(i)->House == Class->House) {
   3333 			delete TriggerTypes.Ptr(i);
   3334 			i--;
   3335 		}
   3336 	}
   3337 
   3338 	delete this;
   3339 }
   3340 
   3341 
   3342 /***********************************************************************************************
   3343  * HouseClass::Detach -- Removes specified object from house tracking systems.                 *
   3344  *                                                                                             *
   3345  *    This routine is called when an object is to be removed from the game system. If the      *
   3346  *    specified object is part of the house tracking system, then it will be removed.          *
   3347  *                                                                                             *
   3348  * INPUT:   target   -- The target value of the object that is to be removed from the game.    *
   3349  *                                                                                             *
   3350  *          all      -- Is the target going away for good as opposed to just cloaking/hiding?  *
   3351  *                                                                                             *
   3352  * OUTPUT:  none                                                                               *
   3353  *                                                                                             *
   3354  * WARNINGS:   none                                                                            *
   3355  *                                                                                             *
   3356  * HISTORY:                                                                                    *
   3357  *   05/18/1995 JLB : commented                                                                *
   3358  *=============================================================================================*/
   3359 void HouseClass::Detach(TARGET target, bool )
   3360 {
   3361 	assert(Houses.ID(this) == ID);
   3362 
   3363 	if (ToCapture == target) {
   3364 		ToCapture = TARGET_NONE;
   3365 	}
   3366 
   3367 	if (Is_Target_Trigger(target)) {
   3368 		HouseTriggers[ID].Delete(As_Trigger(target));
   3369 	}
   3370 }
   3371 
   3372 
   3373 /***********************************************************************************************
   3374  * HouseClass::Does_Enemy_Building_Exist -- Checks for enemy building of specified type.       *
   3375  *                                                                                             *
   3376  *    This routine will examine the enemy houses and if there is a building owned by one       *
   3377  *    of those house, true will be returned.                                                   *
   3378  *                                                                                             *
   3379  * INPUT:   btype -- The building type to check for.                                           *
   3380  *                                                                                             *
   3381  * OUTPUT:  Does a building of the specified type exist for one of the enemy houses?           *
   3382  *                                                                                             *
   3383  * WARNINGS:   none                                                                            *
   3384  *                                                                                             *
   3385  * HISTORY:                                                                                    *
   3386  *   05/23/1995 JLB : Created.                                                                 *
   3387  *=============================================================================================*/
   3388 bool HouseClass::Does_Enemy_Building_Exist(StructType btype) const
   3389 {
   3390 	assert(Houses.ID(this) == ID);
   3391 
   3392 	int bflag = 1L << btype;
   3393 	for (HousesType index = HOUSE_FIRST; index < HOUSE_COUNT; index++) {
   3394 		HouseClass * house = HouseClass::As_Pointer(index);
   3395 
   3396 		if (house && !Is_Ally(house) && (house->ActiveBScan & bflag) != 0) {
   3397 			return(true);
   3398 		}
   3399 	}
   3400 	return(false);
   3401 }
   3402 
   3403 
   3404 /***********************************************************************************************
   3405  * HouseClass::Suggest_New_Object -- Determine what would the next buildable object be.        *
   3406  *                                                                                             *
   3407  *    This routine will examine the house status and return with a techno type pointer to      *
   3408  *    the object type that it thinks should be created. The type is restricted to match the    *
   3409  *    type specified. Typical use of this routine is by computer controlled factories.         *
   3410  *                                                                                             *
   3411  * INPUT:   objecttype  -- The type of object to restrict the scan for.                        *
   3412  *                                                                                             *
   3413  *          kennel      -- Is this from a kennel? There are special hacks to ensure that only  *
   3414  *                         dogs can be produced from a kennel.                                 *
   3415  *                                                                                             *
   3416  * OUTPUT:  Returns with a pointer to a techno type for the object type that should be         *
   3417  *          created. If no object should be created, then NULL is returned.                    *
   3418  *                                                                                             *
   3419  * WARNINGS:   This is a time consuming routine. Only call when necessary.                     *
   3420  *                                                                                             *
   3421  * HISTORY:                                                                                    *
   3422  *   05/23/1995 JLB : Created.                                                                 *
   3423  *=============================================================================================*/
   3424 TechnoTypeClass const * HouseClass::Suggest_New_Object(RTTIType objecttype, bool kennel) const
   3425 {
   3426 	assert(Houses.ID(this) == ID);
   3427 
   3428 	TechnoTypeClass const * techno = NULL;
   3429 
   3430 	switch (objecttype) {
   3431 		case RTTI_AIRCRAFT:
   3432 		case RTTI_AIRCRAFTTYPE:
   3433 			if (BuildAircraft != AIRCRAFT_NONE) {
   3434 				return(&AircraftTypeClass::As_Reference(BuildAircraft));
   3435 			}
   3436 			return(NULL);
   3437 
   3438 		case RTTI_VESSEL:
   3439 		case RTTI_VESSELTYPE:
   3440 			if (BuildVessel != VESSEL_NONE) {
   3441 				return(&VesselTypeClass::As_Reference(BuildVessel));
   3442 			}
   3443 			return(NULL);
   3444 
   3445 		/*
   3446 		**	Unit construction is based on the rule that up to twice the number required
   3447 		**	to fill all teams will be created.
   3448 		*/
   3449 		case RTTI_UNIT:
   3450 		case RTTI_UNITTYPE:
   3451 			if (BuildUnit != UNIT_NONE) {
   3452 				return(&UnitTypeClass::As_Reference(BuildUnit));
   3453 			}
   3454 			return(NULL);
   3455 
   3456 		/*
   3457 		**	Infantry construction is based on the rule that up to twice the number required
   3458 		**	to fill all teams will be created.
   3459 		*/
   3460 		case RTTI_INFANTRY:
   3461 		case RTTI_INFANTRYTYPE:
   3462 			if (BuildInfantry != INFANTRY_NONE) {
   3463 				if (kennel && BuildInfantry != INFANTRY_DOG) return(NULL);
   3464 				if (!kennel && BuildInfantry == INFANTRY_DOG) return(NULL);
   3465 				return(&InfantryTypeClass::As_Reference(BuildInfantry));
   3466 			}
   3467 			return(NULL);
   3468 
   3469 		/*
   3470 		**	Building construction is based upon the preconstruction list.
   3471 		*/
   3472 		case RTTI_BUILDING:
   3473 		case RTTI_BUILDINGTYPE:
   3474 			if (BuildStructure != STRUCT_NONE) {
   3475 				return(&BuildingTypeClass::As_Reference(BuildStructure));
   3476 			}
   3477 			return(NULL);
   3478 	}
   3479 	return(techno);
   3480 }
   3481 
   3482 
   3483 /***********************************************************************************************
   3484  * HouseClass::Flag_Remove -- Removes the flag from the specified target.                      *
   3485  *                                                                                             *
   3486  *    This routine will remove the flag attached to the specified target object or cell.       *
   3487  *    Call this routine before placing the object down. This is called inherently by the       *
   3488  *    the Flag_Attach() functions.                                                             *
   3489  *                                                                                             *
   3490  * INPUT:   target   -- The target that the flag was attached to but will be removed from.     *
   3491  *                                                                                             *
   3492  *          set_home -- if true, clears the flag's waypoint designation                        *
   3493  *                                                                                             *
   3494  * OUTPUT:  Was the flag successfully removed from the specified target?                       *
   3495  *                                                                                             *
   3496  * WARNINGS:   none                                                                            *
   3497  *                                                                                             *
   3498  * HISTORY:                                                                                    *
   3499  *   05/23/1995 JLB : Created.                                                                 *
   3500  *=============================================================================================*/
   3501 bool HouseClass::Flag_Remove(TARGET target, bool set_home)
   3502 {
   3503 	assert(Houses.ID(this) == ID);
   3504 
   3505 	bool rc = false;
   3506 
   3507 	if (Target_Legal(target)) {
   3508 
   3509 		/*
   3510 		**	Remove the flag from a unit
   3511 		*/
   3512 		UnitClass * object = As_Unit(target);
   3513 		if (object) {
   3514 			rc = object->Flag_Remove();
   3515 			if (rc && FlagLocation == target) {
   3516 				FlagLocation = TARGET_NONE;
   3517 			}
   3518 
   3519 		} else {
   3520 
   3521 			/*
   3522 			**	Remove the flag from a cell
   3523 			*/
   3524 			CELL cell = As_Cell(target);
   3525 			if (Map.In_Radar(cell)) {
   3526 				rc = Map[cell].Flag_Remove();
   3527 				if (rc && FlagLocation == target) {
   3528 					FlagLocation = TARGET_NONE;
   3529 				}
   3530 			}
   3531 		}
   3532 
   3533 		/*
   3534 		**	Handle the flag home cell:
   3535 		**	If 'set_home' is set, clear the home value & the cell's overlay
   3536 		*/
   3537 		if (set_home) {
   3538 			if (FlagHome != 0) {
   3539 				Map[FlagHome].Overlay = OVERLAY_NONE;
   3540 				Map.Flag_Cell(FlagHome);
   3541 				FlagHome = 0;
   3542 			}
   3543 		}
   3544 	}
   3545 	return(rc);
   3546 }
   3547 
   3548 
   3549 /***********************************************************************************************
   3550  * HouseClass::Flag_Attach -- Attach flag to specified cell (or thereabouts).                  *
   3551  *                                                                                             *
   3552  *    This routine will attach the house flag to the location specified. If the location       *
   3553  *    cannot contain the flag, then a suitable nearby location will be selected.               *
   3554  *                                                                                             *
   3555  * INPUT:   cell  -- The desired cell location to place the flag.                              *
   3556  *                                                                                             *
   3557  *          set_home -- if true, resets the flag's waypoint designation                        *
   3558  *                                                                                             *
   3559  * OUTPUT:  Was the flag successfully placed?                                                  *
   3560  *                                                                                             *
   3561  * WARNINGS:   The cell picked for the flag might very likely not be the cell requested.       *
   3562  *             Check the FlagLocation value to determine the final cell resting spot.          *
   3563  *                                                                                             *
   3564  * HISTORY:                                                                                    *
   3565  *   05/23/1995 JLB : Created.                                                                 *
   3566  *   10/08/1996 JLB : Uses map nearby cell scanning handler.                                   *
   3567  *=============================================================================================*/
   3568 bool HouseClass::Flag_Attach(CELL cell, bool set_home)
   3569 {
   3570 	assert(Houses.ID(this) == ID);
   3571 
   3572 	bool rc;
   3573 	bool clockwise;
   3574 
   3575 	/*
   3576 	**	Randomly decide if we're going to search cells clockwise or counter-
   3577 	**	clockwise
   3578 	*/
   3579 	clockwise = Percent_Chance(50);
   3580 
   3581 	/*
   3582 	**	Only continue if this cell is a legal placement cell.
   3583 	*/
   3584 	if (Map.In_Radar(cell)) {
   3585 
   3586 		/*
   3587 		**	If the flag already exists, then it must be removed from the object
   3588 		**	it is attached to.
   3589 		*/
   3590 		Flag_Remove(FlagLocation, set_home);
   3591 
   3592 		/*
   3593 		**	Attach the flag to the cell specified. If it can't be placed, then pick
   3594 		**	a nearby cell where it can be placed.
   3595 		*/
   3596 		CELL newcell = cell;
   3597 		rc = Map[newcell].Flag_Place(Class->House);
   3598 		if (!rc) {
   3599 			newcell = Map.Nearby_Location(cell, SPEED_TRACK, -1, MZONE_NORMAL, true);
   3600 			if (newcell != 0) {
   3601 				rc = Map[newcell].Flag_Place(Class->House);
   3602 			}
   3603 
   3604 #ifdef OBSOLETE
   3605 			/*
   3606 			**	Loop for increasing distance from the desired cell.
   3607 			**	For each distance, randomly pick a starting direction.  Between
   3608 			**	this and the clockwise/counterclockwise random value, the flag
   3609 			**	should appear to be placed fairly randomly.
   3610 			*/
   3611 			for (int dist = 1; dist < 32; dist++) {
   3612 				FacingType fcounter;
   3613 				FacingType rot;
   3614 
   3615 				/*
   3616 				**	Clockwise search.
   3617 				*/
   3618 				if (clockwise) {
   3619 					rot = Random_Pick(FACING_N, FACING_NW);
   3620 					for (fcounter = FACING_N; fcounter <= FACING_NW; fcounter++) {
   3621 						newcell = Coord_Cell(Coord_Move(Cell_Coord(cell), Facing_Dir(rot), dist*256));
   3622 						if (Map.In_Radar(newcell) && Map[newcell].Flag_Place(Class->House)) {
   3623 							dist = 32;
   3624 							rc = true;
   3625 							break;
   3626 						}
   3627 						rot++;
   3628 						if (rot > FACING_NW) rot = FACING_N;
   3629 					}
   3630 				} else {
   3631 
   3632 					/*
   3633 					**	Counter-clockwise search
   3634 					*/
   3635 					rot = Random_Pick(FACING_N, FACING_NW);
   3636 					for (fcounter = FACING_NW; fcounter >= FACING_N; fcounter--) {
   3637 						newcell = Coord_Cell(Coord_Move(Cell_Coord(cell), Facing_Dir(rot), dist*256));
   3638 						if (Map.In_Radar(newcell) && Map[newcell].Flag_Place(Class->House)) {
   3639 							dist = 32;
   3640 							rc = true;
   3641 							break;
   3642 						}
   3643 						rot--;
   3644 						if (rot < FACING_N)
   3645 							rot = FACING_NW;
   3646 					}
   3647 				}
   3648 			}
   3649 #endif
   3650 		}
   3651 
   3652 		/*
   3653 		**	If we've found a spot for the flag, place the flag at the new cell.
   3654 		**	if 'set_home' is set, OR this house has no current flag home cell,
   3655 		**	mark that cell as this house's flag home cell. Otherwise fall back
   3656 		**	on returning the flag to its home.
   3657 		*/
   3658 		if (rc) {
   3659 			FlagLocation = As_Target(newcell);
   3660 
   3661 			if (set_home || FlagHome == 0) {
   3662 				Map[newcell].Overlay = OVERLAY_FLAG_SPOT;
   3663 				Map[newcell].OverlayData = 0;
   3664 				Map[newcell].Recalc_Attributes();
   3665 				FlagHome = newcell;
   3666 			}
   3667 		}
   3668 		else if (FlagHome != 0) {
   3669 			rc = Map[FlagHome].Flag_Place(Class->House);
   3670 		}
   3671 
   3672 		return(rc);
   3673 	}
   3674 	return(false);
   3675 }
   3676 
   3677 
   3678 /***********************************************************************************************
   3679  * HouseClass::Flag_Attach -- Attaches the house flag the specified unit.                      *
   3680  *                                                                                             *
   3681  *    This routine will attach the house flag to the specified unit. This routine is called    *
   3682  *    when a unit drives over a cell containing a flag.                                        *
   3683  *                                                                                             *
   3684  * INPUT:   object   -- Pointer to the object that the house flag is to be attached to.        *
   3685  *                                                                                             *
   3686  *          set_home -- if true, clears the flag's waypoint designation                        *
   3687  *                                                                                             *
   3688  * OUTPUT:  Was the flag attached successfully?                                                *
   3689  *                                                                                             *
   3690  * WARNINGS:   none                                                                            *
   3691  *                                                                                             *
   3692  * HISTORY:                                                                                    *
   3693  *   05/23/1995 JLB : Created.                                                                 *
   3694  *=============================================================================================*/
   3695 bool HouseClass::Flag_Attach(UnitClass * object, bool set_home)
   3696 {
   3697 	assert(Houses.ID(this) == ID);
   3698 
   3699 	if (object && !object->IsInLimbo) {
   3700 		Flag_Remove(FlagLocation, set_home);
   3701 
   3702 		/*
   3703 		**	Attach the flag to the object.
   3704 		*/
   3705 		object->Flag_Attach(Class->House);
   3706 		FlagLocation = object->As_Target();
   3707 		return(true);
   3708 	}
   3709 	return(false);
   3710 }
   3711 
   3712 extern void On_Defeated_Message(const char* message, float timeout_seconds);
   3713 
   3714 /***************************************************************************
   3715  * HouseClass::MPlayer_Defeated -- multiplayer; house is defeated          *
   3716  *                                                                         *
   3717  * INPUT:                                                                  *
   3718  *      none.                                                              *
   3719  *                                                                         *
   3720  * OUTPUT:                                                                 *
   3721  *      none.                                                              *
   3722  *                                                                         *
   3723  * WARNINGS:                                                               *
   3724  *      none.                                                              *
   3725  *                                                                         *
   3726  * HISTORY:                                                                *
   3727  *   05/25/1995 BRR : Created.                                             *
   3728  *=========================================================================*/
   3729 void HouseClass::MPlayer_Defeated(void)
   3730 {
   3731 	assert(Houses.ID(this) == ID);
   3732 
   3733 	char txt[80];
   3734 	int i,j;
   3735 	unsigned char id;
   3736 	HouseClass * hptr;
   3737 	HouseClass * hptr2;
   3738 	int num_alive;
   3739 	int num_humans;
   3740 	int all_allies;
   3741 
   3742 	/*
   3743 	**	Set the defeat flag for this house
   3744 	*/
   3745 	IsDefeated = true;
   3746 
   3747 	/*
   3748 	**	If this is a computer controlled house, then all computer controlled
   3749 	**	houses become paranoid.
   3750 	*/
   3751 	if (IQ == Rule.MaxIQ && !IsHuman && Rule.IsComputerParanoid) {
   3752 		Computer_Paranoid();
   3753 	}
   3754 
   3755 	/*
   3756 	**	Remove this house's flag & flag home cell
   3757 	*/
   3758 	if (Special.IsCaptureTheFlag) {
   3759 		if (FlagLocation) {
   3760 			Flag_Remove(FlagLocation, true);
   3761 		} else {
   3762 			if (FlagHome != 0) {
   3763 				Flag_Remove(FlagHome, true);
   3764 			}
   3765 		}
   3766 	}
   3767 
   3768 	/*
   3769 	**	Remove any one-time superweapons the player might have.
   3770 	*/
   3771 	for (i = SPC_FIRST; i < SPC_COUNT; i++) {
   3772 		SuperWeapon[i].Remove(true);
   3773 	}
   3774 
   3775 	/*
   3776 	**	If this is me:
   3777 	**	- Set MPlayerObiWan, so I can only send messages to all players, and
   3778 	**	  not just one (so I can't be obnoxiously omnipotent)
   3779 	**	- Reveal the map
   3780 	**	- Add my defeat message
   3781 	*/
   3782 	if (PlayerPtr == this) {
   3783 		Session.ObiWan = 1;
   3784 		HidPage.Clear();
   3785 		Map.Flag_To_Redraw(true);
   3786 
   3787 		/*
   3788 		**	Pop up a message showing that I was defeated
   3789 		*/
   3790 		sprintf(txt, Text_String(TXT_PLAYER_DEFEATED), IniName);
   3791 		if (Session.Type == GAME_NORMAL) {
   3792 			Session.Messages.Add_Message(NULL, 0, txt, Session.ColorIdx,
   3793 				TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);
   3794 		}
   3795 		Map.Flag_To_Redraw(false);
   3796 		if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   3797 			int timeout = Rule.MessageDelay * TICKS_PER_MINUTE;
   3798 			On_Defeated_Message(txt, timeout * 60.0f / TICKS_PER_MINUTE);
   3799 			Sound_Effect(VOC_INCOMING_MESSAGE);
   3800 		}
   3801 
   3802 	} else {
   3803 
   3804 		/*
   3805 		**	If it wasn't me, find out who was defeated
   3806 		*/
   3807 		if (IsHuman) {
   3808 			sprintf (txt, Text_String(TXT_PLAYER_DEFEATED), IniName);
   3809 
   3810 			//Session.Messages.Add_Message(NULL, 0, txt, RemapColor,
   3811 			//	TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);
   3812 			Map.Flag_To_Redraw(false);
   3813 			RedrawOptionsMenu = true;
   3814 
   3815 			int timeout = Rule.MessageDelay * TICKS_PER_MINUTE;
   3816 			On_Defeated_Message(txt, timeout * 60.0f / TICKS_PER_MINUTE);
   3817 			Sound_Effect(VOC_INCOMING_MESSAGE);
   3818 		}
   3819 	}
   3820 
   3821 	/*
   3822 	**	Find out how many players are left alive.
   3823 	*/
   3824 	num_alive = 0;
   3825 	num_humans = 0;
   3826 	for (i = 0; i < Session.MaxPlayers; i++) {
   3827 		hptr = HouseClass::As_Pointer((HousesType)(HOUSE_MULTI1 + i));
   3828 		if (hptr && !hptr->IsDefeated) {
   3829 			if (hptr->IsHuman) {
   3830 				num_humans++;
   3831 			}
   3832 			num_alive++;
   3833 		}
   3834 	}
   3835 
   3836 	/*
   3837 	**	If all the houses left alive are allied with each other, then in reality
   3838 	**	there's only one player left:
   3839 	*/
   3840 	all_allies = 1;
   3841 	for (i = 0; i < Session.MaxPlayers; i++) {
   3842 
   3843 		/*
   3844 		**	Get a pointer to this house
   3845 		*/
   3846 		hptr = HouseClass::As_Pointer((HousesType)(HOUSE_MULTI1 + i));
   3847 		if (!hptr || hptr->IsDefeated)
   3848 			continue;
   3849 
   3850 		/*
   3851 		**	Loop through all houses; if there's one left alive that this house
   3852 		**	isn't allied with, then all_allies will be false
   3853 		*/
   3854 		for (j = 0; j < Session.MaxPlayers; j++) {
   3855 			hptr2 = HouseClass::As_Pointer((HousesType)(HOUSE_MULTI1 + j));
   3856 			if (!hptr2) {
   3857 				continue;
   3858 			}
   3859 
   3860 			if (!hptr2->IsDefeated && !hptr->Is_Ally(hptr2)) {
   3861 				all_allies = 0;
   3862 				break;
   3863 			}
   3864 		}
   3865 		if (!all_allies) {
   3866 			break;
   3867 		}
   3868 	}
   3869 
   3870 	/*
   3871 	**	If all houses left are allies, set 'num_alive' to 1; game over.
   3872 	*/
   3873 	if (all_allies) {
   3874 		num_alive = 1;
   3875 	}
   3876 
   3877 	/*
   3878 	**	If there's only one human player left or no humans left, the game is over:
   3879 	**	- Determine whether this player wins or loses, based on the state of the
   3880 	**	  player's IsDefeated flag
   3881 	**	- Find all players' indices in the Session.Score array
   3882 	**	- Tally up scores for this game
   3883 	*/
   3884 	if (num_alive == 1 || num_humans == 0) {
   3885 		if (PlayerPtr->IsDefeated) {
   3886 			PlayerLoses = true;
   3887 		} else {
   3888 			PlayerWins = true;
   3889 		}
   3890 
   3891 		/*
   3892 		** Add up the scores
   3893 		*/
   3894 		Tally_Score();
   3895 
   3896 		/*
   3897 		**	Destroy all the IPX connections, since we have to go through the rest
   3898 		**	of the Main_Loop() before we detect that the game is over, and we'll
   3899 		**	end up waiting for frame sync packets from the other machines.
   3900 		*/
   3901 		if (Session.Type==GAME_IPX || Session.Type == GAME_INTERNET) {
   3902 			i = 0;
   3903 			while (Ipx.Num_Connections() && (i++ < 1000) ) {
   3904 				id = Ipx.Connection_ID(0);
   3905 				Ipx.Delete_Connection(id);
   3906 			}
   3907 			Session.NumPlayers = 0;
   3908 		}
   3909 
   3910 #if(TEN)
   3911 		//
   3912 		// Tell the TEN server who won
   3913 		//
   3914 		if (Session.Type == GAME_TEN) {
   3915 			Send_TEN_Win_Packet();
   3916 		}
   3917 #endif	// TEN
   3918 
   3919 #if(MPATH)
   3920 		//
   3921 		// Tell the MPATH server who won
   3922 		//
   3923 		if (Session.Type == GAME_MPATH) {
   3924 			FILE *fp;
   3925 
   3926 			fp = fopen("winner.txt","wt");
   3927 			if (fp) {
   3928 				for (i = 0; i < Session.Players.Count(); i++) {
   3929 					hptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);
   3930 					if (!hptr->IsDefeated) {
   3931 						fprintf(fp,"%s\n",hptr->IniName);
   3932 					}
   3933 				}
   3934 				fclose(fp);
   3935 			}
   3936 		}
   3937 #endif	// MPATH
   3938 
   3939 	}
   3940 }
   3941 
   3942 
   3943 /***************************************************************************
   3944  * HouseClass::Tally_Score -- Fills in the score system for this round     *
   3945  *                                                                         *
   3946  * INPUT:                                                                  *
   3947  *		none.																						*
   3948  *                                                                         *
   3949  * OUTPUT:                                                                 *
   3950  *		none.																						*
   3951  *                                                                         *
   3952  * WARNINGS:                                                               *
   3953  *		none.																						*
   3954  *                                                                         *
   3955  * HISTORY:                                                                *
   3956  *   11/29/1995 BRR : Created.                                             *
   3957  *=========================================================================*/
   3958 void HouseClass::Tally_Score(void)
   3959 {
   3960 	HousesType house;
   3961 	HousesType house2;
   3962 	HouseClass * hptr;
   3963 	int score_index;
   3964 	int i,j,k;
   3965 	int max_index;
   3966 	int max_count;
   3967 	int count;
   3968 
   3969 	/*
   3970 	** Loop through all houses, tallying up each player's score
   3971 	*/
   3972 	for (house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
   3973 		hptr = HouseClass::As_Pointer(house);
   3974 		/*
   3975 		** Skip this house if it's not human.
   3976 		*/
   3977 		if (!hptr || !hptr->IsHuman) {
   3978 			continue;
   3979 		}
   3980 		/*
   3981 		** Now find out where this player is in the score array
   3982 		*/
   3983 		score_index = -1;
   3984 		for (i = 0; i < Session.NumScores; i++) {
   3985 			if (!stricmp(hptr->IniName, Session.Score[i].Name)) {
   3986 				score_index = i;
   3987 				break;
   3988 			}
   3989 		}
   3990 
   3991 		/*
   3992 		**	If the index is still -1, the name wasn't found; add a new entry.
   3993 		*/
   3994 		if (score_index == -1) {
   3995 			/*
   3996 			** Just add this player to the end of the array, if there's room
   3997 			*/
   3998 			if (Session.NumScores < MAX_MULTI_NAMES) {
   3999 				score_index = Session.NumScores;
   4000 				Session.NumScores++;
   4001 			}
   4002 			/*
   4003 			** If there's not room, we have to remove somebody.
   4004 			**	For each player in the scores array, count the # of '-1' entries
   4005 			**	from this game backwards; the one with the most is the one that
   4006 			**	hasn't played the longest; replace him with this new guy.
   4007 			*/
   4008 			else {
   4009 				max_index = 0;
   4010 				max_count = 0;
   4011 				for (j = 0; j < Session.NumScores; j++) {
   4012 					count = 0;
   4013 					for (k = Session.NumScores - 1; k >= 0; k--) {
   4014 						if (Session.Score[j].Kills[k]==-1) {
   4015 							count++;
   4016 						}
   4017 						else {
   4018 							break;
   4019 						}
   4020 					}
   4021 					if (count > max_count) {
   4022 						max_count = count;
   4023 						max_index = j;
   4024 					}
   4025 				}
   4026 				score_index = max_index;
   4027 			}
   4028 
   4029 			/*
   4030 			**	Initialize this new score entry
   4031 			*/
   4032 			Session.Score[score_index].Wins = 0;
   4033 			strcpy (Session.Score[score_index].Name, hptr->IniName);
   4034 			for (j = 0; j < MAX_MULTI_GAMES; j++)
   4035 				Session.Score[score_index].Kills[j] = -1;
   4036 		}
   4037 
   4038 		/*
   4039 		**	Init this player's Kills to 0 (-1 means he didn't play this round;
   4040 		**	0 means he played but got no kills).
   4041 		*/
   4042 		Session.Score[score_index].Kills[Session.CurGame] = 0;
   4043 
   4044 		/*
   4045 		**	Init this player's color to his last-used color index
   4046 		*/
   4047 		Session.Score[score_index].Color = hptr->RemapColor;
   4048 
   4049 		/*
   4050 		**	If this house was undefeated, it must have been the winner.
   4051 		** (If no human houses are undefeated, the computer won.)
   4052 		*/
   4053 		if (!hptr->IsDefeated) {
   4054 			Session.Score[score_index].Wins++;
   4055 			Session.Winner = score_index;
   4056 		}
   4057 
   4058 		/*
   4059 		**	Tally up all kills for this player
   4060 		*/
   4061 		for (house2 = HOUSE_FIRST; house2 < HOUSE_COUNT; house2++) {
   4062 			Session.Score[score_index].Kills[Session.CurGame] += hptr->UnitsKilled[house2];
   4063 			Session.Score[score_index].Kills[Session.CurGame] += hptr->BuildingsKilled[house2];
   4064 		}
   4065 	}
   4066 }
   4067 
   4068 
   4069 /***************************************************************************
   4070  * HouseClass::Blowup_All -- blows up everything                           *
   4071  *                                                                         *
   4072  * INPUT:                                                                  *
   4073  *      none.                                                              *
   4074  *                                                                         *
   4075  * OUTPUT:                                                                 *
   4076  *      none.                                                              *
   4077  *                                                                         *
   4078  * WARNINGS:                                                               *
   4079  *      none.                                                              *
   4080  *                                                                         *
   4081  * HISTORY:                                                                *
   4082  *   05/16/1995 BRR : Created.                                             *
   4083  *   06/09/1995 JLB : Handles aircraft.                                    *
   4084  *   05/07/1996 JLB : Handles ships.                                       *
   4085  *=========================================================================*/
   4086 void HouseClass::Blowup_All(void)
   4087 {
   4088 	assert(Houses.ID(this) == ID);
   4089 
   4090 	int i;
   4091 	int damage;
   4092 	UnitClass * uptr;
   4093 	InfantryClass * iptr;
   4094 	BuildingClass * bptr;
   4095 	int count;
   4096 	WarheadType warhead;
   4097 
   4098 	/*
   4099 	**	Find everything owned by this house & blast it with a huge amount of damage
   4100 	**	at zero range.  Do units before infantry, so the units' drivers are killed
   4101 	**	too.  Using Explosion_Damage is like dropping a big bomb right on the
   4102 	**	object; it will also damage anything around it.
   4103 	*/
   4104 	for (i = 0; i < ::Units.Count(); i++) {
   4105 		if (::Units.Ptr(i)->House == this && !::Units.Ptr(i)->IsInLimbo) {
   4106 			uptr = ::Units.Ptr(i);
   4107 
   4108 			/*
   4109 			**	Some units can't be killed with one shot, so keep damaging them until
   4110 			**	they're gone.  The unit will destroy itself, and put an infantry in
   4111 			**	its place.  When the unit destroys itself, decrement 'i' since
   4112 			**	its pointer will be removed from the active pointer list.
   4113 			*/
   4114 			count = 0;
   4115 			while (::Units.Ptr(i)==uptr && uptr->Strength) {
   4116 
   4117 				// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
   4118 				// Likely due to damage biasing based on RA factions and/or difficulty settings
   4119 				// Applying this to units (vehicles), ships, buildings, and infantry, too
   4120 				//
   4121 				// damage = uptr->Strength; // Original
   4122 				damage = 0x7fff; // Copied from TD
   4123 
   4124 				uptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
   4125 				count++;
   4126 				if (count > 5 && uptr->IsActive) {
   4127 					delete uptr;
   4128 					break;
   4129 				}
   4130 			}
   4131 			i--;
   4132 		}
   4133 	}
   4134 
   4135 	/*
   4136 	**	Destroy all aircraft owned by this house.
   4137 	*/
   4138 	for (i = 0; i < ::Aircraft.Count(); i++) {
   4139 		if (::Aircraft.Ptr(i)->House == this && !::Aircraft.Ptr(i)->IsInLimbo) {
   4140 			AircraftClass * aptr = ::Aircraft.Ptr(i);
   4141 
   4142 			// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
   4143 			// Likely due to damage biasing based on RA factions and/or difficulty settings
   4144 			// Applying this to units (vehicles), ships, buildings, and infantry, too
   4145 			//
   4146 			// damage = aptr->Strength; // Original
   4147 			damage = 0x7fff; // Copied from TD
   4148 
   4149 			aptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
   4150 			if (!aptr->IsActive) {
   4151 				i--;
   4152 			}
   4153 		}
   4154 	}
   4155 
   4156 	/*
   4157 	**	Destroy all vessels owned by this house.
   4158 	*/
   4159 	for (i = 0; i < ::Vessels.Count(); i++) {
   4160 		if (::Vessels.Ptr(i)->House == this && !::Vessels.Ptr(i)->IsInLimbo) {
   4161 			VesselClass * vptr = ::Vessels.Ptr(i);
   4162 
   4163 			// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
   4164 			// Likely due to damage biasing based on RA factions and/or difficulty settings
   4165 			// Applying this to units (vehicles), ships, buildings, and infantry, too
   4166 			//
   4167 			// damage = vptr->Strength; // Original
   4168 			damage = 0x7fff; // Copied from TD 
   4169 
   4170 			vptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
   4171 			if (!vptr->IsActive) {
   4172 				i--;
   4173 			}
   4174 		}
   4175 	}
   4176 
   4177 	/*
   4178 	**	Buildings don't delete themselves when they die; they shake the screen
   4179 	**	and begin a countdown, so don't decrement 'i' when it's destroyed.
   4180 	*/
   4181 	for (i = 0; i < Buildings.Count(); i++) {
   4182 		if (Buildings.Ptr(i)->House == this && !Buildings.Ptr(i)->IsInLimbo) {
   4183 			bptr = Buildings.Ptr(i);
   4184 
   4185 			count = 0;
   4186 			while (Buildings.Ptr(i)==bptr && bptr->Strength) {
   4187 
   4188 				// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
   4189 				// Likely due to damage biasing based on RA factions and/or difficulty settings
   4190 				// Applying this to units (vehicles), ships, buildings, and infantry, too
   4191 				//
   4192 				// damage = bptr->Strength; // Original
   4193 				damage = 0x7fff; // Copied from TD 
   4194 
   4195 				bptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
   4196 				count++;
   4197 				if (count > 5) {
   4198 					delete bptr;
   4199 					break;
   4200 				}
   4201 			}
   4202 		}
   4203 	}
   4204 
   4205 	/*
   4206 	**	Infantry don't delete themselves when they die; they go into a death-
   4207 	**	animation sequence, so there's no need to decrement 'i' when they die.
   4208 	**	Infantry should die by different types of warheads, so their death
   4209 	**	anims aren't all synchronized.
   4210 	*/
   4211 	for (i = 0; i < Infantry.Count(); i++) {
   4212 		if (Infantry.Ptr(i)->House == this && !Infantry.Ptr(i)->IsInLimbo) {
   4213 			iptr = Infantry.Ptr(i);
   4214 
   4215 			count = 0;
   4216 			while (Infantry.Ptr(i)==iptr && iptr->Strength) {
   4217 
   4218 				// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
   4219 				// Likely due to damage biasing based on RA factions and/or difficulty settings
   4220 				// Applying this to units (vehicles), ships, buildings, and infantry, too
   4221 				//
   4222 				// damage = iptr->Strength; // Original
   4223 				damage = 0x7fff; // Copied from TD 
   4224 
   4225 				warhead = Random_Pick(WARHEAD_SA, WARHEAD_FIRE);
   4226 				iptr->Take_Damage(damage, 0, warhead, NULL, true);
   4227 
   4228 				count++;
   4229 				if (count > 5) {
   4230 					delete iptr;
   4231 					break;
   4232 				}
   4233 			}
   4234 		}
   4235 	}
   4236 }
   4237 
   4238 
   4239 /***********************************************************************************************
   4240  * HouseClass::Flag_To_Die -- Flags the house to blow up soon.                                 *
   4241  *                                                                                             *
   4242  *    When this routine is called, the house will blow up after a period of time. Typically    *
   4243  *    this is called when the flag is captured or the HQ destroyed.                            *
   4244  *                                                                                             *
   4245  * INPUT:   none                                                                               *
   4246  *                                                                                             *
   4247  * OUTPUT:  Was the house flagged to blow up?                                                  *
   4248  *                                                                                             *
   4249  * WARNINGS:   none                                                                            *
   4250  *                                                                                             *
   4251  * HISTORY:                                                                                    *
   4252  *   06/20/1995 JLB : Created.                                                                 *
   4253  *=============================================================================================*/
   4254 bool HouseClass::Flag_To_Die(void)
   4255 {
   4256 	assert(Houses.ID(this) == ID);
   4257 
   4258 	if (!IsToWin && !IsToDie && !IsToLose) {
   4259 		IsToDie = true;
   4260 		BorrowedTime = TICKS_PER_MINUTE * Rule.SavourDelay;
   4261 	}
   4262 	return(IsToDie);
   4263 }
   4264 
   4265 
   4266 /***********************************************************************************************
   4267  * HouseClass::Flag_To_Win -- Flags the house to win soon.                                     *
   4268  *                                                                                             *
   4269  *    When this routine is called, the house will be declared the winner after a period of     *
   4270  *    time.                                                                                    *
   4271  *                                                                                             *
   4272  * INPUT:   none                                                                               *
   4273  *                                                                                             *
   4274  * OUTPUT:  Was the house flagged to win?                                                      *
   4275  *                                                                                             *
   4276  * WARNINGS:   none                                                                            *
   4277  *                                                                                             *
   4278  * HISTORY:                                                                                    *
   4279  *   06/20/1995 JLB : Created.                                                                 *
   4280  *=============================================================================================*/
   4281 bool HouseClass::Flag_To_Win(void)
   4282 {
   4283 	assert(Houses.ID(this) == ID);
   4284 
   4285 	if (!IsToWin && !IsToDie && !IsToLose) {
   4286 		IsToWin = true;
   4287 		BorrowedTime = TICKS_PER_MINUTE * Rule.SavourDelay;
   4288 	}
   4289 	return(IsToWin);
   4290 }
   4291 
   4292 
   4293 /***********************************************************************************************
   4294  * HouseClass::Flag_To_Lose -- Flags the house to die soon.                                    *
   4295  *                                                                                             *
   4296  *    When this routine is called, it will spell the doom of this house. In a short while      *
   4297  *    all of the object owned by this house will explode. Typical use of this routine is when  *
   4298  *    the flag has been captured or the command vehicle has been destroyed.                    *
   4299  *                                                                                             *
   4300  * INPUT:   none                                                                               *
   4301  *                                                                                             *
   4302  * OUTPUT:  Has the doom been initiated?                                                       *
   4303  *                                                                                             *
   4304  * WARNINGS:   none                                                                            *
   4305  *                                                                                             *
   4306  * HISTORY:                                                                                    *
   4307  *   06/12/1995 JLB : Created.                                                                 *
   4308  *=============================================================================================*/
   4309 bool HouseClass::Flag_To_Lose(void)
   4310 {
   4311 	assert(Houses.ID(this) == ID);
   4312 
   4313 	IsToWin = false;
   4314 	if (!IsToDie && !IsToLose) {
   4315 		IsToLose = true;
   4316 		BorrowedTime = TICKS_PER_MINUTE * Rule.SavourDelay;
   4317 	}
   4318 	return(IsToLose);
   4319 }
   4320 
   4321 
   4322 /***********************************************************************************************
   4323  * HouseClass::Init_Data -- Initializes the multiplayer color data.                            *
   4324  *                                                                                             *
   4325  *    This routine is called when initializing the color and remap data for this house. The    *
   4326  *    primary user of this routine is the multiplayer version of the game, especially for		  *
   4327  *    saving & loading multiplayer games.																		  *
   4328  *                                                                                             *
   4329  * INPUT:   color    -- The color of this house.                                               *
   4330  *                                                                                             *
   4331  *          house    -- The house that this should act like.                                   *
   4332  *                                                                                             *
   4333  *          credits  -- The initial credits to assign to this house.                           *
   4334  *                                                                                             *
   4335  * OUTPUT:  none                                                                               *
   4336  *                                                                                             *
   4337  * WARNINGS:   none                                                                            *
   4338  *                                                                                             *
   4339  * HISTORY:                                                                                    *
   4340  *   07/29/1995 JLB : Created.                                                                 *
   4341  *=============================================================================================*/
   4342 extern bool NowSavingGame; // TEMP MBL: Need to discuss better solution with Steve
   4343 void HouseClass::Init_Data(PlayerColorType color, HousesType house, int credits)
   4344 {
   4345 	assert(Houses.ID(this) == ID);
   4346 
   4347 	Credits = Control.InitialCredits = credits;
   4348 	VisibleCredits.Current = Credits;
   4349 	RemapColor = color;
   4350 	ActLike = house;
   4351 
   4352 	// MBL 03.20.2020 
   4353 	// Attempt to fix Red Alert credit tick-up bug after saving a game that has had harvesting underway
   4354 	// Note that this code gets called with both game loads and saves
   4355 	// When this function is called, sometimes credits value has Tiberium (or HarvestedCredits?) variables applied, and sometimes now
   4356 	//
   4357 	if (NowSavingGame == true) 
   4358 	{
   4359 		// At this point VisibleCredits.Current (set above) does not have harvested ore/tiberium applied, but VisibleCredits.Credits does
   4360 		VisibleCredits.Current = VisibleCredits.Credits;
   4361 	}
   4362 }
   4363 
   4364 
   4365 /***********************************************************************************************
   4366  * HouseClass::Power_Fraction -- Fetches the current power output rating.                      *
   4367  *                                                                                             *
   4368  *    Use this routine to fetch the current power output as a fixed point fraction. The        *
   4369  *    value 0x0100 is 100% power.                                                              *
   4370  *                                                                                             *
   4371  * INPUT:   none                                                                               *
   4372  *                                                                                             *
   4373  * OUTPUT:  Returns with power rating as a fixed pointer number.                               *
   4374  *                                                                                             *
   4375  * WARNINGS:   none                                                                            *
   4376  *                                                                                             *
   4377  * HISTORY:                                                                                    *
   4378  *   07/22/1995 JLB : Created.                                                                 *
   4379  *=============================================================================================*/
   4380 fixed HouseClass::Power_Fraction(void) const
   4381 {
   4382 	assert(Houses.ID(this) == ID);
   4383 
   4384 	if (Power >= Drain || Drain == 0) return(1);
   4385 
   4386 	if (Power) {
   4387 		return(fixed(Power, Drain));
   4388 	}
   4389 	return(0);
   4390 }
   4391 
   4392 
   4393 /***********************************************************************************************
   4394  * HouseClass::Sell_Wall -- Tries to sell the wall at the specified location.                  *
   4395  *                                                                                             *
   4396  *    This routine will try to sell the wall at the specified location. If there is a wall     *
   4397  *    present and it is owned by this house, then it can be sold.                              *
   4398  *                                                                                             *
   4399  * INPUT:   cell  -- The cell that wall selling is desired.                                    *
   4400  *                                                                                             *
   4401  * OUTPUT:  none                                                                               *
   4402  *                                                                                             *
   4403  * WARNINGS:   none                                                                            *
   4404  *                                                                                             *
   4405  * HISTORY:                                                                                    *
   4406  *   08/05/1995 JLB : Created.                                                                 *
   4407  *   11/02/1996 JLB : Checks unsellable bit for wall type.                                     *
   4408  *=============================================================================================*/
   4409 void HouseClass::Sell_Wall(CELL cell)
   4410 {
   4411 	assert(Houses.ID(this) == ID);
   4412 
   4413 	if ((unsigned)cell > 0) {
   4414 		OverlayType overlay = Map[cell].Overlay;
   4415 
   4416 		if (overlay != OVERLAY_NONE && Map[cell].Owner == Class->House) {
   4417 			OverlayTypeClass const & optr = OverlayTypeClass::As_Reference(overlay);
   4418 
   4419 			if (optr.IsWall) {
   4420 				BuildingTypeClass const * btype = NULL;
   4421 				switch (overlay) {
   4422 					case OVERLAY_SANDBAG_WALL:
   4423 						btype = &BuildingTypeClass::As_Reference(STRUCT_SANDBAG_WALL);
   4424 						break;
   4425 
   4426 					case OVERLAY_CYCLONE_WALL:
   4427 						btype = &BuildingTypeClass::As_Reference(STRUCT_CYCLONE_WALL);
   4428 						break;
   4429 
   4430 					case OVERLAY_BRICK_WALL:
   4431 						btype = &BuildingTypeClass::As_Reference(STRUCT_BRICK_WALL);
   4432 						break;
   4433 
   4434 					case OVERLAY_BARBWIRE_WALL:
   4435 						btype = &BuildingTypeClass::As_Reference(STRUCT_BARBWIRE_WALL);
   4436 						break;
   4437 
   4438 					case OVERLAY_WOOD_WALL:
   4439 						btype = &BuildingTypeClass::As_Reference(STRUCT_WOOD_WALL);
   4440 						break;
   4441 
   4442 					case OVERLAY_FENCE:
   4443 						btype = &BuildingTypeClass::As_Reference(STRUCT_FENCE);
   4444 						break;
   4445 
   4446 					default:
   4447 						break;
   4448 				}
   4449 				if (btype != NULL && !btype->IsUnsellable) {
   4450 
   4451 					if (PlayerPtr == this) {
   4452 						Sound_Effect(VOC_CASHTURN);
   4453 					}
   4454 
   4455 					Refund_Money(btype->Raw_Cost() * Rule.RefundPercent);
   4456 					Map[cell].Overlay = OVERLAY_NONE;
   4457 					Map[cell].OverlayData = 0;
   4458 					Map[cell].Owner = HOUSE_NONE;
   4459 					Map[cell].Wall_Update();
   4460 					CellClass * ncell = Map[cell].Adjacent_Cell(FACING_N);
   4461 					if (ncell) ncell->Wall_Update();
   4462 					CellClass * wcell = Map[cell].Adjacent_Cell(FACING_W);
   4463 					if (wcell) wcell->Wall_Update();
   4464 					CellClass * scell = Map[cell].Adjacent_Cell(FACING_S);
   4465 					if (scell) scell->Wall_Update();
   4466 					CellClass * ecell = Map[cell].Adjacent_Cell(FACING_E);
   4467 					if (ecell) ecell->Wall_Update();
   4468 					Map[cell].Recalc_Attributes();
   4469 					Map[cell].Redraw_Objects();
   4470 					Map.Radar_Pixel(cell);
   4471 					Detach_This_From_All(::As_Target(cell), true);
   4472 
   4473 					if (optr.IsCrushable) {
   4474 						Map.Zone_Reset(MZONEF_NORMAL);
   4475 					} else {
   4476 						Map.Zone_Reset(MZONEF_CRUSHER|MZONEF_NORMAL);
   4477 					}
   4478 				}
   4479 			}
   4480 		}
   4481 	}
   4482 }
   4483 
   4484 
   4485 /***********************************************************************************************
   4486  * HouseClass::Suggest_New_Building -- Examines the situation and suggests a building.         *
   4487  *                                                                                             *
   4488  *    This routine is called when a construction yard needs to know what to build next. It     *
   4489  *    will either examine the prebuilt base list or try to figure out what to build next       *
   4490  *    based on the current game situation.                                                     *
   4491  *                                                                                             *
   4492  * INPUT:   none                                                                               *
   4493  *                                                                                             *
   4494  * OUTPUT:  Returns with a pointer to the building type class to build.                        *
   4495  *                                                                                             *
   4496  * WARNINGS:   none                                                                            *
   4497  *                                                                                             *
   4498  * HISTORY:                                                                                    *
   4499  *   09/27/1995 JLB : Created.                                                                 *
   4500  *=============================================================================================*/
   4501 BuildingTypeClass const * HouseClass::Suggest_New_Building(void) const
   4502 {
   4503 	assert(Houses.ID(this) == ID);
   4504 
   4505 	if (BuildStructure != STRUCT_NONE) {
   4506 		return(&BuildingTypeClass::As_Reference(BuildStructure));
   4507 	}
   4508 	return(NULL);
   4509 }
   4510 
   4511 
   4512 /***********************************************************************************************
   4513  * HouseClass::Find_Building -- Finds a building of specified type.                            *
   4514  *                                                                                             *
   4515  *    This routine is used to find a building of the specified type. This is particularly      *
   4516  *    useful for when some event requires a specific building instance. The nuclear missile    *
   4517  *    launch is a good example.                                                                *
   4518  *                                                                                             *
   4519  * INPUT:   type  -- The building type to scan for.                                            *
   4520  *                                                                                             *
   4521  *          zone  -- The zone that the building must be located in. If no zone specific search *
   4522  *                   is desired, then pass ZONE_NONE.                                          *
   4523  *                                                                                             *
   4524  * OUTPUT:  Returns with a pointer to the building type requested. If there is no building     *
   4525  *          of the type requested, then NULL is returned.                                      *
   4526  *                                                                                             *
   4527  * WARNINGS:   none                                                                            *
   4528  *                                                                                             *
   4529  * HISTORY:                                                                                    *
   4530  *   09/27/1995 JLB : Created.                                                                 *
   4531  *   10/02/1995 JLB : Allows for zone specifics.                                               *
   4532  *=============================================================================================*/
   4533 BuildingClass * HouseClass::Find_Building(StructType type, ZoneType zone) const
   4534 {
   4535 	assert(Houses.ID(this) == ID);
   4536 
   4537 	/*
   4538 	**	Only scan if we KNOW there is at least one building of the type
   4539 	**	requested.
   4540 	*/
   4541 	if (BQuantity[type] > 0) {
   4542 
   4543 		/*
   4544 		**	Search for a suitable launch site for this missile.
   4545 		*/
   4546 		for (int index = 0; index < Buildings.Count(); index++) {
   4547 			BuildingClass * b = Buildings.Ptr(index);
   4548 			if (b && !b->IsInLimbo && b->House == this && *b == type) {
   4549 				if (zone == ZONE_NONE || Which_Zone(b) == zone) {
   4550 					return(b);
   4551 				}
   4552 			}
   4553 		}
   4554 	}
   4555 	return(NULL);
   4556 }
   4557 
   4558 
   4559 /***********************************************************************************************
   4560  * HouseClass::Find_Build_Location -- Finds a suitable building location.                      *
   4561  *                                                                                             *
   4562  *    This routine is used to find a suitable building location for the building specified.    *
   4563  *    The auto base building logic uses this when building the base for the computer.          *
   4564  *                                                                                             *
   4565  * INPUT:   building -- Pointer to the building that needs to be placed down.                  *
   4566  *                                                                                             *
   4567  * OUTPUT:  Returns with the coordinate to place the building at. If there are no suitable     *
   4568  *          locations, then NULL is returned.                                                  *
   4569  *                                                                                             *
   4570  * WARNINGS:   none                                                                            *
   4571  *                                                                                             *
   4572  * HISTORY:                                                                                    *
   4573  *   09/27/1995 JLB : Created.                                                                 *
   4574  *=============================================================================================*/
   4575 COORDINATE HouseClass::Find_Build_Location(BuildingClass * building) const
   4576 {
   4577 	assert(Houses.ID(this) == ID);
   4578 
   4579 	int zonerating[ZONE_COUNT];
   4580 	struct {
   4581 		int AntiAir;			// Average air defense for the base.
   4582 		int AntiArmor;			// Average armor defense for the base.
   4583 		int AntiInfantry;		// Average infantry defense for the base.
   4584 	} zoneinfo = {0,0,0};
   4585 	int antiair = building->Anti_Air();
   4586 	int antiarmor = building->Anti_Armor();
   4587 	int antiinfantry = building->Anti_Infantry();
   4588 	bool adj = true;
   4589 
   4590 	/*
   4591 	**	Never place combat buildings adjacent to each other. This is partly
   4592 	**	because combat buildings don't have a bib and jamming will occur as well
   4593 	**	as because spacing defensive buildings out will yield a better
   4594 	**	defense.
   4595 	*/
   4596 	if (antiair || antiarmor || antiinfantry) {
   4597 		adj = false;
   4598 	}
   4599 
   4600 	/*
   4601 	**	Determine the average zone strengths for the base. This value is
   4602 	**	used to determine what zones are considered under or over strength.
   4603 	*/
   4604 	ZoneType z;
   4605 	for (z = ZONE_NORTH; z < ZONE_COUNT; z++) {
   4606 		zoneinfo.AntiAir += ZoneInfo[z].AirDefense;
   4607 		zoneinfo.AntiArmor += ZoneInfo[z].ArmorDefense;
   4608 		zoneinfo.AntiInfantry += ZoneInfo[z].InfantryDefense;
   4609 	}
   4610 	zoneinfo.AntiAir /= ZONE_COUNT-ZONE_NORTH;
   4611 	zoneinfo.AntiArmor /= ZONE_COUNT-ZONE_NORTH;
   4612 	zoneinfo.AntiInfantry /= ZONE_COUNT-ZONE_NORTH;
   4613 
   4614 	/*
   4615 	**	Give each zone a rating for value. The higher the value the more desirable
   4616 	**	to place the specified building in that zone. Factor the average value of
   4617 	**	zone defense such that more weight is given to zones that are very under
   4618 	**	defended.
   4619 	*/
   4620 	memset(&zonerating[0], '\0', sizeof(zonerating));
   4621 	for (z = ZONE_FIRST; z < ZONE_COUNT; z++) {
   4622 		int diff;
   4623 
   4624 		diff = zoneinfo.AntiAir-ZoneInfo[z].AirDefense;
   4625 		if (z == ZONE_CORE) diff /= 2;
   4626 		if (diff > 0) {
   4627 			zonerating[z] += min(antiair, diff);
   4628 		}
   4629 
   4630 		diff = zoneinfo.AntiArmor-ZoneInfo[z].ArmorDefense;
   4631 		if (z == ZONE_CORE) diff /= 2;
   4632 		if (diff > 0) {
   4633 			zonerating[z] += min(antiarmor, diff);
   4634 		}
   4635 
   4636 		diff = zoneinfo.AntiInfantry-ZoneInfo[z].InfantryDefense;
   4637 		if (z == ZONE_CORE) diff /= 2;
   4638 		if (diff > 0) {
   4639 			zonerating[z] += min(antiinfantry, diff);
   4640 		}
   4641 	}
   4642 
   4643 	/*
   4644 	**	Now that each zone has been given a desirability rating, find the zone
   4645 	**	with the greatest value and try to place the building in that zone.
   4646 	*/
   4647 	ZoneType zone = Random_Pick(ZONE_FIRST, ZONE_WEST);
   4648 	int largest = 0;
   4649 	for (z = ZONE_FIRST; z < ZONE_COUNT; z++) {
   4650 		if (zonerating[z] > largest) {
   4651 			zone = z;
   4652 			largest = zonerating[z];
   4653 		}
   4654 	}
   4655 
   4656 	CELL zcell = Find_Cell_In_Zone(building, zone);
   4657 	if (zcell) {
   4658 		return(Cell_Coord(zcell));
   4659 	}
   4660 
   4661 	/*
   4662 	**	Could not build in preferred zone, so try building in any zone.
   4663 	*/
   4664 	static ZoneType _zones[] = {ZONE_CORE, ZONE_NORTH, ZONE_SOUTH, ZONE_EAST, ZONE_WEST};
   4665 	int start = Random_Pick(0, ARRAY_SIZE(_zones)-1);
   4666 	for (int zz = 0; zz < ARRAY_SIZE(_zones); zz++) {
   4667 		ZoneType tryzone = _zones[(zz + start) % ARRAY_SIZE(_zones)];
   4668 		zcell = Find_Cell_In_Zone(building, tryzone);
   4669 		if (zcell) return(zcell);
   4670 	}
   4671 
   4672 	return(NULL);
   4673 }
   4674 
   4675 
   4676 /***********************************************************************************************
   4677  * HouseClass::Recalc_Center -- Recalculates the center point of the base.                     *
   4678  *                                                                                             *
   4679  *    This routine will average the location of the base and record the center point. The      *
   4680  *    recorded center point is used to determine such things as how far the base is spread     *
   4681  *    out and where to protect the most. This routine should be called whenever a building     *
   4682  *    is created or destroyed.                                                                 *
   4683  *                                                                                             *
   4684  * INPUT:   none                                                                               *
   4685  *                                                                                             *
   4686  * OUTPUT:  none                                                                               *
   4687  *                                                                                             *
   4688  * WARNINGS:   none                                                                            *
   4689  *                                                                                             *
   4690  * HISTORY:                                                                                    *
   4691  *   09/28/1995 JLB : Created.                                                                 *
   4692  *=============================================================================================*/
   4693 void HouseClass::Recalc_Center(void)
   4694 {
   4695 	assert(Houses.ID(this) == ID);
   4696 
   4697 	/*
   4698 	**	First presume that there is no base. If there is a base, then these values will be
   4699 	**	properly filled in below.
   4700 	*/
   4701 	Center = 0;
   4702 	Radius = 0;
   4703 	for (ZoneType zone = ZONE_FIRST; zone < ZONE_COUNT; zone++) {
   4704 		ZoneInfo[zone].AirDefense = 0;
   4705 		ZoneInfo[zone].ArmorDefense = 0;
   4706 		ZoneInfo[zone].InfantryDefense = 0;
   4707 	}
   4708 
   4709 	/*
   4710 	**	Only process the center base size/position calculation if there are buildings to
   4711 	**	consider. When no buildings for this house are present, then no processing need
   4712 	**	occur.
   4713 	*/
   4714 	if (CurBuildings > 0) {
   4715 		int x = 0;
   4716 		int y = 0;
   4717 		int count = 0;
   4718 		int index;
   4719 
   4720 		for (index = 0; index < Buildings.Count(); index++) {
   4721 			BuildingClass const * b = Buildings.Ptr(index);
   4722 
   4723 			if (b != NULL && !b->IsInLimbo && (HouseClass *)b->House == this && b->Strength > 0) {
   4724 
   4725 				/*
   4726 				**	Give more "weight" to buildings that cost more. The presumption is that cheap
   4727 				**	buildings don't affect the base disposition as much as the more expensive
   4728 				**	buildings do.
   4729 				*/
   4730 				int weight = (b->Class->Cost_Of() / 1000)+1;
   4731 				for (int i = 0; i < weight; i++) {
   4732 					x += Coord_X(b->Center_Coord());
   4733 					y += Coord_Y(b->Center_Coord());
   4734 					count++;
   4735 				}
   4736 			}
   4737 		}
   4738 
   4739 		/*
   4740 		**	This second check for quantity of buildings is necessary because the first
   4741 		**	check against CurBuildings doesn't take into account if the building is in
   4742 		**	limbo, but for base calculation, the limbo state disqualifies a building
   4743 		**	from being processed. Thus, CurBuildings may indicate a base, but count may
   4744 		**	not match.
   4745 		*/
   4746 		if (count > 0) {
   4747 			x /= count;
   4748 			y /= count;
   4749 
   4750 #ifdef NEVER
   4751 			/*
   4752 			**	Bias the center of the base away from the edges of the map.
   4753 			*/
   4754 			LEPTON left = Cell_To_Lepton(Map.MapCellX + 10);
   4755 			LEPTON top = Cell_To_Lepton(Map.MapCellY + 10);
   4756 			LEPTON right = Cell_To_Lepton(Map.MapCellX + Map.MapCellWidth - 10);
   4757 			LEPTON bottom = Cell_To_Lepton(Map.MapCellY + Map.MapCellHeight - 10);
   4758 			if (x < left) x = left;
   4759 			if (x > right) x = right;
   4760 			if (y < top) y = top;
   4761 			if (y > bottom) y = bottom;
   4762 #endif
   4763 
   4764 			Center = XY_Coord(x, y);
   4765 		}
   4766 
   4767 		/*
   4768 		**	If there were any buildings discovered as legal to consider as part of the base,
   4769 		**	then figure out the general average radius of the building disposition as it
   4770 		**	relates to the center of the base.
   4771 		*/
   4772 		if (count > 1) {
   4773 			int radius = 0;
   4774 	
   4775 			for (index = 0; index < Buildings.Count(); index++) {
   4776 				BuildingClass const * b = Buildings.Ptr(index);
   4777 
   4778 				if (b != NULL && !b->IsInLimbo && (HouseClass *)b->House == this && b->Strength > 0) {
   4779 					radius += Distance(Center, b->Center_Coord());
   4780 				}
   4781 			}
   4782 			Radius = max(radius / count, 2 * CELL_LEPTON_W);
   4783 
   4784 			/*
   4785 			**	Determine the relative strength of each base defense zone.
   4786 			*/
   4787 			for (index = 0; index < Buildings.Count(); index++) {
   4788 				BuildingClass const * b = Buildings.Ptr(index);
   4789 
   4790 				if (b != NULL && !b->IsInLimbo && (HouseClass *)b->House == this && b->Strength > 0) {
   4791 					ZoneType z = Which_Zone(b);
   4792 
   4793 					if (z != ZONE_NONE) {
   4794 						ZoneInfo[z].ArmorDefense += b->Anti_Armor();
   4795 						ZoneInfo[z].AirDefense += b->Anti_Air();
   4796 						ZoneInfo[z].InfantryDefense += b->Anti_Infantry();
   4797 					}
   4798 				}
   4799 			}
   4800 
   4801 		} else {
   4802 			Radius = 0x0200;
   4803 		}
   4804 	}
   4805 }
   4806 
   4807 
   4808 /***********************************************************************************************
   4809  * HouseClass::Expert_AI -- Handles expert AI processing.                                      *
   4810  *                                                                                             *
   4811  *    This routine is called when the computer should perform expert AI processing. This       *
   4812  *    method of AI is categorized as an "Expert System" process.                               *
   4813  *                                                                                             *
   4814  * INPUT:   none                                                                               *
   4815  *                                                                                             *
   4816  * OUTPUT:  Returns the number of game frames to delay before calling this routine again.      *
   4817  *                                                                                             *
   4818  * WARNINGS:   This is relatively time consuming -- call periodically.                         *
   4819  *                                                                                             *
   4820  * HISTORY:                                                                                    *
   4821  *   09/29/1995 JLB : Created.                                                                 *
   4822  *=============================================================================================*/
   4823 int HouseClass::Expert_AI(void)
   4824 {
   4825 	assert(Houses.ID(this) == ID);
   4826 
   4827 	BuildingClass * b = 0;
   4828 	bool stop = false;
   4829 	int time = TICKS_PER_SECOND * 10;
   4830 
   4831 	/*
   4832 	**	If the current enemy no longer has a base or is defeated, then don't consider
   4833 	**	that house a threat anymore. Clear out the enemy record and then try
   4834 	**	to find a new enemy.
   4835 	*/
   4836 	if (Enemy != HOUSE_NONE) {
   4837 		HouseClass * h = HouseClass::As_Pointer(Enemy);
   4838 
   4839 		if (h == NULL || !h->IsActive || h->IsDefeated || Is_Ally(h) || h->BScan == 0) {
   4840 			Enemy = HOUSE_NONE;
   4841 		}
   4842 	}
   4843 
   4844 	/*
   4845 	**	If there is no enemy assigned to this house, then assign one now. The
   4846 	**	enemy that is closest is picked. However, don't pick an enemy if the
   4847 	**	base has not been established yet.
   4848 	*/
   4849 	if (ActiveBScan && Center && Attack == 0) {
   4850 		int close = 0;
   4851 		HousesType enemy = HOUSE_NONE;
   4852 		int maxunit = 0;
   4853 		int maxinfantry = 0;
   4854 		int maxvessel = 0;
   4855 		int maxaircraft = 0;
   4856 		int maxbuilding = 0;
   4857 		int enemycount = 0;
   4858 
   4859 		for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
   4860 			HouseClass * h = HouseClass::As_Pointer(house);
   4861 			if (h != NULL && h->IsActive && !h->IsDefeated && !Is_Ally(h)) {
   4862 
   4863 				/*
   4864 				**	Perform a special restriction check to ensure that no enemy is chosen if
   4865 				**	there is even one enemy that has not established a base yet. This will
   4866 				**	ensure an accurate first pick for enemy since the distance to base
   4867 				**	value can be determined.
   4868 				*/
   4869 				if (!h->IsStarted) {
   4870 					enemy = HOUSE_NONE;
   4871 					break;
   4872 				}
   4873 
   4874 				/*
   4875 				**	Keep track of the number of buildings and units owned by the
   4876 				**	enemy. This is used to bring up the maximum allowed to match.
   4877 				*/
   4878 				maxunit += h->CurUnits;
   4879 				maxbuilding += h->CurBuildings;
   4880 				maxinfantry += h->CurInfantry;
   4881 				maxvessel += h->CurVessels;
   4882 				maxaircraft += h->CurAircraft;
   4883 				enemycount++;
   4884 
   4885 				/*
   4886 				**	Determine a priority value based on distance to the center of the
   4887 				**	candidate base. The higher the value, the better the candidate house
   4888 				**	is to becoming the preferred enemy for this house.
   4889 				*/
   4890 				int value = ((MAP_CELL_W*2)-Distance(Center, h->Center));
   4891 				value *= 2;
   4892 
   4893 				/*
   4894 				**	In addition to distance, record the number of kills directed
   4895 				**	against this house. The enemy that does more damage might be
   4896 				**	considered a greater threat.
   4897 				*/
   4898 				value += h->BuildingsKilled[Class->House]*5;
   4899 				value += h->UnitsKilled[Class->House];
   4900 
   4901 				/*
   4902 				**	Factor in the relative sizes of the bases. An enemy that has a
   4903 				**	larger base will be considered a bigger threat. Conversely, a
   4904 				**	smaller base is considered a lesser threat.
   4905 				*/
   4906 				value += h->CurUnits - CurUnits;
   4907 				value += h->CurBuildings - CurBuildings;
   4908 				value += (h->CurInfantry - CurInfantry)/4;
   4909 
   4910 				/*
   4911 				**	Whoever last attacked is given a little more priority as
   4912 				**	a potential designated enemy.
   4913 				*/
   4914 				if (house == LAEnemy) {
   4915 					value += 100;
   4916 				}
   4917 
   4918 #ifdef OBSOLETE
   4919 				/*
   4920 				**	Human players are a given preference as the target.
   4921 				*/
   4922 				if (h->IsHuman) {
   4923 					value *= 2;
   4924 				}
   4925 #endif
   4926 
   4927 				/*
   4928 				**	Compare the calculated value for this candidate house and if it is
   4929 				**	greater than the previously recorded maximum, record this house as
   4930 				**	the prime candidate for enemy.
   4931 				*/
   4932 				if (value > close) {
   4933 					enemy = house;
   4934 					close = value;
   4935 				}
   4936 			}
   4937 		}
   4938 
   4939 		/*
   4940 		**	Record this closest enemy base as the first enemy to attack.
   4941 		*/
   4942 		Enemy = enemy;
   4943 
   4944 		/*
   4945 		**	Up the maximum allowed units and buildings to match a rough average
   4946 		**	of what the enemies are allowed.
   4947 		*/
   4948 		if (enemycount) {
   4949 			maxunit /= enemycount;
   4950 			maxbuilding /= enemycount;
   4951 			maxinfantry /= enemycount;
   4952 			maxvessel /= enemycount;
   4953 			maxaircraft /= enemycount;
   4954 		}
   4955 
   4956 		if (Control.MaxBuilding < (unsigned)maxbuilding + 10) {
   4957 			Control.MaxBuilding = maxbuilding + 10;
   4958 		}
   4959 		if (Control.MaxUnit < (unsigned)maxunit + 10) {
   4960 			Control.MaxUnit = maxunit + 10;
   4961 		}
   4962 		if (Control.MaxInfantry < (unsigned)maxinfantry + 10) {
   4963 			Control.MaxInfantry = maxinfantry + 10;
   4964 		}
   4965 		if (Control.MaxVessel < (unsigned)maxvessel + 10) {
   4966 			Control.MaxVessel = maxvessel + 10;
   4967 		}
   4968 		if (Control.MaxAircraft < (unsigned)maxaircraft + 10) {
   4969 			Control.MaxAircraft = maxaircraft + 10;
   4970 		}
   4971 	}
   4972 
   4973 	/*
   4974 	**	House state transition check occurs here. Transitions that occur here are ones
   4975 	**	that relate to general base condition rather than specific combat events.
   4976 	**	Typically, this is limited to transitions between normal buildup mode and
   4977 	**	broke mode.
   4978 	*/
   4979 	if (State == STATE_ENDGAME) {
   4980 		Fire_Sale();
   4981 		Do_All_To_Hunt();
   4982 	} else {
   4983 		if (State == STATE_BUILDUP) {
   4984 			if (Available_Money() < 25) {
   4985 				State = STATE_BROKE;
   4986 			}
   4987 		}
   4988 		if (State == STATE_BROKE) {
   4989 			if (Available_Money() >= 25) {
   4990 				State = STATE_BUILDUP;
   4991 			}
   4992 		}
   4993 		if (State == STATE_ATTACKED && LATime + TICKS_PER_MINUTE < Frame) {
   4994 			State = STATE_BUILDUP;
   4995 		}
   4996 		if (State != STATE_ATTACKED && LATime + TICKS_PER_MINUTE > Frame) {
   4997 			State = STATE_ATTACKED;
   4998 		}
   4999 	}
   5000 
   5001 	/*
   5002 	**	Records the urgency of all actions possible.
   5003 	*/
   5004 	UrgencyType urgency[STRATEGY_COUNT];
   5005 	StrategyType strat;
   5006 	for (strat = STRATEGY_FIRST; strat < STRATEGY_COUNT; strat++) {
   5007 		urgency[strat] = URGENCY_NONE;
   5008 
   5009 		switch (strat) {
   5010 			case STRATEGY_BUILD_POWER:
   5011 				urgency[strat] = Check_Build_Power();
   5012 				break;
   5013 
   5014 			case STRATEGY_BUILD_DEFENSE:
   5015 				urgency[strat] = Check_Build_Defense();
   5016 				break;
   5017 
   5018 			case STRATEGY_BUILD_INCOME:
   5019 				urgency[strat] = Check_Build_Income();
   5020 				break;
   5021 
   5022 			case STRATEGY_FIRE_SALE:
   5023 				urgency[strat] = Check_Fire_Sale();
   5024 				break;
   5025 
   5026 			case STRATEGY_BUILD_ENGINEER:
   5027 				urgency[strat] = Check_Build_Engineer();
   5028 				break;
   5029 
   5030 			case STRATEGY_BUILD_OFFENSE:
   5031 				urgency[strat] = Check_Build_Offense();
   5032 				break;
   5033 
   5034 			case STRATEGY_RAISE_MONEY:
   5035 				urgency[strat] = Check_Raise_Money();
   5036 				break;
   5037 
   5038 			case STRATEGY_RAISE_POWER:
   5039 				urgency[strat] = Check_Raise_Power();
   5040 				break;
   5041 
   5042 			case STRATEGY_LOWER_POWER:
   5043 				urgency[strat] = Check_Lower_Power();
   5044 				break;
   5045 
   5046 			case STRATEGY_ATTACK:
   5047 				urgency[strat] = Check_Attack();
   5048 				break;
   5049 
   5050 			default:
   5051 				urgency[strat] = URGENCY_NONE;
   5052 				break;
   5053 		}
   5054 	}
   5055 
   5056 	/*
   5057 	**	Performs the action required for each of the strategies that share
   5058 	**	the most urgent category. Stop processing if any strategy at the
   5059 	**	highest urgency performed any action. This is because higher urgency
   5060 	**	actions tend to greatly affect the lower urgency actions.
   5061 	*/
   5062 	for (UrgencyType u = URGENCY_CRITICAL; u >= URGENCY_LOW; u--) {
   5063 		bool acted = false;
   5064 
   5065 		for (strat = STRATEGY_FIRST; strat < STRATEGY_COUNT; strat++) {
   5066 			if (urgency[strat] == u) {
   5067 				switch (strat) {
   5068 					case STRATEGY_BUILD_POWER:
   5069 						acted |= AI_Build_Power(u);
   5070 						break;
   5071 
   5072 					case STRATEGY_BUILD_DEFENSE:
   5073 						acted |= AI_Build_Defense(u);
   5074 						break;
   5075 
   5076 					case STRATEGY_BUILD_INCOME:
   5077 						acted |= AI_Build_Income(u);
   5078 						break;
   5079 
   5080 					case STRATEGY_FIRE_SALE:
   5081 						acted |= AI_Fire_Sale(u);
   5082 						break;
   5083 
   5084 					case STRATEGY_BUILD_ENGINEER:
   5085 						acted |= AI_Build_Engineer(u);
   5086 						break;
   5087 
   5088 					case STRATEGY_BUILD_OFFENSE:
   5089 						acted |= AI_Build_Offense(u);
   5090 						break;
   5091 
   5092 					case STRATEGY_RAISE_MONEY:
   5093 						acted |= AI_Raise_Money(u);
   5094 						break;
   5095 
   5096 					case STRATEGY_RAISE_POWER:
   5097 						acted |= AI_Raise_Power(u);
   5098 						break;
   5099 
   5100 					case STRATEGY_LOWER_POWER:
   5101 						acted |= AI_Lower_Power(u);
   5102 						break;
   5103 
   5104 					case STRATEGY_ATTACK:
   5105 						acted |= AI_Attack(u);
   5106 						break;
   5107 
   5108 					default:
   5109 						break;
   5110 				}
   5111 			}
   5112 		}
   5113 	}
   5114 
   5115 	return(TICKS_PER_SECOND*5 + Random_Pick(1, TICKS_PER_SECOND/2));
   5116 }
   5117 
   5118 
   5119 UrgencyType HouseClass::Check_Build_Power(void) const
   5120 {
   5121 	assert(Houses.ID(this) == ID);
   5122 
   5123 	fixed frac = Power_Fraction();
   5124 	UrgencyType urgency = URGENCY_NONE;
   5125 
   5126 	if (frac < 1 && Can_Make_Money()) {
   5127 		urgency = URGENCY_LOW;
   5128 
   5129 		/*
   5130 		**	Very low power condition is considered a higher priority.
   5131 		*/
   5132 		if (frac < fixed::_3_4) urgency = URGENCY_MEDIUM;
   5133 
   5134 		/*
   5135 		**	When under attack and there is a need for power in defense,
   5136 		**	then consider power building a higher priority.
   5137 		*/
   5138 		if (State == STATE_THREATENED || State == STATE_ATTACKED) {
   5139 			if (BScan | (STRUCTF_CHRONOSPHERE)) {
   5140 				urgency = URGENCY_HIGH;
   5141 			}
   5142 		}
   5143 
   5144 	}
   5145 	return(urgency);
   5146 }
   5147 
   5148 
   5149 UrgencyType HouseClass::Check_Build_Defense(void) const
   5150 {
   5151 	assert(Houses.ID(this) == ID);
   5152 
   5153 	/*
   5154 	**	This routine determines what urgency level that base defense
   5155 	**	should be given. The more vulnerable the base is, the higher
   5156 	**	the urgency this routine should return.
   5157 	*/
   5158 	return(URGENCY_NONE);
   5159 }
   5160 
   5161 
   5162 UrgencyType HouseClass::Check_Build_Offense(void) const
   5163 {
   5164 	assert(Houses.ID(this) == ID);
   5165 
   5166 	/*
   5167 	**	This routine determines what urgency level that offensive
   5168 	**	weaponry should be given. Surplus money or a very strong
   5169 	**	defense will cause the offensive urgency to increase.
   5170 	*/
   5171 	return(URGENCY_NONE);
   5172 }
   5173 
   5174 /*
   5175 **	Determines what the attack state of the base is. The higher the state,
   5176 **	the greater the immediate threat to base defense is.
   5177 */
   5178 UrgencyType HouseClass::Check_Attack(void) const
   5179 {
   5180 	assert(Houses.ID(this) == ID);
   5181 
   5182 	if (Frame > TICKS_PER_MINUTE && Attack == 0) {
   5183 		if (State == STATE_ATTACKED) {
   5184 			return(URGENCY_LOW);
   5185 		}
   5186 		return(URGENCY_CRITICAL);
   5187 	}
   5188 	return(URGENCY_NONE);
   5189 }
   5190 
   5191 
   5192 UrgencyType HouseClass::Check_Build_Income(void) const
   5193 {
   5194 	assert(Houses.ID(this) == ID);
   5195 
   5196 	/*
   5197 	**	This routine should determine if income processing buildings
   5198 	**	should be constructed and at what urgency. The lower the money,
   5199 	**	the lower the refineries, or recent harvester losses should
   5200 	**	cause a greater urgency to be returned.
   5201 	*/
   5202 	return(URGENCY_NONE);
   5203 }
   5204 
   5205 
   5206 UrgencyType HouseClass::Check_Fire_Sale(void) const
   5207 {
   5208 	assert(Houses.ID(this) == ID);
   5209 
   5210 	/*
   5211 	**	If there are no more factories at all, then sell everything off because the game
   5212 	**	is basically over at this point.
   5213 	*/
   5214 	if (State != STATE_ATTACKED && CurBuildings && !(ActiveBScan & (STRUCTF_TENT|STRUCTF_BARRACKS|STRUCTF_CONST|STRUCTF_AIRSTRIP|STRUCTF_WEAP|STRUCTF_HELIPAD))) {
   5215 		return(URGENCY_CRITICAL);
   5216 	}
   5217 	return(URGENCY_NONE);
   5218 }
   5219 
   5220 
   5221 UrgencyType HouseClass::Check_Build_Engineer(void) const
   5222 {
   5223 	assert(Houses.ID(this) == ID);
   5224 
   5225 	/*
   5226 	**	This routine should check to see what urgency that the production of
   5227 	**	engineers should be. If a friendly building has been captured or the
   5228 	**	enemy has weak defenses, then building an engineer would be a priority.
   5229 	*/
   5230 	return(URGENCY_NONE);
   5231 }
   5232 
   5233 
   5234 /*
   5235 **	Checks to see if money is critically low and something must be done
   5236 **	to immediately raise cash.
   5237 */
   5238 UrgencyType HouseClass::Check_Raise_Money(void) const
   5239 {
   5240 	assert(Houses.ID(this) == ID);
   5241 
   5242 	UrgencyType urgency = URGENCY_NONE;
   5243 	if (Available_Money() < 100) {
   5244 		urgency = URGENCY_LOW;
   5245 	}
   5246 	if (Available_Money() < 2000 && !Can_Make_Money()) {
   5247 		urgency++;
   5248 	}
   5249 
   5250 	return(urgency);
   5251 }
   5252 
   5253 /*
   5254 **	Checks to see if power is very low and if so, a greater urgency to
   5255 **	build more power is returned.
   5256 */
   5257 UrgencyType HouseClass::Check_Lower_Power(void) const
   5258 {
   5259 	assert(Houses.ID(this) == ID);
   5260 
   5261 	if (Power > Drain+300) {
   5262 		return(URGENCY_LOW);
   5263 	}
   5264 	return(URGENCY_NONE);
   5265 }
   5266 
   5267 /*
   5268 **	This routine determines if there is a power emergency. Such an
   5269 **	emergency might require selling of structures in order to free
   5270 **	up power. This might occur if the base is being attacked and there
   5271 **	are defenses that require power, but are just short of having
   5272 **	enough.
   5273 */
   5274 UrgencyType HouseClass::Check_Raise_Power(void) const
   5275 {
   5276 	assert(Houses.ID(this) == ID);
   5277 
   5278 	UrgencyType urgency = URGENCY_NONE;
   5279 
   5280 	if (Power_Fraction() < Rule.PowerEmergencyFraction && Power < Drain - 400) {
   5281 //	if (Power_Fraction() < Rule.PowerEmergencyFraction && (BQuantity[STRUCT_CONST] == 0 || Available_Money() < 200 || Power < Drain-400)) {
   5282 		urgency = URGENCY_MEDIUM;
   5283 		if (State == STATE_ATTACKED) {
   5284 			urgency++;
   5285 		}
   5286 	}
   5287 	return(urgency);
   5288 }
   5289 
   5290 
   5291 bool HouseClass::AI_Attack(UrgencyType )
   5292 {
   5293 	assert(Houses.ID(this) == ID);
   5294 
   5295 	bool shuffle = !((Frame > TICKS_PER_MINUTE && !CurBuildings) || Percent_Chance(33));
   5296 	bool forced = (CurBuildings == 0);
   5297 	int index;
   5298 	for (index = 0; index < Aircraft.Count(); index++) {
   5299 		AircraftClass * a = Aircraft.Ptr(index);
   5300 
   5301 		if (a != NULL && !a->IsInLimbo && a->House == this && a->Strength > 0) {
   5302 			if (!shuffle && a->Is_Weapon_Equipped() && (forced || Percent_Chance(75))) {
   5303 				a->Assign_Mission(MISSION_HUNT);
   5304 			}
   5305 		}
   5306 	}
   5307 	for (index = 0; index < Units.Count(); index++) {
   5308 		UnitClass * u = Units.Ptr(index);
   5309 
   5310 		if (u != NULL && !u->IsInLimbo && u->House == this && u->Strength > 0) {
   5311 			if (!shuffle && u->Is_Weapon_Equipped() && (forced || Percent_Chance(75))) {
   5312 				u->Assign_Mission(MISSION_HUNT);
   5313 			} else {
   5314 
   5315 				/*
   5316 				**	If this unit is guarding the base, then cause it to shuffle
   5317 				**	location instead.
   5318 				*/
   5319 				if (Percent_Chance(20) && u->Mission == MISSION_GUARD_AREA && Which_Zone(u) != ZONE_NONE) {
   5320 					u->ArchiveTarget = ::As_Target(Where_To_Go(u));
   5321 				}
   5322 			}
   5323 		}
   5324 	}
   5325 	for (index = 0; index < Infantry.Count(); index++) {
   5326 		InfantryClass * i = Infantry.Ptr(index);
   5327 
   5328 		if (i != NULL && !i->IsInLimbo && i->House == this && i->Strength > 0) {
   5329 			if (!shuffle && (i->Is_Weapon_Equipped() || *i == INFANTRY_RENOVATOR) && (forced || Percent_Chance(75))) {
   5330 				i->Assign_Mission(MISSION_HUNT);
   5331 			} else {
   5332 
   5333 				/*
   5334 				**	If this soldier is guarding the base, then cause it to shuffle
   5335 				**	location instead.
   5336 				*/
   5337 				if (Percent_Chance(20) && i->Mission == MISSION_GUARD_AREA && Which_Zone(i) != ZONE_NONE) {
   5338 					i->ArchiveTarget = ::As_Target(Where_To_Go(i));
   5339 				}
   5340 			}
   5341 		}
   5342 	}
   5343 	Attack = Rule.AttackInterval * Random_Pick(TICKS_PER_MINUTE/2, TICKS_PER_MINUTE*2);
   5344 	return(true);
   5345 }
   5346 
   5347 
   5348 /*
   5349 **	Given the specified urgency, build a power structure to meet
   5350 **	this need.
   5351 */
   5352 bool HouseClass::AI_Build_Power(UrgencyType ) const
   5353 {
   5354 	assert(Houses.ID(this) == ID);
   5355 
   5356 	return(false);
   5357 }
   5358 
   5359 
   5360 /*
   5361 **	Given the specified urgency, build base defensive structures
   5362 **	according to need and according to existing base disposition.
   5363 */
   5364 bool HouseClass::AI_Build_Defense(UrgencyType ) const
   5365 {
   5366 	assert(Houses.ID(this) == ID);
   5367 
   5368 	return(false);
   5369 }
   5370 
   5371 /*
   5372 **	Given the specified urgency, build offensive units according
   5373 **	to need and according to the opponents base defenses.
   5374 */
   5375 bool HouseClass::AI_Build_Offense(UrgencyType ) const
   5376 {
   5377 	assert(Houses.ID(this) == ID);
   5378 
   5379 	return(false);
   5380 }
   5381 
   5382 /*
   5383 **	Given the specified urgency, build income producing
   5384 **	structures according to need.
   5385 */
   5386 bool HouseClass::AI_Build_Income(UrgencyType ) const
   5387 {
   5388 	assert(Houses.ID(this) == ID);
   5389 
   5390 	return(false);
   5391 }
   5392 
   5393 
   5394 bool HouseClass::AI_Fire_Sale(UrgencyType urgency)
   5395 {
   5396 	assert(Houses.ID(this) == ID);
   5397 
   5398 	if (CurBuildings && urgency == URGENCY_CRITICAL) {
   5399 		Fire_Sale();
   5400 		Do_All_To_Hunt();
   5401 		return(true);
   5402 	}
   5403 	return(false);
   5404 }
   5405 
   5406 /*
   5407 **	Given the specified urgency, build an engineer.
   5408 */
   5409 bool HouseClass::AI_Build_Engineer(UrgencyType ) const
   5410 {
   5411 	assert(Houses.ID(this) == ID);
   5412 
   5413 	return(false);
   5414 }
   5415 
   5416 /*
   5417 **	Given the specified urgency, sell of some power since
   5418 **	there appears to be excess.
   5419 */
   5420 bool HouseClass::AI_Lower_Power(UrgencyType ) const
   5421 {
   5422 	assert(Houses.ID(this) == ID);
   5423 
   5424 	BuildingClass * b = Find_Building(STRUCT_POWER);
   5425 	if (b != NULL) {
   5426 		b->Sell_Back(1);
   5427 		return(true);
   5428 	}
   5429 
   5430 	b = Find_Building(STRUCT_ADVANCED_POWER);
   5431 	if (b != NULL) {
   5432 		b->Sell_Back(1);
   5433 		return(true);
   5434 	}
   5435 	return(false);
   5436 }
   5437 
   5438 
   5439 /***********************************************************************************************
   5440  * HouseClass::AI_Raise_Power -- Try to raise power levels by selling off buildings.           *
   5441  *                                                                                             *
   5442  *    This routine is called when the computer needs to raise power by selling off buildings.  *
   5443  *    Usually this occurs because of some catastrophe that has lowered power levels to         *
   5444  *    the danger zone.                                                                         *
   5445  *                                                                                             *
   5446  * INPUT:   urgency  -- The urgency that the power needs to be raised. This controls what      *
   5447  *                      buildings will be sold.                                                *
   5448  *                                                                                             *
   5449  * OUTPUT:  bool; Was a building sold to raise power?                                          *
   5450  *                                                                                             *
   5451  * WARNINGS:   none                                                                            *
   5452  *                                                                                             *
   5453  * HISTORY:                                                                                    *
   5454  *   11/02/1996 JLB : Created.                                                                 *
   5455  *=============================================================================================*/
   5456 bool HouseClass::AI_Raise_Power(UrgencyType urgency) const
   5457 {
   5458 	assert(Houses.ID(this) == ID);
   5459 
   5460 	/*
   5461 	**	Sell off structures in this order.
   5462 	*/
   5463 	static struct {
   5464 		StructType Structure;
   5465 		UrgencyType Urgency;
   5466 	} _types[] = {
   5467 		{STRUCT_CHRONOSPHERE, URGENCY_LOW},
   5468 		{STRUCT_SHIP_YARD, URGENCY_LOW},
   5469 		{STRUCT_SUB_PEN, URGENCY_LOW},
   5470 		{STRUCT_ADVANCED_TECH, URGENCY_LOW},
   5471 		{STRUCT_FORWARD_COM, URGENCY_LOW},
   5472 		{STRUCT_SOVIET_TECH, URGENCY_LOW},
   5473 		{STRUCT_IRON_CURTAIN, URGENCY_MEDIUM},
   5474 		{STRUCT_RADAR, URGENCY_MEDIUM},
   5475 		{STRUCT_REPAIR, URGENCY_MEDIUM},
   5476 		{STRUCT_TESLA, URGENCY_HIGH}
   5477 	};
   5478 
   5479 	/*
   5480 	**	Find a structure to sell and then sell it. Bail from further scanning until
   5481 	**	the next time.
   5482 	*/
   5483 	for (int i = 0; i < ARRAY_SIZE(_types); i++) {
   5484 		if (urgency >= _types[i].Urgency) {
   5485 			BuildingClass * b = Find_Building(_types[i].Structure);
   5486 			if (b != NULL) {
   5487 				b->Sell_Back(1);
   5488 				return(true);
   5489 			}
   5490 		}
   5491 	}
   5492 	return(false);
   5493 }
   5494 
   5495 
   5496 /***********************************************************************************************
   5497  * HouseClass::AI_Raise_Money -- Raise emergency cash by selling buildings.                    *
   5498  *                                                                                             *
   5499  *    This routine handles the situation where the computer desperately needs cash but cannot  *
   5500  *    wait for normal harvesting to raise it. Buildings must be sold.                          *
   5501  *                                                                                             *
   5502  * INPUT:   urgency  -- The urgency level that cash must be raised. The greater the urgency,   *
   5503  *                      the more important the buildings that can be sold become.              *
   5504  *                                                                                             *
   5505  * OUTPUT:  bool; Was a building sold to raise cash?                                           *
   5506  *                                                                                             *
   5507  * WARNINGS:   none                                                                            *
   5508  *                                                                                             *
   5509  * HISTORY:                                                                                    *
   5510  *   11/02/1996 JLB : Created.                                                                 *
   5511  *=============================================================================================*/
   5512 bool HouseClass::AI_Raise_Money(UrgencyType urgency) const
   5513 {
   5514 	assert(Houses.ID(this) == ID);
   5515 
   5516 	/*
   5517 	**	Sell off structures in this order.
   5518 	*/
   5519 	static struct {
   5520 		StructType	Structure;
   5521 		UrgencyType	Urgency;
   5522 	} _types[] = {
   5523 		{STRUCT_CHRONOSPHERE, URGENCY_LOW},
   5524 		{STRUCT_SHIP_YARD, URGENCY_LOW},
   5525 		{STRUCT_SUB_PEN, URGENCY_LOW},
   5526 		{STRUCT_ADVANCED_TECH, URGENCY_LOW},
   5527 		{STRUCT_FORWARD_COM, URGENCY_LOW},
   5528 		{STRUCT_SOVIET_TECH, URGENCY_LOW},
   5529 		{STRUCT_STORAGE,URGENCY_LOW},
   5530 		{STRUCT_REPAIR,URGENCY_LOW},
   5531 		{STRUCT_TESLA,URGENCY_MEDIUM},
   5532 		{STRUCT_HELIPAD,URGENCY_MEDIUM},
   5533 		{STRUCT_POWER,URGENCY_HIGH},
   5534 		{STRUCT_AIRSTRIP,URGENCY_HIGH},
   5535 //		{STRUCT_WEAP,URGENCY_HIGH},
   5536 //		{STRUCT_BARRACKS,URGENCY_HIGH},
   5537 //		{STRUCT_TENT,URGENCY_HIGH},
   5538 		{STRUCT_CONST,URGENCY_CRITICAL}
   5539 	};
   5540 	BuildingClass * b = 0;
   5541 
   5542 	/*
   5543 	**	Find a structure to sell and then sell it. Bail from further scanning until
   5544 	**	the next time.
   5545 	*/
   5546 	for (int i = 0; i < ARRAY_SIZE(_types); i++) {
   5547 		if (urgency >= _types[i].Urgency) {
   5548 			b = Find_Building(_types[i].Structure);
   5549 			if (b != NULL) {
   5550 				b->Sell_Back(1);
   5551 				return(true);
   5552 			}
   5553 		}
   5554 	}
   5555 	return(false);
   5556 }
   5557 
   5558 
   5559 #ifdef NEVER
   5560 
   5561 /***********************************************************************************************
   5562  * HouseClass::AI_Base_Defense -- Handles maintaining a strong base defense.                   *
   5563  *                                                                                             *
   5564  *    This logic is used to maintain a base defense.                                           *
   5565  *                                                                                             *
   5566  * INPUT:   none                                                                               *
   5567  *                                                                                             *
   5568  * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *
   5569  *                                                                                             *
   5570  * WARNINGS:   none                                                                            *
   5571  *                                                                                             *
   5572  * HISTORY:                                                                                    *
   5573  *   09/29/1995 JLB : Created.                                                                 *
   5574  *=============================================================================================*/
   5575 int HouseClass::AI_Base_Defense(void)
   5576 {
   5577 	assert(Houses.ID(this) == ID);
   5578 
   5579 	/*
   5580 	**	Check to find if any zone of the base is over defended. Such zones should have
   5581 	**	some of their defenses sold off to make better use of the money.
   5582 	*/
   5583 
   5584 	/*
   5585 	**	Make sure that the core defense is only about 1/2 of the perimeter defense average.
   5586 	*/
   5587 	int average = 0;
   5588 	for (ZoneType z = ZONE_NORTH; z < ZONE_COUNT; z++) {
   5589 		average += ZoneInfo[z].AirDefense;
   5590 		average += ZoneInfo[z].ArmorDefense;
   5591 		average += ZoneInfo[z].InfantryDefense;
   5592 	}
   5593 	average /= (ZONE_COUNT-ZONE_NORTH);
   5594 
   5595 	/*
   5596 	**	If the core value is greater than the average, then sell off some of the
   5597 	**	inner defensive structures.
   5598 	*/
   5599 	int core = ZoneInfo[ZONE_CORE].AirDefense + ZoneInfo[ZONE_CORE].ArmorDefense + ZoneInfo[ZONE_CORE].InfantryDefense;
   5600 	if (core >= average) {
   5601 		static StructType _stype[] = {
   5602 			STRUCT_GTOWER,
   5603 			STRUCT_TURRET,
   5604 			STRUCT_ATOWER,
   5605 			STRUCT_OBELISK,
   5606 			STRUCT_TESLA,
   5607 			STRUCT_SAM
   5608 		};
   5609 		BuildingClass * b;
   5610 
   5611 		for (int index = 0; index < sizeof(_stype)/sizeof(_stype[0]); index++) {
   5612 			b = Find_Building(_stype[index], ZONE_CORE);
   5613 			if (b) {
   5614 				b->Sell_Back(1);
   5615 				break;
   5616 			}
   5617 		}
   5618 	}
   5619 
   5620 	/*
   5621 	**	If the enemy doesn't have any offensive air capability, then sell off any
   5622 	**	SAM sites. Only do this when money is moderately low.
   5623 	*/
   5624 	if (Available_Money() < 1000 && (ActiveBScan & STRUCTF_SAM)) {
   5625 
   5626 		/*
   5627 		**	Scan to find if ANY human opponents have aircraft or a helipad. If one
   5628 		** is found then consider that opponent to have a valid air threat potential.
   5629 		**	Don't sell off SAM sites in that case.
   5630 		*/
   5631 		bool nothreat = true;
   5632 		for (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {
   5633 			HouseClass * house = HouseClass::As_Pointer(h);
   5634 
   5635 			if (house && house->IsActive && house->IsHuman && !Is_Ally(house)) {
   5636 				if ((house->ActiveAScan & (AIRCRAFTF_ORCA|AIRCRAFTF_TRANSPORT|AIRCRAFTF_HELICOPTER)) || (house->ActiveBScan & STRUCTF_HELIPAD)) {
   5637 					nothreat = false;
   5638 					break;
   5639 				}
   5640 			}
   5641 		}
   5642 	}
   5643 
   5644 	return(TICKS_PER_SECOND*5);
   5645 }
   5646 #endif
   5647 
   5648 
   5649 /***********************************************************************************************
   5650  * HouseClass::AI_Building -- Determines what building to build.                               *
   5651  *                                                                                             *
   5652  *    This routine handles the general case of determining what building to build next.        *
   5653  *                                                                                             *
   5654  * INPUT:   none                                                                               *
   5655  *                                                                                             *
   5656  * OUTPUT:  Returns with the number of game frames to delay before calling this routine again. *
   5657  *                                                                                             *
   5658  * WARNINGS:   none                                                                            *
   5659  *                                                                                             *
   5660  * HISTORY:                                                                                    *
   5661  *   09/29/1995 JLB : Created.                                                                 *
   5662  *   11/03/1996 JLB : Tries to match aircraft of enemy                                         *
   5663  *=============================================================================================*/
   5664 int HouseClass::AI_Building(void)
   5665 {
   5666 	assert(Houses.ID(this) == ID);
   5667 
   5668 	if (BuildStructure != STRUCT_NONE) return(TICKS_PER_SECOND);
   5669 
   5670 	if (Session.Type == GAME_NORMAL && Base.House == Class->House) {
   5671 		BaseNodeClass * node = Base.Next_Buildable();
   5672 		if (node) {
   5673 			BuildStructure = node->Type;
   5674 		}
   5675 	}
   5676 
   5677 	if (IsBaseBuilding) {
   5678 		/*
   5679 		**	Don't suggest anything to build if the base is already big enough.
   5680 		*/
   5681 		unsigned int quant = 0;
   5682 		for (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {
   5683 			HouseClass const * hptr = HouseClass::As_Pointer(h);
   5684 
   5685 			if (hptr != NULL && hptr->IsActive && hptr->IsHuman && quant < hptr->CurBuildings) {
   5686 				quant = hptr->CurBuildings;
   5687 			}
   5688 		}
   5689 		quant += Rule.BaseSizeAdd;
   5690 
   5691 // TCTC -- Should multiply largest player base by some rational number.
   5692 //		if (CurBuildings >= quant) return(TICKS_PER_SECOND);
   5693 
   5694 		BuildChoice.Free_All();
   5695 		BuildChoiceClass * choiceptr;
   5696 		StructType stype = STRUCT_NONE;
   5697 		int money = Available_Money();
   5698 		int level = Control.TechLevel;
   5699 		bool hasincome = (BQuantity[STRUCT_REFINERY] > 0 && !IsTiberiumShort && UQuantity[UNIT_HARVESTER] > 0);
   5700 		BuildingTypeClass const * b = NULL;
   5701 		HouseClass const * enemy = NULL;
   5702 		if (Enemy != HOUSE_NONE) {
   5703 			enemy = HouseClass::As_Pointer(Enemy);
   5704 		}
   5705 
   5706 		level = Control.TechLevel;
   5707 
   5708 		/*
   5709 		**	Try to build a power plant if there is insufficient power and there is enough
   5710 		**	money available.
   5711 		*/
   5712 		b = &BuildingTypeClass::As_Reference(STRUCT_ADVANCED_POWER);
   5713 		if (Can_Build(b, ActLike) && Power <= Drain+Rule.PowerSurplus && b->Cost_Of() < money) {
   5714 			choiceptr = BuildChoice.Alloc();
   5715 			if (choiceptr != NULL) {
   5716 				*choiceptr = BuildChoiceClass(BQuantity[STRUCT_REFINERY] == 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);
   5717 			}
   5718 		} else {
   5719 			b = &BuildingTypeClass::As_Reference(STRUCT_POWER);
   5720 			if (Can_Build(b, ActLike) && Power <= Drain+Rule.PowerSurplus && b->Cost_Of() < money) {
   5721 				choiceptr = BuildChoice.Alloc();
   5722 				if (choiceptr != NULL) {
   5723 					*choiceptr = BuildChoiceClass(BQuantity[STRUCT_REFINERY] == 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);
   5724 				}
   5725 			}
   5726 		}
   5727 
   5728 		/*
   5729 		**	Build a refinery if there isn't one already available.
   5730 		*/
   5731 		unsigned int current = BQuantity[STRUCT_REFINERY];
   5732 		if (!IsTiberiumShort && current < Round_Up(Rule.RefineryRatio*fixed(CurBuildings)) && current < (unsigned)Rule.RefineryLimit) {
   5733 			b = &BuildingTypeClass::As_Reference(STRUCT_REFINERY);
   5734 			if (Can_Build(b, ActLike) && (money > b->Cost_Of() || hasincome)) {
   5735 				choiceptr = BuildChoice.Alloc();
   5736 				if (choiceptr != NULL) {
   5737 					*choiceptr = BuildChoiceClass(BQuantity[STRUCT_REFINERY] == 0 ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);
   5738 				}
   5739 			}
   5740 		}
   5741 
   5742 		/*
   5743 		**	Always make sure there is a barracks available, but only if there
   5744 		**	will be sufficient money to train troopers.
   5745 		*/
   5746 		current = BQuantity[STRUCT_BARRACKS] + BQuantity[STRUCT_TENT];
   5747 		if (current < Round_Up(Rule.BarracksRatio*fixed(CurBuildings)) && current < (unsigned)Rule.BarracksLimit && (money > 300 || hasincome)) {
   5748 			b = &BuildingTypeClass::As_Reference(STRUCT_BARRACKS);
   5749 			if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5750 				choiceptr = BuildChoice.Alloc();
   5751 				if (choiceptr != NULL) {
   5752 					*choiceptr = BuildChoiceClass(current > 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);
   5753 				}
   5754 			} else {
   5755 				b = &BuildingTypeClass::As_Reference(STRUCT_TENT);
   5756 				if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5757 					choiceptr = BuildChoice.Alloc();
   5758 					if (choiceptr != NULL) {
   5759 						*choiceptr = BuildChoiceClass(current > 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);
   5760 					}
   5761 				}
   5762 			}
   5763 		}
   5764 
   5765 		/*
   5766 		**	Try to build one dog house.
   5767 		*/
   5768 		current = BQuantity[STRUCT_KENNEL];
   5769 		if (current < 1 && (money > 300 || hasincome)) {
   5770 			b = &BuildingTypeClass::As_Reference(STRUCT_KENNEL);
   5771 			if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5772 				choiceptr = BuildChoice.Alloc();
   5773 				if (choiceptr != NULL) {
   5774 					*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);
   5775 				}
   5776 			}
   5777 		}
   5778 
   5779 		/*
   5780 		**	Try to build one gap generator.
   5781 		*/
   5782 		current = BQuantity[STRUCT_GAP];
   5783 		if (current < 1 && Power_Fraction() >= 1 && hasincome) {
   5784 			b = &BuildingTypeClass::As_Reference(STRUCT_GAP);
   5785 			if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5786 				choiceptr = BuildChoice.Alloc();
   5787 				if (choiceptr != NULL) {
   5788 					*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);
   5789 				}
   5790 			}
   5791 		}
   5792 
   5793 		/*
   5794 		**	A source of combat vehicles is always needed, but only if there will
   5795 		**	be sufficient money to build vehicles.
   5796 		*/
   5797 		current = BQuantity[STRUCT_WEAP];
   5798 		if (current < Round_Up(Rule.WarRatio*fixed(CurBuildings)) && current < (unsigned)Rule.WarLimit && (money > 2000 || hasincome)) {
   5799 			b = &BuildingTypeClass::As_Reference(STRUCT_WEAP);
   5800 			if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5801 				choiceptr = BuildChoice.Alloc();
   5802 				if (choiceptr != NULL) {
   5803 					*choiceptr = BuildChoiceClass(current > 0 ? URGENCY_LOW : URGENCY_MEDIUM, b->Type);
   5804 				}
   5805 			}
   5806 		}
   5807 
   5808 		/*
   5809 		**	Always build up some base defense.
   5810 		*/
   5811 		current = BQuantity[STRUCT_PILLBOX] + BQuantity[STRUCT_CAMOPILLBOX] + BQuantity[STRUCT_TURRET] + BQuantity[STRUCT_FLAME_TURRET];
   5812 		if (current < Round_Up(Rule.DefenseRatio*fixed(CurBuildings)) && current < (unsigned)Rule.DefenseLimit) {
   5813 			b = &BuildingTypeClass::As_Reference(STRUCT_FLAME_TURRET);
   5814 			if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5815 				choiceptr = BuildChoice.Alloc();
   5816 				if (choiceptr != NULL) {
   5817 					*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);
   5818 				}
   5819 			} else {
   5820 				if (Percent_Chance(50)) {
   5821 					b = &BuildingTypeClass::As_Reference(STRUCT_PILLBOX);
   5822 					if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5823 						choiceptr = BuildChoice.Alloc();
   5824 						if (choiceptr != NULL) {
   5825 							*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);
   5826 						}
   5827 					}
   5828 				} else {
   5829 					b = &BuildingTypeClass::As_Reference(STRUCT_TURRET);
   5830 					if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5831 						choiceptr = BuildChoice.Alloc();
   5832 						if (choiceptr != NULL) {
   5833 							*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);
   5834 						}
   5835 					}
   5836 				}
   5837 			}
   5838 		}
   5839 
   5840 		/*
   5841 		**	Build some air defense.
   5842 		*/
   5843 		current = BQuantity[STRUCT_SAM] + BQuantity[STRUCT_AAGUN];
   5844 		if (current < Round_Up(Rule.AARatio*fixed(CurBuildings)) && current < (unsigned)Rule.AALimit) {
   5845 
   5846 			/*
   5847 			**	Building air defense only makes sense if the opponent has aircraft
   5848 			**	of some kind.
   5849 			*/
   5850 			bool airthreat = false;
   5851 			int threat_quantity = 0;
   5852 			if (enemy != NULL && enemy->AScan != 0) {
   5853 				airthreat = true;
   5854 				threat_quantity = enemy->CurAircraft;
   5855 			}
   5856 			if (!airthreat) {
   5857 				for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
   5858 					HouseClass * h = HouseClass::As_Pointer(house);
   5859 					if (h != NULL && !Is_Ally(house) && h->AScan != 0) {
   5860 						airthreat = true;
   5861 						break;
   5862 					}
   5863 				}
   5864 			}
   5865 
   5866 			if (airthreat) {
   5867 
   5868 				if (BQuantity[STRUCT_RADAR] == 0) {
   5869 					b = &BuildingTypeClass::As_Reference(STRUCT_RADAR);
   5870 					if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5871 						choiceptr = BuildChoice.Alloc();
   5872 						if (choiceptr != NULL) {
   5873 							*choiceptr = BuildChoiceClass(URGENCY_HIGH, b->Type);
   5874 						}
   5875 					}
   5876 				}
   5877 
   5878 				b = &BuildingTypeClass::As_Reference(STRUCT_SAM);
   5879 				if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5880 					choiceptr = BuildChoice.Alloc();
   5881 					if (choiceptr != NULL) {
   5882 						*choiceptr = BuildChoiceClass((current < (unsigned)threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);
   5883 					}
   5884 				} else {
   5885 					b = &BuildingTypeClass::As_Reference(STRUCT_AAGUN);
   5886 					if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5887 						choiceptr = BuildChoice.Alloc();
   5888 						if (choiceptr != NULL) {
   5889 							*choiceptr = BuildChoiceClass((current < (unsigned)threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);
   5890 						}
   5891 					}
   5892 				}
   5893 			}
   5894 		}
   5895 
   5896 		/*
   5897 		**	Advanced base defense would be good.
   5898 		*/
   5899 		current = BQuantity[STRUCT_TESLA];
   5900 		if (current < Round_Up(Rule.TeslaRatio*fixed(CurBuildings)) && current < (unsigned)Rule.TeslaLimit) {
   5901 			b = &BuildingTypeClass::As_Reference(STRUCT_TESLA);
   5902 			if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome) && Power_Fraction() >= 1) {
   5903 				choiceptr = BuildChoice.Alloc();
   5904 				if (choiceptr != NULL) {
   5905 					*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);
   5906 				}
   5907 			}
   5908 		}
   5909 
   5910 		/*
   5911 		**	Build a tech center as soon as possible.
   5912 		*/
   5913 		current = BQuantity[STRUCT_ADVANCED_TECH] + BQuantity[STRUCT_SOVIET_TECH];
   5914 		if (current < 1) {
   5915 			b = &BuildingTypeClass::As_Reference(STRUCT_ADVANCED_TECH);
   5916 			if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome) && Power_Fraction() >= 1) {
   5917 				choiceptr = BuildChoice.Alloc();
   5918 				if (choiceptr != NULL) {
   5919 					*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);
   5920 				}
   5921 			} else {
   5922 				b = &BuildingTypeClass::As_Reference(STRUCT_SOVIET_TECH);
   5923 				if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome) && Power_Fraction() >= 1) {
   5924 					choiceptr = BuildChoice.Alloc();
   5925 					if (choiceptr != NULL) {
   5926 						*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);
   5927 					}
   5928 				}
   5929 			}
   5930 		}
   5931 
   5932 		/*
   5933 		**	A helipad would be good.
   5934 		*/
   5935 		current = BQuantity[STRUCT_HELIPAD];
   5936 		if (current < Round_Up(Rule.HelipadRatio*fixed(CurBuildings)) && current < (unsigned)Rule.HelipadLimit) {
   5937 			b = &BuildingTypeClass::As_Reference(STRUCT_HELIPAD);
   5938 			if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5939 				choiceptr = BuildChoice.Alloc();
   5940 				if (choiceptr != NULL) {
   5941 					int threat_quantity = 0;
   5942 					if (enemy != NULL) {
   5943 						threat_quantity = enemy->CurAircraft;
   5944 					}
   5945 
   5946 					*choiceptr = BuildChoiceClass((CurAircraft < (unsigned)threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);
   5947 				}
   5948 			}
   5949 		}
   5950 
   5951 		/*
   5952 		**	An airstrip would be good.
   5953 		*/
   5954 		current = BQuantity[STRUCT_AIRSTRIP];
   5955 		if (current < Round_Up(Rule.AirstripRatio*fixed(CurBuildings)) && current < (unsigned)Rule.AirstripLimit) {
   5956 			b = &BuildingTypeClass::As_Reference(STRUCT_AIRSTRIP);
   5957 			if (Can_Build(b, ActLike) && (b->Cost_Of() < money || hasincome)) {
   5958 				choiceptr = BuildChoice.Alloc();
   5959 				if (choiceptr != NULL) {
   5960 					int threat_quantity = 0;
   5961 					if (enemy != NULL) {
   5962 						threat_quantity = enemy->CurAircraft;
   5963 					}
   5964 
   5965 					*choiceptr = BuildChoiceClass((CurAircraft < (unsigned)threat_quantity) ? URGENCY_HIGH : URGENCY_MEDIUM, b->Type);
   5966 				}
   5967 			}
   5968 		}
   5969 
   5970 #ifdef OLD
   5971 		/*
   5972 		**	Build a repair bay if there isn't one already available.
   5973 		*/
   5974 		current = BQuantity[STRUCT_REPAIR];
   5975 		if (current == 0) {
   5976 			b = &BuildingTypeClass::As_Reference(STRUCT_REPAIR);
   5977 			if (Can_Build(b, ActLike) && b->Cost_Of() < money) {
   5978 				choiceptr = BuildChoice.Alloc();
   5979 				if (choiceptr) {
   5980 					*choiceptr = BuildChoiceClass(URGENCY_MEDIUM, b->Type);
   5981 				}
   5982 			}
   5983 		}
   5984 #endif
   5985 
   5986 		/*
   5987 		**	Pick the choice that is the most urgent.
   5988 		*/
   5989 		UrgencyType best = URGENCY_NONE;
   5990 		int bestindex;
   5991 		for (int index = 0; index < BuildChoice.Count(); index++) {
   5992 			if (BuildChoice.Ptr(index)->Urgency > best) {
   5993 				bestindex = index;
   5994 				best = BuildChoice.Ptr(index)->Urgency;
   5995 			}
   5996 		}
   5997 		if (best != URGENCY_NONE) {
   5998 			BuildStructure = BuildChoice.Ptr(bestindex)->Structure;
   5999 		}
   6000 	}
   6001 
   6002 	return(TICKS_PER_SECOND);
   6003 }
   6004 
   6005 
   6006 /***********************************************************************************************
   6007  * HouseClass::AI_Unit -- Determines what unit to build next.                                  *
   6008  *                                                                                             *
   6009  *    This routine handles the general case of determining what units to build next.           *
   6010  *                                                                                             *
   6011  * INPUT:   none                                                                               *
   6012  *                                                                                             *
   6013  * OUTPUT:  Returns with the number of games frames to delay before calling this routine again.*
   6014  *                                                                                             *
   6015  * WARNINGS:   none                                                                            *
   6016  *                                                                                             *
   6017  * HISTORY:                                                                                    *
   6018  *   09/29/1995 JLB : Created.                                                                 *
   6019  *=============================================================================================*/
   6020 int HouseClass::AI_Unit(void)
   6021 {
   6022 	assert(Houses.ID(this) == ID);
   6023 
   6024 	if (BuildUnit != UNIT_NONE) return(TICKS_PER_SECOND);
   6025 	if (CurUnits >= Control.MaxUnit) return(TICKS_PER_SECOND);
   6026 
   6027 	/*
   6028 	**	A computer controlled house will try to build a replacement
   6029 	**	harvester if possible.
   6030 	*/
   6031 	if (IQ >= Rule.IQHarvester && !IsTiberiumShort && !IsHuman && BQuantity[STRUCT_REFINERY] > UQuantity[UNIT_HARVESTER] && Difficulty != DIFF_HARD) {
   6032 		if (UnitTypeClass::As_Reference(UNIT_HARVESTER).Level <= (unsigned)Control.TechLevel) {
   6033 			BuildUnit = UNIT_HARVESTER;
   6034 			return(TICKS_PER_SECOND);
   6035 		}
   6036 	}
   6037 
   6038 	if (Session.Type == GAME_NORMAL) {
   6039 
   6040 		int counter[UNIT_COUNT];
   6041 		memset(counter, 0x00, sizeof(counter));
   6042 
   6043 		/*
   6044 		**	Build a list of the maximum of each type we wish to produce. This will be
   6045 		**	twice the number required to fill all teams.
   6046 		*/
   6047 		int index;
   6048 		for (index = 0; index < Teams.Count(); index++) {
   6049 			TeamClass * tptr = Teams.Ptr(index);
   6050 			if (tptr != NULL) {
   6051 				TeamTypeClass const * team = tptr->Class;
   6052 				if (((team->IsReinforcable && !tptr->IsFullStrength) || (!tptr->IsForcedActive && !tptr->IsHasBeen && !tptr->JustAltered)) && team->House == Class->House) {
   6053 					for (int subindex = 0; subindex < team->ClassCount; subindex++) {
   6054 						TechnoTypeClass const * memtype = team->Members[subindex].Class;
   6055 						if (memtype->What_Am_I() == RTTI_UNITTYPE) {
   6056 							counter[((UnitTypeClass const *)memtype)->Type] = 1;
   6057 						}
   6058 					}
   6059 				}
   6060 			}
   6061 		}
   6062 
   6063 		/*
   6064 		**	Team types that are flagged as prebuilt, will always try to produce enough
   6065 		**	to fill one team of this type regardless of whether there is a team active
   6066 		**	of that type.
   6067 		*/
   6068 		for (index = 0; index < TeamTypes.Count(); index++) {
   6069 			TeamTypeClass const * team = TeamTypes.Ptr(index);
   6070 			if (team != NULL && team->House == Class->House && team->IsPrebuilt && (!team->IsAutocreate || IsAlerted)) {
   6071 				for (int subindex = 0; subindex < team->ClassCount; subindex++) {
   6072 					TechnoTypeClass const * memtype = team->Members[subindex].Class;
   6073 
   6074 					if (memtype->What_Am_I() == RTTI_UNITTYPE) {
   6075 						int subtype = ((UnitTypeClass const *)memtype)->Type;
   6076 						counter[subtype] = max(counter[subtype], team->Members[subindex].Quantity);
   6077 					}
   6078 				}
   6079 			}
   6080 		}
   6081 
   6082 		/*
   6083 		**	Reduce the theoretical maximum by the actual number of objects currently
   6084 		**	in play.
   6085 		*/
   6086 		for (int uindex = 0; uindex < Units.Count(); uindex++) {
   6087 			UnitClass * unit = Units.Ptr(uindex);
   6088 			if (unit != NULL && unit->Is_Recruitable(this) && counter[unit->Class->Type] > 0) {
   6089 				counter[unit->Class->Type]--;
   6090 			}
   6091 		}
   6092 
   6093 		/*
   6094 		**	Pick to build the most needed object but don't consider those objects that
   6095 		**	can't be built because of scenario restrictions or insufficient cash.
   6096 		*/
   6097 		int bestval = -1;
   6098 		int bestcount = 0;
   6099 		UnitType bestlist[UNIT_COUNT];
   6100 		for (UnitType utype = UNIT_FIRST; utype < UNIT_COUNT; utype++) {
   6101 			if (counter[utype] > 0 && Can_Build(&UnitTypeClass::As_Reference(utype), Class->House) && UnitTypeClass::As_Reference(utype).Cost_Of() <= Available_Money()) {
   6102 				if (bestval == -1 || bestval < counter[utype]) {
   6103 					bestval = counter[utype];
   6104 					bestcount = 0;
   6105 				}
   6106 				bestlist[bestcount++] = utype;
   6107 			}
   6108 		}
   6109 
   6110 		/*
   6111 		**	The unit type to build is now known. Fetch a pointer to the techno type class.
   6112 		*/
   6113 		if (bestcount) {
   6114 			BuildUnit = bestlist[Random_Pick(0, bestcount-1)];
   6115 		}
   6116 	}
   6117 
   6118 	if (IsBaseBuilding) {
   6119 
   6120 		int counter[UNIT_COUNT];
   6121 		int total = 0;
   6122 		UnitType index;
   6123 		for (index = UNIT_FIRST; index < UNIT_COUNT; index++) {
   6124 			UnitTypeClass const * utype = &UnitTypeClass::As_Reference(index);
   6125 			if (Can_Build(utype, ActLike) && utype->Type != UNIT_HARVESTER) {
   6126 				if (utype->PrimaryWeapon != NULL) {
   6127 					counter[index] = 20;
   6128 				} else {
   6129 					counter[index] = 1;
   6130 				}
   6131 			} else {
   6132 				counter[index] = 0;
   6133 			}
   6134 			total += counter[index];
   6135 		}
   6136 
   6137 		if (total > 0) {
   6138 			int choice = Random_Pick(0, total-1);
   6139 			for (index = UNIT_FIRST; index < UNIT_COUNT; index++) {
   6140 				if (choice < counter[index]) {
   6141 					BuildUnit = index;
   6142 					break;
   6143 				}
   6144 				choice -= counter[index];
   6145 			}
   6146 		}
   6147 	}
   6148 
   6149 	return(TICKS_PER_SECOND);
   6150 }
   6151 
   6152 
   6153 int HouseClass::AI_Vessel(void)
   6154 {
   6155 	assert(Houses.ID(this) == ID);
   6156 	if (BuildVessel != VESSEL_NONE) return(TICKS_PER_SECOND);
   6157 
   6158 	if (CurVessels >= Control.MaxVessel) {
   6159 		return(TICKS_PER_SECOND);
   6160 	}
   6161 
   6162 	if (Session.Type == GAME_NORMAL) {
   6163 
   6164 		int counter[VESSEL_COUNT];
   6165 		if (Session.Type == GAME_NORMAL) {
   6166 			memset(counter, 0x00, sizeof(counter));
   6167 		} else {
   6168 			for (VesselType index = VESSEL_FIRST; index < VESSEL_COUNT; index++) {
   6169 				if (Can_Build(&VesselTypeClass::As_Reference(index), Class->House) && VesselTypeClass::As_Reference(index).Level <= (unsigned)Control.TechLevel) {
   6170 					counter[index] = 16;
   6171 				} else {
   6172 					counter[index] = 0;
   6173 				}
   6174 			}
   6175 		}
   6176 
   6177 		/*
   6178 		**	Build a list of the maximum of each type we wish to produce. This will be
   6179 		**	twice the number required to fill all teams.
   6180 		*/
   6181 		int index;
   6182 		for (index = 0; index < Teams.Count(); index++) {
   6183 			TeamClass * tptr = Teams.Ptr(index);
   6184 			if (tptr) {
   6185 				TeamTypeClass const * team = tptr->Class;
   6186 
   6187 				if (((team->IsReinforcable && !tptr->IsFullStrength) || (!tptr->IsForcedActive && !tptr->IsHasBeen && !tptr->JustAltered)) && team->House == Class->House) {
   6188 					for (int subindex = 0; subindex < team->ClassCount; subindex++) {
   6189 						if (team->Members[subindex].Class->What_Am_I() == RTTI_VESSELTYPE) {
   6190 							counter[((VesselTypeClass const *)(team->Members[subindex].Class))->Type] = 1;
   6191 						}
   6192 					}
   6193 				}
   6194 			}
   6195 		}
   6196 
   6197 		/*
   6198 		**	Team types that are flagged as prebuilt, will always try to produce enough
   6199 		**	to fill one team of this type regardless of whether there is a team active
   6200 		**	of that type.
   6201 		*/
   6202 		for (index = 0; index < TeamTypes.Count(); index++) {
   6203 			TeamTypeClass const * team = TeamTypes.Ptr(index);
   6204 			if (team) {
   6205 				if (team->House == Class->House && team->IsPrebuilt && (!team->IsAutocreate || IsAlerted)) {
   6206 					for (int subindex = 0; subindex < team->ClassCount; subindex++) {
   6207 						if (team->Members[subindex].Class->What_Am_I() == RTTI_VESSELTYPE) {
   6208 							int subtype = ((VesselTypeClass const *)(team->Members[subindex].Class))->Type;
   6209 							counter[subtype] = max(counter[subtype], team->Members[subindex].Quantity);
   6210 						}
   6211 					}
   6212 				}
   6213 			}
   6214 		}
   6215 
   6216 		/*
   6217 		**	Reduce the theoretical maximum by the actual number of objects currently
   6218 		**	in play.
   6219 		*/
   6220 		for (int vindex = 0; vindex < Vessels.Count(); vindex++) {
   6221 			VesselClass * unit = Vessels.Ptr(vindex);
   6222 			if (unit != NULL && unit->Is_Recruitable(this) && counter[unit->Class->Type] > 0) {
   6223 				counter[unit->Class->Type]--;
   6224 			}
   6225 		}
   6226 
   6227 		/*
   6228 		**	Pick to build the most needed object but don't consider those object that
   6229 		**	can't be built because of scenario restrictions or insufficient cash.
   6230 		*/
   6231 		int bestval = -1;
   6232 		int bestcount = 0;
   6233 		VesselType bestlist[VESSEL_COUNT];
   6234 		for (VesselType utype = VESSEL_FIRST; utype < VESSEL_COUNT; utype++) {
   6235 			if (counter[utype] > 0 && Can_Build(&VesselTypeClass::As_Reference(utype), Class->House) && VesselTypeClass::As_Reference(utype).Cost_Of() <= Available_Money()) {
   6236 				if (bestval == -1 || bestval < counter[utype]) {
   6237 					bestval = counter[utype];
   6238 					bestcount = 0;
   6239 				}
   6240 				bestlist[bestcount++] = utype;
   6241 			}
   6242 		}
   6243 
   6244 		/*
   6245 		**	The unit type to build is now known. Fetch a pointer to the techno type class.
   6246 		*/
   6247 		if (bestcount) {
   6248 			BuildVessel = bestlist[Random_Pick(0, bestcount-1)];
   6249 		}
   6250 	}
   6251 
   6252 	if (IsBaseBuilding) {
   6253 		BuildVessel = VESSEL_NONE;
   6254 	}
   6255 
   6256 	return(TICKS_PER_SECOND);
   6257 }
   6258 
   6259 
   6260 
   6261 /***********************************************************************************************
   6262  * HouseClass::AI_Infantry -- Determines the infantry unit to build.                           *
   6263  *                                                                                             *
   6264  *    This routine handles the general case of determining what infantry unit to build         *
   6265  *    next.                                                                                    *
   6266  *                                                                                             *
   6267  * INPUT:   none                                                                               *
   6268  *                                                                                             *
   6269  * OUTPUT:  Returns with the number of game frames to delay before being called again.         *
   6270  *                                                                                             *
   6271  * WARNINGS:   none                                                                            *
   6272  *                                                                                             *
   6273  * HISTORY:                                                                                    *
   6274  *   09/29/1995 JLB : Created.                                                                 *
   6275  *=============================================================================================*/
   6276 int HouseClass::AI_Infantry(void)
   6277 {
   6278 	assert(Houses.ID(this) == ID);
   6279 
   6280 	if (BuildInfantry != INFANTRY_NONE) return(TICKS_PER_SECOND);
   6281 	if (CurInfantry >= Control.MaxInfantry) return(TICKS_PER_SECOND);
   6282 
   6283 	if (Session.Type == GAME_NORMAL) {
   6284 		TechnoTypeClass const * techno = 0;
   6285 		int counter[INFANTRY_COUNT];
   6286 		memset(counter, 0x00, sizeof(counter));
   6287 
   6288 		/*
   6289 		**	Build a list of the maximum of each type we wish to produce. This will be
   6290 		**	twice the number required to fill all teams.
   6291 		*/
   6292 		int index;
   6293 		for (index = 0; index < Teams.Count(); index++) {
   6294 			TeamClass * tptr = Teams.Ptr(index);
   6295 			if (tptr != NULL) {
   6296 				TeamTypeClass const * team = tptr->Class;
   6297 
   6298 				if (((team->IsReinforcable && !tptr->IsFullStrength) || (!tptr->IsForcedActive && !tptr->IsHasBeen && !tptr->JustAltered)) && team->House == Class->House) {
   6299 					for (int subindex = 0; subindex < team->ClassCount; subindex++) {
   6300 						if (team->Members[subindex].Class->What_Am_I() == RTTI_INFANTRYTYPE) {
   6301 							counter[((InfantryTypeClass const *)(team->Members[subindex].Class))->Type] += team->Members[subindex].Quantity + (team->IsReinforcable ? 1 : 0);
   6302 						}
   6303 					}
   6304 				}
   6305 			}
   6306 		}
   6307 
   6308 		/*
   6309 		**	Team types that are flagged as prebuilt, will always try to produce enough
   6310 		**	to fill one team of this type regardless of whether there is a team active
   6311 		**	of that type.
   6312 		*/
   6313 		for (index = 0; index < TeamTypes.Count(); index++) {
   6314 			TeamTypeClass const * team = TeamTypes.Ptr(index);
   6315 			if (team != NULL) {
   6316 				if (team->House == Class->House && team->IsPrebuilt && (!team->IsAutocreate || IsAlerted)) {
   6317 					for (int subindex = 0; subindex < team->ClassCount; subindex++) {
   6318 						if (team->Members[subindex].Class->What_Am_I() == RTTI_INFANTRYTYPE) {
   6319 							int subtype = ((InfantryTypeClass const *)(team->Members[subindex].Class))->Type;
   6320 //									counter[subtype] = 1;
   6321 							counter[subtype] = max(counter[subtype], team->Members[subindex].Quantity);
   6322 							counter[subtype] = min(counter[subtype], 5);
   6323 						}
   6324 					}
   6325 				}
   6326 			}
   6327 		}
   6328 
   6329 		/*
   6330 		**	Reduce the theoretical maximum by the actual number of objects currently
   6331 		**	in play.
   6332 		*/
   6333 		for (int uindex = 0; uindex < Infantry.Count(); uindex++) {
   6334 			InfantryClass * infantry = Infantry.Ptr(uindex);
   6335 			if (infantry != NULL && infantry->Is_Recruitable(this) && counter[infantry->Class->Type] > 0) {
   6336 				counter[infantry->Class->Type]--;
   6337 			}
   6338 		}
   6339 
   6340 		/*
   6341 		**	Pick to build the most needed object but don't consider those object that
   6342 		**	can't be built because of scenario restrictions or insufficient cash.
   6343 		*/
   6344 		int bestval = -1;
   6345 		int bestcount = 0;
   6346 		InfantryType bestlist[INFANTRY_COUNT];
   6347 		for (InfantryType utype = INFANTRY_FIRST; utype < INFANTRY_COUNT; utype++) {
   6348 
   6349 			if (utype != INFANTRY_DOG || !(IScan & INFANTRYF_DOG)) {
   6350 				if (counter[utype] > 0 && Can_Build(&InfantryTypeClass::As_Reference(utype), Class->House) && InfantryTypeClass::As_Reference(utype).Cost_Of() <= Available_Money()) {
   6351 					if (bestval == -1 || bestval < counter[utype]) {
   6352 						bestval = counter[utype];
   6353 						bestcount = 0;
   6354 					}
   6355 					bestlist[bestcount++] = utype;
   6356 				}
   6357 			}
   6358 		}
   6359 
   6360 		/*
   6361 		**	The infantry type to build is now known. Fetch a pointer to the techno type class.
   6362 		*/
   6363 		if (bestcount) {
   6364 			int pick = Random_Pick(0, bestcount-1);
   6365 			BuildInfantry = bestlist[pick];
   6366 		}
   6367 
   6368 	}
   6369 
   6370 	if (IsBaseBuilding) {
   6371 		HouseClass const * enemy = NULL;
   6372 		if (Enemy != HOUSE_NONE) {
   6373 			enemy = HouseClass::As_Pointer(Enemy);
   6374 		}
   6375 
   6376 		/*
   6377 		**	This structure is used to keep track of the list of infantry types that should be
   6378 		**	built. The infantry type and the value assigned to it is recorded.
   6379 		*/
   6380 		struct {
   6381 			InfantryType	Type;		// Infantry type.
   6382 			int				Value;	// Relative value assigned.
   6383 		} typetrack[INFANTRY_COUNT];
   6384 		int count = 0;
   6385 		int total = 0;
   6386 		for (InfantryType index = INFANTRY_FIRST; index < INFANTRY_COUNT; index++) {
   6387 			if (Can_Build(&InfantryTypeClass::As_Reference(index), ActLike) && InfantryTypeClass::As_Reference(index).Level <= (unsigned)Control.TechLevel) {
   6388 				typetrack[count].Value = 0;
   6389 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98 This looks like a potential bug. It is prob. for save game format compatibility.
   6390 				int clipindex = index;
   6391 				if (clipindex >= INFANTRY_RA_COUNT) clipindex -= INFANTRY_RA_COUNT;
   6392 				if ((enemy != NULL && enemy->IQuantity[clipindex] > IQuantity[clipindex]) || Available_Money() > Rule.InfantryReserve || CurInfantry < CurBuildings * Rule.InfantryBaseMult) {
   6393 #else
   6394 				if ((enemy != NULL && enemy->IQuantity[index] > IQuantity[index]) || Available_Money() > Rule.InfantryReserve || CurInfantry < CurBuildings * Rule.InfantryBaseMult) {
   6395 #endif
   6396 
   6397 					switch (index) {
   6398 						case INFANTRY_E1:
   6399 							typetrack[count].Value = 3;
   6400 							break;
   6401 
   6402 						case INFANTRY_E2:
   6403 							typetrack[count].Value = 5;
   6404 							break;
   6405 
   6406 						case INFANTRY_E3:
   6407 							typetrack[count].Value = 2;
   6408 							break;
   6409 
   6410 						case INFANTRY_E4:
   6411 							typetrack[count].Value = 5;
   6412 							break;
   6413 
   6414 						case INFANTRY_RENOVATOR:
   6415 							if (CurInfantry > 5) {
   6416 								typetrack[count].Value = 1 - max(IQuantity[index], 0);
   6417 							}
   6418 							break;
   6419 
   6420 						case INFANTRY_TANYA:
   6421 							typetrack[count].Value = 1 - max(IQuantity[index], 0);
   6422 							break;
   6423 
   6424 						default:
   6425 							typetrack[count].Value = 0;
   6426 							break;
   6427 					}
   6428 				}
   6429 
   6430 				if (typetrack[count].Value > 0) {
   6431 					typetrack[count].Type = index;
   6432 					total += typetrack[count].Value;
   6433 					count++;
   6434 				}
   6435 			}
   6436 		}
   6437 
   6438 		/*
   6439 		**	If there is at least one choice, then pick it. The object picked
   6440 		**	is influenced by the weight (value) assigned to it. This is accomplished
   6441 		**	by picking a number between 0 and the total weight value. The appropriate
   6442 		**	infantry object that matches the number picked is then selected to be built.
   6443 		*/
   6444 		if (count > 0) {
   6445 			int pick = Random_Pick(0, total-1);
   6446 			for (int index = 0; index < count; index++) {
   6447 				if (pick < typetrack[index].Value) {
   6448 					BuildInfantry = typetrack[index].Type;
   6449 					break;
   6450 				}
   6451 				pick -= typetrack[index].Value;
   6452 			}
   6453 		}
   6454 	}
   6455 	return(TICKS_PER_SECOND);
   6456 }
   6457 
   6458 
   6459 /***********************************************************************************************
   6460  * HouseClass::AI_Aircraft -- Determines what aircraft to build next.                          *
   6461  *                                                                                             *
   6462  *    This routine is used to determine the general case of what aircraft to build next.       *
   6463  *                                                                                             *
   6464  * INPUT:   none                                                                               *
   6465  *                                                                                             *
   6466  * OUTPUT:  Returns with the number of frame to delay before calling this routine again.       *
   6467  *                                                                                             *
   6468  * WARNINGS:   none                                                                            *
   6469  *                                                                                             *
   6470  * HISTORY:                                                                                    *
   6471  *   09/29/1995 JLB : Created.                                                                 *
   6472  *=============================================================================================*/
   6473 int HouseClass::AI_Aircraft(void)
   6474 {
   6475 	assert(Houses.ID(this) == ID);
   6476 
   6477 	if (!IsHuman && IQ >= Rule.IQAircraft) {
   6478 		if (BuildAircraft != AIRCRAFT_NONE) return(TICKS_PER_SECOND);
   6479 		if (CurAircraft >= Control.MaxAircraft) return(TICKS_PER_SECOND);
   6480 
   6481 		if (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_LONGBOW), ActLike) &&
   6482 				 AircraftTypeClass::As_Reference(AIRCRAFT_LONGBOW).Level <= (unsigned)Control.TechLevel &&
   6483 				 BQuantity[STRUCT_HELIPAD] > AQuantity[AIRCRAFT_LONGBOW] + AQuantity[AIRCRAFT_HIND]) {
   6484 			BuildAircraft = AIRCRAFT_LONGBOW;
   6485 			return(TICKS_PER_SECOND);
   6486 		}
   6487 
   6488 		if (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_HIND), ActLike) &&
   6489 				 AircraftTypeClass::As_Reference(AIRCRAFT_HIND).Level <= (unsigned)Control.TechLevel &&
   6490 				 BQuantity[STRUCT_HELIPAD] > AQuantity[AIRCRAFT_LONGBOW] + AQuantity[AIRCRAFT_HIND]) {
   6491 			BuildAircraft = AIRCRAFT_HIND;
   6492 			return(TICKS_PER_SECOND);
   6493 		}
   6494 
   6495 		if (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_MIG), ActLike) &&
   6496 				 AircraftTypeClass::As_Reference(AIRCRAFT_MIG).Level <= (unsigned)Control.TechLevel &&
   6497 				 BQuantity[STRUCT_AIRSTRIP] > AQuantity[AIRCRAFT_MIG] + AQuantity[AIRCRAFT_YAK]) {
   6498 			BuildAircraft = AIRCRAFT_MIG;
   6499 			return(TICKS_PER_SECOND);
   6500 		}
   6501 
   6502 		if (Can_Build(&AircraftTypeClass::As_Reference(AIRCRAFT_YAK), ActLike) &&
   6503 				 AircraftTypeClass::As_Reference(AIRCRAFT_YAK).Level <= (unsigned)Control.TechLevel &&
   6504 				 BQuantity[STRUCT_AIRSTRIP] > AQuantity[AIRCRAFT_MIG] + AQuantity[AIRCRAFT_YAK]) {
   6505 			BuildAircraft = AIRCRAFT_YAK;
   6506 			return(TICKS_PER_SECOND);
   6507 		}
   6508 	}
   6509 
   6510 	return(TICKS_PER_SECOND);
   6511 }
   6512 
   6513 
   6514 /***********************************************************************************************
   6515  * HouseClass::Production_Begun -- Records that production has begun.                          *
   6516  *                                                                                             *
   6517  *    This routine is used to inform the Expert System that production of the specified object *
   6518  *    has begun. This allows the AI to proceed with picking another object to begin production *
   6519  *    on.                                                                                      *
   6520  *                                                                                             *
   6521  * INPUT:   product  -- Pointer to the object that production has just begun on.               *
   6522  *                                                                                             *
   6523  * OUTPUT:  none                                                                               *
   6524  *                                                                                             *
   6525  * WARNINGS:   none                                                                            *
   6526  *                                                                                             *
   6527  * HISTORY:                                                                                    *
   6528  *   09/29/1995 JLB : Created.                                                                 *
   6529  *=============================================================================================*/
   6530 void HouseClass::Production_Begun(TechnoClass const * product)
   6531 {
   6532 	assert(Houses.ID(this) == ID);
   6533 
   6534 	if (product != NULL) {
   6535 		switch (product->What_Am_I()) {
   6536 			case RTTI_UNIT:
   6537 				if (*((UnitClass*)product) == BuildUnit) {
   6538 					BuildUnit = UNIT_NONE;
   6539 				}
   6540 				break;
   6541 
   6542 			case RTTI_VESSEL:
   6543 				if (*((VesselClass*)product) == BuildVessel) {
   6544 					BuildVessel = VESSEL_NONE;
   6545 				}
   6546 				break;
   6547 
   6548 			case RTTI_INFANTRY:
   6549 				if (*((InfantryClass*)product) == BuildInfantry) {
   6550 					BuildInfantry = INFANTRY_NONE;
   6551 				}
   6552 				break;
   6553 
   6554 			case RTTI_BUILDING:
   6555 				if (*((BuildingClass*)product) == BuildStructure) {
   6556 					BuildStructure = STRUCT_NONE;
   6557 				}
   6558 				break;
   6559 
   6560 			case RTTI_AIRCRAFT:
   6561 				if (*((AircraftClass*)product) == BuildAircraft) {
   6562 					BuildAircraft = AIRCRAFT_NONE;
   6563 				}
   6564 				break;
   6565 
   6566 			default:
   6567 				break;
   6568 		}
   6569 	}
   6570 }
   6571 
   6572 
   6573 /***********************************************************************************************
   6574  * HouseClass::Tracking_Remove -- Remove object from house tracking system.                    *
   6575  *                                                                                             *
   6576  *    This routine informs the Expert System that the specified object is no longer part of    *
   6577  *    this house's inventory. This occurs when the object is destroyed or captured.            *
   6578  *                                                                                             *
   6579  * INPUT:   techno   -- Pointer to the object to remove from the tracking systems of this      *
   6580  *                      house.                                                                 *
   6581  *                                                                                             *
   6582  * OUTPUT:  none                                                                               *
   6583  *                                                                                             *
   6584  * WARNINGS:   none                                                                            *
   6585  *                                                                                             *
   6586  * HISTORY:                                                                                    *
   6587  *   09/29/1995 JLB : Created.                                                                 *
   6588  *=============================================================================================*/
   6589 void HouseClass::Tracking_Remove(TechnoClass const * techno)
   6590 {
   6591 	assert(Houses.ID(this) == ID);
   6592 
   6593 	int type;
   6594 
   6595 	switch (techno->What_Am_I()) {
   6596 		case RTTI_BUILDING:
   6597 			CurBuildings--;
   6598 			BQuantity[((BuildingTypeClass const &)techno->Class_Of()).Type]--;
   6599 			break;
   6600 
   6601 		case RTTI_AIRCRAFT:
   6602 			CurAircraft--;
   6603 			AQuantity[((AircraftTypeClass const &)techno->Class_Of()).Type]--;
   6604 			break;
   6605 
   6606 		case RTTI_INFANTRY:
   6607 			CurInfantry--;
   6608 			if (!((InfantryClass *)techno)->IsTechnician) {
   6609 				type = ((InfantryTypeClass const &)techno->Class_Of()).Type;
   6610 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   6611 				if (type >= INFANTRY_RA_COUNT) type -= INFANTRY_RA_COUNT;
   6612 #endif
   6613 				IQuantity[type]--;
   6614 			}
   6615 			break;
   6616 
   6617 		case RTTI_UNIT:
   6618 			CurUnits--;
   6619 			type = ((UnitTypeClass const &)techno->Class_Of()).Type;
   6620 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   6621 			if (type >= UNIT_RA_COUNT) type -= UNIT_RA_COUNT;
   6622 #endif
   6623 			UQuantity[type]--;
   6624 			break;
   6625 
   6626 		case RTTI_VESSEL:
   6627 			CurVessels--;
   6628 			type = ((VesselTypeClass const &)techno->Class_Of()).Type;
   6629 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   6630 			if (type >= VESSEL_RA_COUNT) type -= VESSEL_RA_COUNT;
   6631 #endif
   6632 			VQuantity[type]--;
   6633 			break;
   6634 
   6635 		default:
   6636 			break;
   6637 	}
   6638 }
   6639 
   6640 
   6641 /***********************************************************************************************
   6642  * HouseClass::Tracking_Add -- Informs house of new inventory item.                            *
   6643  *                                                                                             *
   6644  *    This function is called when the specified object is now available as part of the house's*
   6645  *    inventory. This occurs when the object is newly produced and also when it is captured    *
   6646  *    by this house.                                                                           *
   6647  *                                                                                             *
   6648  * INPUT:   techno   -- Pointer to the object that is now part of the house inventory.         *
   6649  *                                                                                             *
   6650  * OUTPUT:  none                                                                               *
   6651  *                                                                                             *
   6652  * WARNINGS:   none                                                                            *
   6653  *                                                                                             *
   6654  * HISTORY:                                                                                    *
   6655  *   09/29/1995 JLB : Created.                                                                 *
   6656  *=============================================================================================*/
   6657 void HouseClass::Tracking_Add(TechnoClass const * techno)
   6658 {
   6659 	assert(Houses.ID(this) == ID);
   6660 
   6661 	StructType building;
   6662 	AircraftType aircraft;
   6663 	InfantryType infantry;
   6664 	UnitType unit;
   6665 	VesselType vessel;
   6666 	int quant;
   6667 
   6668 	switch (techno->What_Am_I()) {
   6669 		case RTTI_BUILDING:
   6670 			CurBuildings++;
   6671 			building = ((BuildingTypeClass const &)techno->Class_Of()).Type;
   6672 			BQuantity[building]++;
   6673 			BScan |= (1L << building);
   6674 			if (Session.Type == GAME_INTERNET) {
   6675 				BuildingTotals->Increment_Unit_Total(techno->Class_Of().ID);
   6676 			}
   6677 			break;
   6678 
   6679 		case RTTI_AIRCRAFT:
   6680 			CurAircraft++;
   6681 			aircraft = ((AircraftTypeClass const &)techno->Class_Of()).Type;
   6682 			AQuantity[aircraft]++;
   6683 			AScan |= (1L << aircraft);
   6684 			if (Session.Type == GAME_INTERNET) {
   6685 				AircraftTotals->Increment_Unit_Total(techno->Class_Of().ID);
   6686 			}
   6687 			break;
   6688 
   6689 		case RTTI_INFANTRY:
   6690 			CurInfantry++;
   6691 			infantry = ((InfantryTypeClass const &)techno->Class_Of()).Type;
   6692 			if (!((InfantryClass *)techno)->IsTechnician) {
   6693 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   6694 				quant = infantry;
   6695 				if (quant >= INFANTRY_RA_COUNT) quant -= INFANTRY_RA_COUNT;
   6696 				IQuantity[quant]++;
   6697 #else
   6698 				IQuantity[infantry]++;
   6699 #endif
   6700 				if (!((InfantryTypeClass const &)techno->Class_Of()).IsCivilian && Session.Type == GAME_INTERNET) {
   6701 					InfantryTotals->Increment_Unit_Total(techno->Class_Of().ID);
   6702 				}
   6703 				IScan |= (1L << infantry);
   6704 			}
   6705 			break;
   6706 
   6707 		case RTTI_UNIT:
   6708 			CurUnits++;
   6709 			unit = ((UnitTypeClass const &)techno->Class_Of()).Type;
   6710 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   6711 			quant = unit;
   6712 			if (quant >= UNIT_RA_COUNT) quant -= UNIT_RA_COUNT;
   6713 			UQuantity[quant]++;
   6714 #else
   6715 			UQuantity[unit]++;
   6716 #endif
   6717 			UScan |= (1L << unit);
   6718 			if (Session.Type == GAME_INTERNET) {
   6719 				UnitTotals->Increment_Unit_Total(techno->Class_Of().ID);
   6720 			}
   6721 			break;
   6722 
   6723 		case RTTI_VESSEL:
   6724 			CurVessels++;
   6725 			vessel = ((VesselTypeClass const &)techno->Class_Of()).Type;
   6726 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   6727 			quant = vessel;
   6728 			if (quant >= VESSEL_RA_COUNT) quant -= VESSEL_RA_COUNT;
   6729 			VQuantity[quant]++;
   6730 #else
   6731 			VQuantity[vessel]++;
   6732 #endif
   6733 			VScan |= (1L << vessel);
   6734 			if (Session.Type == GAME_INTERNET) {
   6735 				VesselTotals->Increment_Unit_Total(techno->Class_Of().ID);
   6736 			}
   6737 			break;
   6738 
   6739 		default:
   6740 			break;
   6741 	}
   6742 }
   6743 
   6744 
   6745 /***********************************************************************************************
   6746  * HouseClass::Factory_Counter -- Fetches a pointer to the factory counter value.              *
   6747  *                                                                                             *
   6748  *    Use this routine to fetch a pointer to the variable that holds the number of factories   *
   6749  *    that can produce the specified object type. This is a helper routine used when           *
   6750  *    examining the number of factories as well as adjusting their number.                     *
   6751  *                                                                                             *
   6752  * INPUT:   rtti  -- The RTTI of the object that could be produced.                            *
   6753  *                                                                                             *
   6754  * OUTPUT:  Returns with the number of factories owned by this house that could produce the    *
   6755  *          object of the type specified.                                                      *
   6756  *                                                                                             *
   6757  * WARNINGS:   none                                                                            *
   6758  *                                                                                             *
   6759  * HISTORY:                                                                                    *
   6760  *   07/30/1996 JLB : Created.                                                                 *
   6761  *=============================================================================================*/
   6762 int * HouseClass::Factory_Counter(RTTIType rtti)
   6763 {
   6764 	switch (rtti) {
   6765 		case RTTI_UNITTYPE:
   6766 		case RTTI_UNIT:
   6767 			return(&UnitFactories);
   6768 
   6769 		case RTTI_VESSELTYPE:
   6770 		case RTTI_VESSEL:
   6771 			return(&VesselFactories);
   6772 
   6773 		case RTTI_AIRCRAFTTYPE:
   6774 		case RTTI_AIRCRAFT:
   6775 			return(&AircraftFactories);
   6776 
   6777 		case RTTI_INFANTRYTYPE:
   6778 		case RTTI_INFANTRY:
   6779 			return(&InfantryFactories);
   6780 
   6781 		case RTTI_BUILDINGTYPE:
   6782 		case RTTI_BUILDING:
   6783 			return(&BuildingFactories);
   6784 
   6785 		default:
   6786 			break;
   6787 	}
   6788 	return(NULL);
   6789 }
   6790 
   6791 
   6792 /***********************************************************************************************
   6793  * HouseClass::Active_Remove -- Remove this object from active duty for this house.            *
   6794  *                                                                                             *
   6795  *    This routine will recognize the specified object as having been removed from active      *
   6796  *    duty.                                                                                    *
   6797  *                                                                                             *
   6798  * INPUT:   techno   -- Pointer to the object to remove from active duty.                      *
   6799  *                                                                                             *
   6800  * OUTPUT:  none                                                                               *
   6801  *                                                                                             *
   6802  * WARNINGS:   none                                                                            *
   6803  *                                                                                             *
   6804  * HISTORY:                                                                                    *
   6805  *   07/16/1996 JLB : Created.                                                                 *
   6806  *=============================================================================================*/
   6807 void HouseClass::Active_Remove(TechnoClass const * techno)
   6808 {
   6809 	if (techno == NULL) return;
   6810 
   6811 	if (techno->What_Am_I() == RTTI_BUILDING) {
   6812 		int * fptr = Factory_Counter(((BuildingClass *)techno)->Class->ToBuild);
   6813 		if (fptr != NULL) {
   6814 			*fptr = *fptr - 1;
   6815 		}
   6816 	}
   6817 }
   6818 
   6819 
   6820 /***********************************************************************************************
   6821  * HouseClass::Active_Add -- Add an object to active duty for this house.                      *
   6822  *                                                                                             *
   6823  *    This routine will recognize the specified object as having entered active duty. Any      *
   6824  *    abilities granted to the house by that object are now available.                         *
   6825  *                                                                                             *
   6826  * INPUT:   techno   -- Pointer to the object that is entering active duty.                    *
   6827  *                                                                                             *
   6828  * OUTPUT:  none                                                                               *
   6829  *                                                                                             *
   6830  * WARNINGS:   none                                                                            *
   6831  *                                                                                             *
   6832  * HISTORY:                                                                                    *
   6833  *   07/16/1996 JLB : Created.                                                                 *
   6834  *=============================================================================================*/
   6835 void HouseClass::Active_Add(TechnoClass const * techno)
   6836 {
   6837 	if (techno == NULL) return;
   6838 
   6839 	if (techno->What_Am_I() == RTTI_BUILDING) {
   6840 		int * fptr = Factory_Counter(((BuildingClass *)techno)->Class->ToBuild);
   6841 		if (fptr != NULL) {
   6842 			*fptr = *fptr + 1;
   6843 		}
   6844 	}
   6845 }
   6846 
   6847 
   6848 /***********************************************************************************************
   6849  * HouseClass::Which_Zone -- Determines what zone a coordinate lies in.                        *
   6850  *                                                                                             *
   6851  *    This routine will determine what zone the specified coordinate lies in with respect to   *
   6852  *    this house's base. A location that is too distant from the base, even though it might    *
   6853  *    be a building, is not considered part of the base and returns ZONE_NONE.                 *
   6854  *                                                                                             *
   6855  * INPUT:   coord -- The coordinate to examine.                                                *
   6856  *                                                                                             *
   6857  * OUTPUT:  Returns with the base zone that the specified coordinate lies in.                  *
   6858  *                                                                                             *
   6859  * WARNINGS:   none                                                                            *
   6860  *                                                                                             *
   6861  * HISTORY:                                                                                    *
   6862  *   10/02/1995 JLB : Created.                                                                 *
   6863  *=============================================================================================*/
   6864 ZoneType HouseClass::Which_Zone(COORDINATE coord) const
   6865 {
   6866 	assert(Houses.ID(this) == ID);
   6867 
   6868 	if (coord == 0) return(ZONE_NONE);
   6869 
   6870 	int distance = Distance(Center, coord);
   6871 	if (distance <= Radius) return(ZONE_CORE);
   6872 	if (distance > Radius*4) return(ZONE_NONE);
   6873 
   6874 	DirType facing = Direction(Center, coord);
   6875 	if (facing < DIR_NE || facing > DIR_NW) return(ZONE_NORTH);
   6876 	if (facing >= DIR_NE && facing < DIR_SE) return(ZONE_EAST);
   6877 	if (facing >= DIR_SE && facing < DIR_SW) return(ZONE_SOUTH);
   6878 	return(ZONE_WEST);
   6879 }
   6880 
   6881 
   6882 /***********************************************************************************************
   6883  * HouseClass::Which_Zone -- Determines which base zone the specified object lies in.          *
   6884  *                                                                                             *
   6885  *    Use this routine to determine what zone the specified object lies in.                    *
   6886  *                                                                                             *
   6887  * INPUT:   object   -- Pointer to the object that will be checked for zone occupation.        *
   6888  *                                                                                             *
   6889  * OUTPUT:  Returns with the base zone that the object lies in. For objects that are too       *
   6890  *          distant from the center of the base, ZONE_NONE is returned.                        *
   6891  *                                                                                             *
   6892  * WARNINGS:   none                                                                            *
   6893  *                                                                                             *
   6894  * HISTORY:                                                                                    *
   6895  *   10/02/1995 JLB : Created.                                                                 *
   6896  *=============================================================================================*/
   6897 ZoneType HouseClass::Which_Zone(ObjectClass const * object) const
   6898 {
   6899 	assert(Houses.ID(this) == ID);
   6900 
   6901 	if (!object) return(ZONE_NONE);
   6902 	return(Which_Zone(object->Center_Coord()));
   6903 }
   6904 
   6905 
   6906 /***********************************************************************************************
   6907  * HouseClass::Which_Zone -- Determines which base zone the specified cell lies in.            *
   6908  *                                                                                             *
   6909  *    This routine is used to determine what base zone the specified cell is in.               *
   6910  *                                                                                             *
   6911  * INPUT:   cell  -- The cell to examine.                                                      *
   6912  *                                                                                             *
   6913  * OUTPUT:  Returns the base zone that the cell lies in or ZONE_NONE if the cell is too far    *
   6914  *          away.                                                                              *
   6915  *                                                                                             *
   6916  * WARNINGS:   none                                                                            *
   6917  *                                                                                             *
   6918  * HISTORY:                                                                                    *
   6919  *   10/02/1995 JLB : Created.                                                                 *
   6920  *=============================================================================================*/
   6921 ZoneType HouseClass::Which_Zone(CELL cell) const
   6922 {
   6923 	assert(Houses.ID(this) == ID);
   6924 
   6925 	return(Which_Zone(Cell_Coord(cell)));
   6926 }
   6927 
   6928 
   6929 /***********************************************************************************************
   6930  * HouseClass::Recalc_Attributes -- Recalcs all houses existence bits.                         *
   6931  *                                                                                             *
   6932  *    This routine will go through all game objects and reset the existence bits for the       *
   6933  *    owning house. This method ensures that if the object exists, then the corresponding      *
   6934  *    existence bit is also set.                                                               *
   6935  *                                                                                             *
   6936  * INPUT:   none                                                                               *
   6937  *                                                                                             *
   6938  * OUTPUT:  none                                                                               *
   6939  *                                                                                             *
   6940  * WARNINGS:   none                                                                            *
   6941  *                                                                                             *
   6942  * HISTORY:                                                                                    *
   6943  *   10/02/1995 JLB : Created.                                                                 *
   6944  *=============================================================================================*/
   6945 void HouseClass::Recalc_Attributes(void)
   6946 {
   6947 	/*
   6948 	**	Clear out all tracking values that will be filled in by this
   6949 	**	routine. This allows the filling in process to not worry about
   6950 	**	old existing values.
   6951 	*/
   6952 	int index;
   6953 	for (index = 0; index < Houses.Count(); index++) {
   6954 		HouseClass * house = Houses.Ptr(index);
   6955 
   6956 		if (house != NULL) {
   6957 			house->BScan = 0;
   6958 			house->ActiveBScan = 0;
   6959 			house->IScan = 0;
   6960 			house->ActiveIScan = 0;
   6961 			house->UScan = 0;
   6962 			house->ActiveUScan = 0;
   6963 			house->AScan = 0;
   6964 			house->ActiveAScan = 0;
   6965 			house->VScan = 0;
   6966 			house->ActiveVScan = 0;
   6967 		}
   6968 	}
   6969 
   6970 	/*
   6971 	**	A second pass through the sentient objects is required so that the appropriate scan
   6972 	**	bits will be set for the owner house.
   6973 	*/
   6974 	for (index = 0; index < Units.Count(); index++) {
   6975 		UnitClass const * unit = Units.Ptr(index);
   6976 		unit->House->UScan |= (1L << unit->Class->Type);
   6977 		if (unit->IsLocked && (Session.Type != GAME_NORMAL || !unit->House->IsHuman || unit->IsDiscoveredByPlayer)) {
   6978 			if (!unit->IsInLimbo) {
   6979 				unit->House->ActiveUScan |= (1L << unit->Class->Type);
   6980 			}
   6981 		}
   6982 	}
   6983 	for (index = 0; index < Infantry.Count(); index++) {
   6984 		InfantryClass const * infantry = Infantry.Ptr(index);
   6985 		infantry->House->IScan |= (1L << infantry->Class->Type);
   6986 		if (infantry->IsLocked && (Session.Type != GAME_NORMAL || !infantry->House->IsHuman || infantry->IsDiscoveredByPlayer)) {
   6987 			if (!infantry->IsInLimbo) {
   6988 				infantry->House->ActiveIScan |= (1L << infantry->Class->Type);
   6989 				infantry->House->OldIScan |= (1L << infantry->Class->Type);
   6990 			}
   6991 		}
   6992 	}
   6993 	for (index = 0; index < Aircraft.Count(); index++) {
   6994 		AircraftClass const * aircraft = Aircraft.Ptr(index);
   6995 		aircraft->House->AScan |= (1L << aircraft->Class->Type);
   6996 		if (aircraft->IsLocked && (Session.Type != GAME_NORMAL || !aircraft->House->IsHuman || aircraft->IsDiscoveredByPlayer)) {
   6997 			if (!aircraft->IsInLimbo) {
   6998 				aircraft->House->ActiveAScan |= (1L << aircraft->Class->Type);
   6999 				aircraft->House->OldAScan |= (1L << aircraft->Class->Type);
   7000 			}
   7001 		}
   7002 	}
   7003 	for (index = 0; index < Buildings.Count(); index++) {
   7004 		BuildingClass const * building = Buildings.Ptr(index);
   7005 		if (building->Class->Type < 32) {
   7006 			building->House->BScan |= (1L << building->Class->Type);
   7007 			if (building->IsLocked && (Session.Type != GAME_NORMAL || !building->House->IsHuman || building->IsDiscoveredByPlayer)) {
   7008 				if (!building->IsInLimbo) {
   7009 					building->House->ActiveBScan |= (1L << building->Class->Type);
   7010 					building->House->OldBScan |= (1L << building->Class->Type);
   7011 				}
   7012 			}
   7013 		}
   7014 	}
   7015 	for (index = 0; index < Vessels.Count(); index++) {
   7016 		VesselClass const * vessel = Vessels.Ptr(index);
   7017 		vessel->House->VScan |= (1L << vessel->Class->Type);
   7018 		if (vessel->IsLocked && (Session.Type != GAME_NORMAL || !vessel->House->IsHuman || vessel->IsDiscoveredByPlayer)) {
   7019 			if (!vessel->IsInLimbo) {
   7020 				vessel->House->ActiveVScan |= (1L << vessel->Class->Type);
   7021 				vessel->House->OldVScan |= (1L << vessel->Class->Type);
   7022 			}
   7023 		}
   7024 	}
   7025 }
   7026 
   7027 
   7028 /***********************************************************************************************
   7029  * HouseClass::Zone_Cell -- Finds the cell closest to the center of the zone.                  *
   7030  *                                                                                             *
   7031  *    This routine is used to find the cell that is closest to the center point of the         *
   7032  *    zone specified. Typical use of this routine is for building and unit placement so that   *
   7033  *    they can "cover" the specified zone.                                                     *
   7034  *                                                                                             *
   7035  * INPUT:   zone  -- The zone that the center point is to be returned.                         *
   7036  *                                                                                             *
   7037  * OUTPUT:  Returns with the cell that is closest to the center point of the zone specified.   *
   7038  *                                                                                             *
   7039  * WARNINGS:   none                                                                            *
   7040  *                                                                                             *
   7041  * HISTORY:                                                                                    *
   7042  *   10/02/1995 JLB : Created.                                                                 *
   7043  *=============================================================================================*/
   7044 CELL HouseClass::Zone_Cell(ZoneType zone) const
   7045 {
   7046 	assert(Houses.ID(this) == ID);
   7047 
   7048 	switch (zone) {
   7049 		case ZONE_CORE:
   7050 			return(Coord_Cell(Center));
   7051 
   7052 		case ZONE_NORTH:
   7053 			return(Coord_Cell(Coord_Move(Center, DIR_N, Radius*3)));
   7054 
   7055 		case ZONE_EAST:
   7056 			return(Coord_Cell(Coord_Move(Center, DIR_E, Radius*3)));
   7057 
   7058 		case ZONE_WEST:
   7059 			return(Coord_Cell(Coord_Move(Center, DIR_W, Radius*3)));
   7060 
   7061 		case ZONE_SOUTH:
   7062 			return(Coord_Cell(Coord_Move(Center, DIR_S, Radius*3)));
   7063 
   7064 		default:
   7065 			break;
   7066 	}
   7067 	return(0);
   7068 }
   7069 
   7070 
   7071 /***********************************************************************************************
   7072  * HouseClass::Where_To_Go -- Determines where the object should go and wait.                  *
   7073  *                                                                                             *
   7074  *    This function is called for every new unit produced or delivered in order to determine   *
   7075  *    where the unit should "hang out" to await further orders. The best area for the          *
   7076  *    unit to loiter is returned as a cell location.                                           *
   7077  *                                                                                             *
   7078  * INPUT:   object   -- Pointer to the object that needs to know where to go.                  *
   7079  *                                                                                             *
   7080  * OUTPUT:  Returns with the cell that the unit should move to.                                *
   7081  *                                                                                             *
   7082  * WARNINGS:   none                                                                            *
   7083  *                                                                                             *
   7084  * HISTORY:                                                                                    *
   7085  *   10/02/1995 JLB : Created.                                                                 *
   7086  *   11/04/1996 JLB : Simplified to use helper functions                                       *
   7087  *=============================================================================================*/
   7088 CELL HouseClass::Where_To_Go(FootClass const * object) const
   7089 {
   7090 	assert(Houses.ID(this) == ID);
   7091 	assert(object != NULL);
   7092 
   7093 	ZoneType zone;			// The zone that the object should go to.
   7094 	if (object->Anti_Air() + object->Anti_Armor() + object->Anti_Infantry() == 0) {
   7095 		zone = ZONE_CORE;
   7096 	} else {
   7097 		zone = Random_Pick(ZONE_NORTH, ZONE_WEST);
   7098 	}
   7099 
   7100 	CELL cell = Random_Cell_In_Zone(zone);
   7101 	assert(cell != 0);
   7102 
   7103 	return(Map.Nearby_Location(cell, SPEED_TRACK, Map[cell].Zones[MZONE_NORMAL], MZONE_NORMAL));
   7104 }
   7105 
   7106 
   7107 /***********************************************************************************************
   7108  * HouseClass::Find_Juicy_Target -- Finds a suitable field target.                             *
   7109  *                                                                                             *
   7110  *    This routine is used to find targets out in the field and away from base defense.        *
   7111  *    Typical of this would be the attack helicopters and the roving attack bands of           *
   7112  *    hunter killers.                                                                          *
   7113  *                                                                                             *
   7114  * INPUT:   coord -- The coordinate of the attacker. Closer targets are given preference.      *
   7115  *                                                                                             *
   7116  * OUTPUT:  Returns with a suitable target to attack.                                          *
   7117  *                                                                                             *
   7118  * WARNINGS:   none                                                                            *
   7119  *                                                                                             *
   7120  * HISTORY:                                                                                    *
   7121  *   10/12/1995 JLB : Created.                                                                 *
   7122  *=============================================================================================*/
   7123 TARGET HouseClass::Find_Juicy_Target(COORDINATE coord) const
   7124 {
   7125 	assert(Houses.ID(this) == ID);
   7126 
   7127 	UnitClass * best = 0;
   7128 	int value = 0;
   7129 
   7130 	for (int index = 0; index < Units.Count(); index++) {
   7131 		UnitClass * unit = Units.Ptr(index);
   7132 
   7133 		if (unit && !unit->IsInLimbo && !Is_Ally(unit) && unit->House->Which_Zone(unit) == ZONE_NONE) {
   7134 			int val = Distance(coord, unit->Center_Coord());
   7135 
   7136 			if (unit->Anti_Air()) val *= 2;
   7137 
   7138 			if (*unit == UNIT_HARVESTER) val /= 2;
   7139 
   7140 			if (value == 0 || val < value) {
   7141 				value = val;
   7142 				best = unit;
   7143 			}
   7144 		}
   7145 	}
   7146 	if (best) {
   7147 		return(best->As_Target());
   7148 	}
   7149 	return(TARGET_NONE);
   7150 }
   7151 
   7152 
   7153 /***********************************************************************************************
   7154  * HouseClass::Get_Quantity -- Fetches the total number of aircraft of the specified type.     *
   7155  *                                                                                             *
   7156  *    Call this routine to fetch the total quantity of aircraft of the type specified that is  *
   7157  *    owned by this house.                                                                     *
   7158  *                                                                                             *
   7159  * INPUT:   aircraft -- The aircraft type to check the quantity of.                            *
   7160  *                                                                                             *
   7161  * OUTPUT:  Returns with the total quantity of all aircraft of that type that is owned by this *
   7162  *          house.                                                                             *
   7163  *                                                                                             *
   7164  * WARNINGS:   none                                                                            *
   7165  *                                                                                             *
   7166  * HISTORY:                                                                                    *
   7167  *   07/09/1996 JLB : Created.                                                                 *
   7168  *=============================================================================================*/
   7169 int  HouseClass::Get_Quantity(AircraftType aircraft)
   7170 {
   7171 	return(AQuantity[aircraft]);
   7172 }
   7173 
   7174 
   7175 /***********************************************************************************************
   7176  * HouseClass::Fetch_Factory -- Finds the factory associated with the object type specified.   *
   7177  *                                                                                             *
   7178  *    This is the counterpart to the Set_Factory function. It will return with a factory       *
   7179  *    pointer that is associated with the object type specified.                               *
   7180  *                                                                                             *
   7181  * INPUT:   rtti  -- The RTTI of the object type to find the factory for.                      *
   7182  *                                                                                             *
   7183  * OUTPUT:  Returns with a pointer to the factory (if present) that can manufacture the        *
   7184  *          object type specified.                                                             *
   7185  *                                                                                             *
   7186  * WARNINGS:   If this returns a non-NULL pointer, then the factory is probably already busy   *
   7187  *             producing another unit of that category.                                        *
   7188  *                                                                                             *
   7189  * HISTORY:                                                                                    *
   7190  *   07/09/1996 JLB : Created.                                                                 *
   7191  *=============================================================================================*/
   7192 FactoryClass * HouseClass::Fetch_Factory(RTTIType rtti) const
   7193 {
   7194 	int factory_index = -1;
   7195 
   7196 	switch (rtti) {
   7197 		case RTTI_INFANTRY:
   7198 		case RTTI_INFANTRYTYPE:
   7199 			factory_index = InfantryFactory;
   7200 			break;
   7201 
   7202 		case RTTI_UNIT:
   7203 		case RTTI_UNITTYPE:
   7204 			factory_index = UnitFactory;
   7205 			break;
   7206 
   7207 		case RTTI_BUILDING:
   7208 		case RTTI_BUILDINGTYPE:
   7209 			factory_index = BuildingFactory;
   7210 			break;
   7211 
   7212 		case RTTI_AIRCRAFT:
   7213 		case RTTI_AIRCRAFTTYPE:
   7214 			factory_index = AircraftFactory;
   7215 			break;
   7216 
   7217 		case RTTI_VESSEL:
   7218 		case RTTI_VESSELTYPE:
   7219 			factory_index = VesselFactory;
   7220 			break;
   7221 
   7222 		default:
   7223 			factory_index = -1;
   7224 			break;
   7225 	}
   7226 
   7227 	/*
   7228 	**	Fetch the actual pointer to the factory object. If there is
   7229 	**	no object factory that matches the specified rtti type, then
   7230 	**	null is returned.
   7231 	*/
   7232 	if (factory_index != -1) {
   7233 		return(Factories.Raw_Ptr(factory_index));
   7234 	}
   7235 	return(NULL);
   7236 }
   7237 
   7238 
   7239 /***********************************************************************************************
   7240  * HouseClass::Set_Factory -- Assign specified factory to house tracking.                      *
   7241  *                                                                                             *
   7242  *    Call this routine when a factory has been created and it now must be passed on to the    *
   7243  *    house for tracking purposes. The house maintains several factory pointers and this       *
   7244  *    routine will ensure that the factory pointer gets stored correctly.                      *
   7245  *                                                                                             *
   7246  * INPUT:   rtti  -- The RTTI of the object the factory it to manufacture.                     *
   7247  *                                                                                             *
   7248  *          factory  -- The factory object pointer.                                            *
   7249  *                                                                                             *
   7250  * OUTPUT:  none                                                                               *
   7251  *                                                                                             *
   7252  * WARNINGS:   none                                                                            *
   7253  *                                                                                             *
   7254  * HISTORY:                                                                                    *
   7255  *   07/09/1996 JLB : Created.                                                                 *
   7256  *=============================================================================================*/
   7257 void HouseClass::Set_Factory(RTTIType rtti, FactoryClass * factory)
   7258 {
   7259 	int * factory_index = 0;
   7260 
   7261 	assert(rtti != RTTI_NONE);
   7262 
   7263 	switch (rtti) {
   7264 		case RTTI_UNIT:
   7265 		case RTTI_UNITTYPE:
   7266 			factory_index = &UnitFactory;
   7267 			break;
   7268 
   7269 		case RTTI_INFANTRY:
   7270 		case RTTI_INFANTRYTYPE:
   7271 			factory_index = &InfantryFactory;
   7272 			break;
   7273 
   7274 		case RTTI_VESSEL:
   7275 		case RTTI_VESSELTYPE:
   7276 			factory_index = &VesselFactory;
   7277 			break;
   7278 
   7279 		case RTTI_BUILDING:
   7280 		case RTTI_BUILDINGTYPE:
   7281 			factory_index = &BuildingFactory;
   7282 			break;
   7283 
   7284 		case RTTI_AIRCRAFT:
   7285 		case RTTI_AIRCRAFTTYPE:
   7286 			factory_index = &AircraftFactory;
   7287 			break;
   7288 	}
   7289 
   7290 	assert(factory_index != NULL);
   7291 
   7292 	/*
   7293 	**	Assign the factory to the appropriate slot. For the case of clearing
   7294 	**	the factory out, then -1 is assigned.
   7295 	*/
   7296 	if (factory != NULL) {
   7297 		*factory_index = factory->ID;
   7298 	} else {
   7299 		*factory_index = -1;
   7300 	}
   7301 }
   7302 
   7303 
   7304 /***********************************************************************************************
   7305  * HouseClass::Factory_Count -- Fetches the number of factories for specified type.            *
   7306  *                                                                                             *
   7307  *    This routine will count the number of factories owned by this house that can build       *
   7308  *    objects of the specified type.                                                           *
   7309  *                                                                                             *
   7310  * INPUT:   rtti  -- The type of object (RTTI) that the factories are to be counted for.       *
   7311  *                                                                                             *
   7312  * OUTPUT:  Returns with the number of factories that can build the object type specified.     *
   7313  *                                                                                             *
   7314  * WARNINGS:   none                                                                            *
   7315  *                                                                                             *
   7316  * HISTORY:                                                                                    *
   7317  *   07/30/1996 JLB : Created.                                                                 *
   7318  *=============================================================================================*/
   7319 int HouseClass::Factory_Count(RTTIType rtti) const
   7320 {
   7321 	int const * ptr = ((HouseClass *)this)->Factory_Counter(rtti);
   7322 	if (ptr != NULL) {
   7323 		return(*ptr);
   7324 	}
   7325 	return(0);
   7326 }
   7327 
   7328 
   7329 /***********************************************************************************************
   7330  * HouseClass::Get_Quantity -- Gets the quantity of the building type specified.               *
   7331  *                                                                                             *
   7332  *    This will return the total number of buildings of that type owned by this house.         *
   7333  *                                                                                             *
   7334  * INPUT:   building -- The building type to check.                                            *
   7335  *                                                                                             *
   7336  * OUTPUT:  Returns with the number of buildings of that type owned by this house.             *
   7337  *                                                                                             *
   7338  * WARNINGS:   none                                                                            *
   7339  *                                                                                             *
   7340  * HISTORY:                                                                                    *
   7341  *   07/09/1996 JLB : Created.                                                                 *
   7342  *=============================================================================================*/
   7343 int  HouseClass::Get_Quantity(StructType building)
   7344 {
   7345 	return(BQuantity[building]);
   7346 }
   7347 
   7348 
   7349 /***********************************************************************************************
   7350  * HouseClass::Read_INI -- Reads house specific data from INI.                                 *
   7351  *                                                                                             *
   7352  *    This routine reads the house specific data for a particular                              *
   7353  *    scenario from the scenario INI file. Typical data includes starting                      *
   7354  *    credits, maximum unit count, etc.                                                        *
   7355  *                                                                                             *
   7356  * INPUT:   buffer   -- Pointer to loaded scenario INI file.                                   *
   7357  *                                                                                             *
   7358  * OUTPUT:  none                                                                               *
   7359  *                                                                                             *
   7360  * WARNINGS:   none                                                                            *
   7361  *                                                                                             *
   7362  * HISTORY:                                                                                    *
   7363  *   05/24/1994 JLB : Created.                                                                 *
   7364  *   05/18/1995 JLB : Creates all houses.                                                      *
   7365  *=============================================================================================*/
   7366 void HouseClass::Read_INI(CCINIClass & ini)
   7367 {
   7368 	HouseClass 	* p;				// Pointer to current player data.
   7369 	char const	* hname;			//	Pointer to house name.
   7370 
   7371 	for (HousesType index = HOUSE_FIRST; index < HOUSE_COUNT; index++) {
   7372 		hname = HouseTypeClass::As_Reference(index).IniName;
   7373 
   7374 		p = new HouseClass(index);
   7375 		p->Control.TechLevel = ini.Get_Int(hname, "TechLevel", Scen.Scenario);
   7376 		p->Control.MaxBuilding = ini.Get_Int(hname, "MaxBuilding", p->Control.MaxBuilding);
   7377 		p->Control.MaxUnit = ini.Get_Int(hname, "MaxUnit", p->Control.MaxUnit);
   7378 		p->Control.MaxInfantry = ini.Get_Int(hname, "MaxInfantry", p->Control.MaxInfantry);
   7379 		p->Control.MaxVessel = ini.Get_Int(hname, "MaxVessel", p->Control.MaxVessel);
   7380 		if (p->Control.MaxVessel == 0) p->Control.MaxVessel = p->Control.MaxUnit;
   7381 		p->Control.InitialCredits = ini.Get_Int(hname, "Credits", 0) * 100;
   7382 		p->Credits = p->Control.InitialCredits;
   7383 
   7384 		int iq = ini.Get_Int(hname, "IQ", 0);
   7385 		if (iq > Rule.MaxIQ) iq = 1;
   7386 		p->IQ = p->Control.IQ = iq;
   7387 
   7388 		p->Control.Edge = ini.Get_SourceType(hname, "Edge", SOURCE_NORTH);
   7389 		p->IsPlayerControl = ini.Get_Bool(hname, "PlayerControl", false);
   7390 
   7391 		int owners = ini.Get_Owners(hname, "Allies", (1 << HOUSE_NEUTRAL));
   7392 		p->Make_Ally(index);
   7393 		p->Make_Ally(HOUSE_NEUTRAL);
   7394 		for (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {
   7395 			if ((owners & (1 << h)) != 0) {
   7396 				p->Make_Ally(h);
   7397 			}
   7398 		}
   7399 	}
   7400 }
   7401 
   7402 
   7403 /***********************************************************************************************
   7404  * HouseClass::Write_INI -- Writes the house data to the INI database.                         *
   7405  *                                                                                             *
   7406  *    This routine will write out all data necessary to recreate it in anticipation of a       *
   7407  *    new scenario. All houses (that are active) will have their scenario type data written    *
   7408  *    out.                                                                                     *
   7409  *                                                                                             *
   7410  * INPUT:   ini   -- Reference to the INI database to write the data to.                       *
   7411  *                                                                                             *
   7412  * OUTPUT:  none                                                                               *
   7413  *                                                                                             *
   7414  * WARNINGS:   none                                                                            *
   7415  *                                                                                             *
   7416  * HISTORY:                                                                                    *
   7417  *   07/09/1996 JLB : Created.                                                                 *
   7418  *=============================================================================================*/
   7419 void HouseClass::Write_INI(CCINIClass & ini)
   7420 {
   7421 	/*
   7422 	**	The identity house control object. Only if the house value differs from the
   7423 	**	identity, will the data be written out.
   7424 	*/
   7425 	HouseStaticClass control;
   7426 
   7427 	for (HousesType i = HOUSE_FIRST; i < HOUSE_COUNT; i++) {
   7428 		HouseClass * p = As_Pointer(i);
   7429 
   7430 		if (p != NULL) {
   7431 			char const * name = p->Class->IniName;
   7432 
   7433 			ini.Clear(name);
   7434 			if (i >= HOUSE_MULTI1) continue;
   7435 
   7436 			if (p->Control.InitialCredits != control.InitialCredits) {
   7437 				ini.Put_Int(name, "Credits", (int)(p->Control.InitialCredits / 100));
   7438 			}
   7439 
   7440 			if (p->Control.Edge != control.Edge) {
   7441 				ini.Put_SourceType(name, "Edge", p->Control.Edge);
   7442 			}
   7443 
   7444 			if (p->Control.MaxUnit > 0 && p->Control.MaxUnit != control.MaxUnit) {
   7445 				ini.Put_Int(name, "MaxUnit", p->Control.MaxUnit);
   7446 			}
   7447 
   7448 			if (p->Control.MaxInfantry > 0 && p->Control.MaxInfantry != control.MaxInfantry) {
   7449 				ini.Put_Int(name, "MaxInfantry", p->Control.MaxInfantry);
   7450 			}
   7451 
   7452 			if (p->Control.MaxBuilding > 0 && p->Control.MaxBuilding != control.MaxBuilding) {
   7453 				ini.Put_Int(name, "MaxBuilding", p->Control.MaxBuilding);
   7454 			}
   7455 
   7456 			if (p->Control.MaxVessel > 0 && p->Control.MaxVessel != control.MaxVessel) {
   7457 				ini.Put_Int(name, "MaxVessel", p->Control.MaxVessel);
   7458 			}
   7459 
   7460 			if (p->Control.TechLevel != control.TechLevel) {
   7461 				ini.Put_Int(name, "TechLevel", p->Control.TechLevel);
   7462 			}
   7463 
   7464 			if (p->Control.IQ != control.IQ) {
   7465 				ini.Put_Int(name, "IQ", p->Control.IQ);
   7466 			}
   7467 
   7468 			if (p->IsPlayerControl != false && p != PlayerPtr) {
   7469 				ini.Put_Bool(name, "PlayerControl", p->IsPlayerControl);
   7470 			}
   7471 
   7472 			ini.Put_Owners(name, "Allies", p->Control.Allies & ~((1 << p->Class->House) | (1 << HOUSE_NEUTRAL)));
   7473 		}
   7474 	}
   7475 }
   7476 
   7477 
   7478 /***********************************************************************************************
   7479  * HouseClass::Is_No_YakMig -- Determines if no more yaks or migs should be allowed.           *
   7480  *                                                                                             *
   7481  *    This routine will examine the current yak and mig situation verses airfields. If there   *
   7482  *    are equal aircraft to airfields, then this routine will return TRUE.                     *
   7483  *                                                                                             *
   7484  * INPUT:   none                                                                               *
   7485  *                                                                                             *
   7486  * OUTPUT:  bool; Are all airfields full and thus no more yaks or migs are allowed?            *
   7487  *                                                                                             *
   7488  * WARNINGS:   none                                                                            *
   7489  *                                                                                             *
   7490  * HISTORY:                                                                                    *
   7491  *   09/23/1996 JLB : Created.                                                                 *
   7492  *=============================================================================================*/
   7493 bool HouseClass::Is_No_YakMig(void) const
   7494 {
   7495 	int quantity = AQuantity[AIRCRAFT_YAK] + AQuantity[AIRCRAFT_MIG];
   7496 
   7497 	/*
   7498 	**	Adjust the quantity down one if there is an aircraft in production. This will
   7499 	**	allow production to resume after being held.
   7500 	*/
   7501 	FactoryClass const * factory = Fetch_Factory(RTTI_AIRCRAFT);
   7502 	if (factory != NULL && factory->Get_Object() != NULL) {
   7503 		AircraftClass const * air = (AircraftClass const *)factory->Get_Object();
   7504 		if (*air == AIRCRAFT_MIG || *air == AIRCRAFT_YAK) {
   7505 			quantity -= 1;
   7506 		}
   7507 	}
   7508 
   7509 	if (quantity >= BQuantity[STRUCT_AIRSTRIP]) {
   7510 		return(true);
   7511 	}
   7512 	return(false);
   7513 }
   7514 
   7515 
   7516 /***********************************************************************************************
   7517  * HouseClass::Is_Hack_Prevented -- Is production of the specified type and id prohibted?      *
   7518  *                                                                                             *
   7519  *    This is a special hack check routine to see if the object type and id specified is       *
   7520  *    prevented from being produced. The Yak and the Mig are so prevented if there would be    *
   7521  *    insufficient airfields for them to land upon.                                            *
   7522  *                                                                                             *
   7523  * INPUT:   rtti  -- The RTTI type of the value specified.                                     *
   7524  *                                                                                             *
   7525  *          value -- The type number (according to the RTTI type specified).                   *
   7526  *                                                                                             *
   7527  * OUTPUT:  bool; Is production of this object prohibited?                                     *
   7528  *                                                                                             *
   7529  * WARNINGS:   none                                                                            *
   7530  *                                                                                             *
   7531  * HISTORY:                                                                                    *
   7532  *   09/23/1996 JLB : Created.                                                                 *
   7533  *=============================================================================================*/
   7534 bool HouseClass::Is_Hack_Prevented(RTTIType rtti, int value) const
   7535 {
   7536 	if (rtti == RTTI_AIRCRAFTTYPE && (value == AIRCRAFT_MIG || value == AIRCRAFT_YAK)) {
   7537 		return(Is_No_YakMig());
   7538 	}
   7539 	return(false);
   7540 }
   7541 
   7542 
   7543 /***********************************************************************************************
   7544  * HouseClass::Fire_Sale -- Cause all buildings to be sold.                                    *
   7545  *                                                                                             *
   7546  *    This routine will sell back all buildings owned by this house.                           *
   7547  *                                                                                             *
   7548  * INPUT:   none                                                                               *
   7549  *                                                                                             *
   7550  * OUTPUT:  bool; Was a fire sale performed?                                                   *
   7551  *                                                                                             *
   7552  * WARNINGS:   none                                                                            *
   7553  *                                                                                             *
   7554  * HISTORY:                                                                                    *
   7555  *   09/23/1996 JLB : Created.                                                                 *
   7556  *=============================================================================================*/
   7557 bool HouseClass::Fire_Sale(void)
   7558 {
   7559 	if (CurBuildings > 0) {
   7560 		for (int index = 0; index < Buildings.Count(); index++) {
   7561 			BuildingClass * b = Buildings.Ptr(index);
   7562 
   7563 			if (b != NULL && !b->IsInLimbo && b->House == this && b->Strength > 0) {
   7564 				b->Sell_Back(1);
   7565 			}
   7566 		}
   7567 		return(true);
   7568 	}
   7569 	return(false);
   7570 }
   7571 
   7572 
   7573 /***********************************************************************************************
   7574  * HouseClass::Do_All_To_Hunt -- Send all units to hunt.                                       *
   7575  *                                                                                             *
   7576  *    This routine will cause all combatants of this house to go into hunt mode. The effect of *
   7577  *    this is to throw everything this house has to muster at the enemies of this house.       *
   7578  *                                                                                             *
   7579  * INPUT:   none                                                                               *
   7580  *                                                                                             *
   7581  * OUTPUT:  none                                                                               *
   7582  *                                                                                             *
   7583  * WARNINGS:   none                                                                            *
   7584  *                                                                                             *
   7585  * HISTORY:                                                                                    *
   7586  *   09/23/1996 JLB : Created.                                                                 *
   7587  *   10/02/1996 JLB : Handles aircraft too.                                                    *
   7588  *=============================================================================================*/
   7589 void HouseClass::Do_All_To_Hunt(void) const
   7590 {
   7591 	int index;
   7592 
   7593 	for (index = 0; index < Units.Count(); index++) {
   7594 		UnitClass * unit = Units.Ptr(index);
   7595 
   7596 		if (unit->House == this && unit->IsDown && !unit->IsInLimbo) {
   7597 			if (unit->Team) unit->Team->Remove(unit);
   7598 			unit->Assign_Mission(MISSION_HUNT);
   7599 		}
   7600 	}
   7601 
   7602 	for (index = 0; index < Infantry.Count(); index++) {
   7603 		InfantryClass * infantry = Infantry.Ptr(index);
   7604 
   7605 		if (infantry->House == this && infantry->IsDown && !infantry->IsInLimbo) {
   7606 			if (infantry->Team) infantry->Team->Remove(infantry);
   7607 			infantry->Assign_Mission(MISSION_HUNT);
   7608 		}
   7609 	}
   7610 
   7611 	for (index = 0; index < Vessels.Count(); index++) {
   7612 		VesselClass * vessel = Vessels.Ptr(index);
   7613 
   7614 		if (vessel->House == this && vessel->IsDown && !vessel->IsInLimbo) {
   7615 			if (vessel->Team) vessel->Team->Remove(vessel);
   7616 			vessel->Assign_Mission(MISSION_HUNT);
   7617 		}
   7618 	}
   7619 
   7620 	for (index = 0; index < Aircraft.Count(); index++) {
   7621 		AircraftClass * aircraft = Aircraft.Ptr(index);
   7622 
   7623 		if (aircraft->House == this && aircraft->IsDown && !aircraft->IsInLimbo) {
   7624 			if (aircraft->Team) aircraft->Team->Remove(aircraft);
   7625 			aircraft->Assign_Mission(MISSION_HUNT);
   7626 		}
   7627 	}
   7628 }
   7629 
   7630 
   7631 /***********************************************************************************************
   7632  * HouseClass::Is_Allowed_To_Ally -- Determines if this house is allied to make allies.        *
   7633  *                                                                                             *
   7634  *    Use this routine to determine if this house is legally allowed to ally with the          *
   7635  *    house specified. There are many reason why an alliance is not allowed. Typically, this   *
   7636  *    is when there would be no more opponents left to fight or if this house has been         *
   7637  *    defeated.                                                                                *
   7638  *                                                                                             *
   7639  * INPUT:   house -- The house that alliance with is desired.                                  *
   7640  *                                                                                             *
   7641  * OUTPUT:  bool; Is alliance with the house specified prohibited?                             *
   7642  *                                                                                             *
   7643  * WARNINGS:   none                                                                            *
   7644  *                                                                                             *
   7645  * HISTORY:                                                                                    *
   7646  *   09/23/1996 JLB : Created.                                                                 *
   7647  *=============================================================================================*/
   7648 bool HouseClass::Is_Allowed_To_Ally(HousesType house) const
   7649 {
   7650 	/*
   7651 	**	Is not allowed to ally with a house that is patently invalid, such
   7652 	**	as one that is illegally defined.
   7653 	*/
   7654 	if (house == HOUSE_NONE) {
   7655 		return(false);
   7656 	}
   7657 
   7658 	/*
   7659 	**	One cannot ally twice with the same house.
   7660 	*/
   7661 	if (Is_Ally(house)) {
   7662 		return(false);
   7663 	}
   7664 
   7665 	/*
   7666 	**	If the scenario is being set up, then alliances are always
   7667 	**	allowed. No further checking is required.
   7668 	*/
   7669 	if (ScenarioInit) {
   7670 		return(true);
   7671 	}
   7672 
   7673 	/*
   7674 	**	Alliances (outside of scneario init time) are allowed only if
   7675 	**	this is a multiplayer game. Otherwise, they are prohibited.
   7676 	*/
   7677 	if (Session.Type == GAME_NORMAL) {
   7678 		return(false);
   7679 	}
   7680 
   7681 	/*
   7682 	**	When the house is defeated, it can no longer make alliances.
   7683 	*/
   7684 	if (IsDefeated) {
   7685 		return(false);
   7686 	}
   7687 
   7688 #ifdef FIXIT_VERSION_3
   7689 	// Fix to prevent ally with computer.
   7690 	if ( !HouseClass::As_Pointer(house)->IsHuman) {
   7691 		return(false);
   7692 	}
   7693 #else	//	FIXIT_VERSION_3
   7694 #ifdef FIXIT_NO_COMP_ALLY
   7695 	// Fix to prevent ally with computer.
   7696 	if (PlayingAgainstVersion > VERSION_RED_ALERT_104 && !HouseClass::As_Pointer(house)->IsHuman) {
   7697 		return(false);
   7698 	}
   7699 #endif
   7700 #endif	//	FIXIT_VERSION_3
   7701 
   7702 	/*
   7703 	**	Count the number of active houses in the game as well as the
   7704 	**	number of existing allies with this house.
   7705 	*/
   7706 	int housecount = 0;
   7707 	int allycount = 0;
   7708 	for (HousesType house2 = HOUSE_MULTI1; house2 < HOUSE_COUNT; house2++) {
   7709 		HouseClass * hptr = HouseClass::As_Pointer(house2);
   7710 		if (hptr != NULL && hptr->IsActive && !hptr->IsDefeated) {
   7711 			housecount++;
   7712 			if (Is_Ally(hptr)) {
   7713 				allycount++;
   7714 			}
   7715 		}
   7716 	}
   7717 
   7718 	/*
   7719 	**	Alliance is not allowed if there wouldn't be any enemies left to
   7720 	**	fight.
   7721 	*/
   7722 	if (housecount == allycount+1) {
   7723 		return(false);
   7724 	}
   7725 
   7726 	return(true);
   7727 }
   7728 
   7729 
   7730 /***********************************************************************************************
   7731  * HouseClass::Computer_Paranoid -- Cause the computer players to becom paranoid.              *
   7732  *                                                                                             *
   7733  *    This routine will cause the computer players to become suspicious of the human           *
   7734  *    players and thus the computer players will band together in order to defeat the          *
   7735  *    human players.                                                                           *
   7736  *                                                                                             *
   7737  * INPUT:   none                                                                               *
   7738  *                                                                                             *
   7739  * OUTPUT:  none                                                                               *
   7740  *                                                                                             *
   7741  * WARNINGS:   none                                                                            *
   7742  *                                                                                             *
   7743  * HISTORY:                                                                                    *
   7744  *   09/23/1996 JLB : Created.                                                                 *
   7745  *=============================================================================================*/
   7746 void HouseClass::Computer_Paranoid(void)
   7747 {
   7748 	if (Session.Type != GAME_GLYPHX_MULTIPLAYER) {		// Re-enable this for multiplayer if we support classic team/ally mode. ST - 10/29/2019
   7749 	
   7750 		/*
   7751 		**	Loop through every computer controlled house and make allies with all other computer
   7752 		**	controlled houses and then make enemies with all other human controlled houses.
   7753 		*/
   7754 		for (HousesType house = HOUSE_MULTI1; house < HOUSE_COUNT; house++) {
   7755 			HouseClass * hptr = HouseClass::As_Pointer(house);
   7756 			if (hptr != NULL && hptr->IsActive && !hptr->IsDefeated && !hptr->IsHuman) {
   7757 				hptr->IsParanoid = true;
   7758 
   7759 				/*
   7760 				**	Break alliance with every human it is allied with and make friends with
   7761 				**	any other computer players.
   7762 				*/
   7763 				for (HousesType house2 = HOUSE_MULTI1; house2 < HOUSE_COUNT; house2++) {
   7764 					HouseClass * hptr2 = HouseClass::As_Pointer(house2);
   7765 					if (hptr2 != NULL && hptr2->IsActive && !hptr2->IsDefeated) {
   7766 						if (hptr2->IsHuman) {
   7767 							hptr->Make_Enemy(house2);
   7768 						} else {
   7769 							hptr->Make_Ally(house2);
   7770 						}
   7771 					}
   7772 				}
   7773 			}
   7774 		}
   7775 	}
   7776 }
   7777 
   7778 
   7779 /***********************************************************************************************
   7780  * HouseClass::Adjust_Power -- Adjust the power value of the house.                            *
   7781  *                                                                                             *
   7782  *    This routine will update the power output value of the house. It will cause any buildgins*
   7783  *    that need to be redrawn to do so.                                                        *
   7784  *                                                                                             *
   7785  * INPUT:   adjust   -- The amount to adjust the power output value.                           *
   7786  *                                                                                             *
   7787  * OUTPUT:  none                                                                               *
   7788  *                                                                                             *
   7789  * WARNINGS:   none                                                                            *
   7790  *                                                                                             *
   7791  * HISTORY:                                                                                    *
   7792  *   11/01/1996 BWG : Created.                                                                 *
   7793  *=============================================================================================*/
   7794 void HouseClass::Adjust_Power(int adjust)
   7795 {
   7796 	Power += adjust;
   7797 
   7798 	Update_Spied_Power_Plants();
   7799 }
   7800 
   7801 
   7802 /***********************************************************************************************
   7803  * HouseClass::Adjust_Drain -- Adjust the power drain value of the house.                      *
   7804  *                                                                                             *
   7805  *    This routine will update the drain value of the house. It will cause any buildings that  *
   7806  *    need to be redraw to do so.                                                              *
   7807  *                                                                                             *
   7808  * INPUT:   adjust   -- The amount to adjust the drain (positive means more drain).            *
   7809  *                                                                                             *
   7810  * OUTPUT:  none                                                                               *
   7811  *                                                                                             *
   7812  * WARNINGS:   none                                                                            *
   7813  *                                                                                             *
   7814  * HISTORY:                                                                                    *
   7815  *   11/01/1996 BWG : Created.                                                                 *
   7816  *=============================================================================================*/
   7817 void HouseClass::Adjust_Drain(int adjust)
   7818 {
   7819 	Drain += adjust;
   7820 	Update_Spied_Power_Plants();
   7821 }
   7822 
   7823 
   7824 /***********************************************************************************************
   7825  * HouseClass::Update_Spied_Power_Plants -- Redraw power graphs on spied-upon power plants.    *
   7826  *                                                                                             *
   7827  * INPUT:   none                                                                               *
   7828  *                                                                                             *
   7829  * OUTPUT:  none                                                                               *
   7830  *                                                                                             *
   7831  * WARNINGS:   none                                                                            *
   7832  *                                                                                             *
   7833  * HISTORY:                                                                                    *
   7834  *   10/11/1996 BWG : Created.                                                                 *
   7835  *=============================================================================================*/
   7836 void HouseClass::Update_Spied_Power_Plants(void)
   7837 {
   7838 	int count = CurrentObject.Count();
   7839 	if (count) {
   7840 		for (int index = 0; index < count; index++) {
   7841 			ObjectClass const * tech = CurrentObject[index];
   7842 			if (tech && tech->What_Am_I()==RTTI_BUILDING) {
   7843 				BuildingClass *bldg = (BuildingClass *)tech;
   7844 				if (!bldg->IsOwnedByPlayer && *bldg == STRUCT_POWER || *bldg == STRUCT_ADVANCED_POWER) {
   7845 					if ( bldg->Spied_By() & (1<<(PlayerPtr->Class->House)) ) {
   7846 						bldg->Mark(MARK_CHANGE);
   7847 					}
   7848 				}
   7849 			}
   7850 		}
   7851 	}
   7852 }
   7853 
   7854 
   7855 /***********************************************************************************************
   7856  * HouseClass::Find_Cell_In_Zone -- Finds a legal placement cell within the zone.              *
   7857  *                                                                                             *
   7858  *    Use this routine to determine where the specified object should go if it were to go      *
   7859  *    some random (but legal) location within the zone specified.                              *
   7860  *                                                                                             *
   7861  * INPUT:   techno   -- The object that is desirous of going into the zone specified.          *
   7862  *                                                                                             *
   7863  *          zone     -- The zone to find a location within.                                    *
   7864  *                                                                                             *
   7865  * OUTPUT:  Returns with the cell that the specified object could be placed in the zone. If    *
   7866  *          no valid location could be found, then 0 is returned.                              *
   7867  *                                                                                             *
   7868  * WARNINGS:   none                                                                            *
   7869  *                                                                                             *
   7870  * HISTORY:                                                                                    *
   7871  *   11/01/1996 JLB : Created.                                                                 *
   7872  *   11/04/1996 JLB : Not so strict on zone requirement.                                       *
   7873  *=============================================================================================*/
   7874 CELL HouseClass::Find_Cell_In_Zone(TechnoClass const * techno, ZoneType zone) const
   7875 {
   7876 	if (techno == NULL) return(0);
   7877 
   7878 	int bestval = -1;
   7879 	int bestcell = 0;
   7880 	TechnoTypeClass const * ttype = techno->Techno_Type_Class();
   7881 
   7882 	/*
   7883 	**	Pick a random location within the zone specified.
   7884 	*/
   7885 	CELL trycell = Random_Cell_In_Zone(zone);
   7886 
   7887 	short const * list = NULL;
   7888 	if (techno->What_Am_I() == RTTI_BUILDING) {
   7889 		list = techno->Occupy_List(true);
   7890 	}
   7891 
   7892 	/*
   7893 	**	Find a legal placement position as close as possible to the picked location while still
   7894 	**	remaining within the zone.
   7895 	*/
   7896 	for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
   7897 //		if (Map.In_Radar(cell)) {
   7898 		if (Map.In_Radar(cell) && Which_Zone(cell) != ZONE_NONE) {
   7899 			bool ok = ttype->Legal_Placement(cell);
   7900 
   7901 			/*
   7902 			**	Another (adjacency) check is required for buildings.
   7903 			*/
   7904 			if (ok && list != NULL && !Map.Passes_Proximity_Check(ttype, techno->House->Class->House, list, cell)) {
   7905 				ok = false;
   7906 			}
   7907 
   7908 			if (ok) {
   7909 				int dist = Distance(Cell_Coord(cell), Cell_Coord(trycell));
   7910 				if (bestval == -1 || dist < bestval) {
   7911 					bestval = dist;
   7912 					bestcell = cell;
   7913 				}
   7914 			}
   7915 		}
   7916 	}
   7917 
   7918 	/*
   7919 	**	Return the best location to move to.
   7920 	*/
   7921 	return(bestcell);
   7922 }
   7923 
   7924 
   7925 /***********************************************************************************************
   7926  * HouseClass::Random_Cell_In_Zone -- Find a (technically) legal cell in the zone specified.   *
   7927  *                                                                                             *
   7928  *    This routine will pick a random cell within the zone specified. The pick will be         *
   7929  *    clipped to the map edge when necessary.                                                  *
   7930  *                                                                                             *
   7931  * INPUT:   zone  -- The zone to pick a cell from.                                             *
   7932  *                                                                                             *
   7933  * OUTPUT:  Returns with a picked cell within the zone. If the entire zone lies outside of the *
   7934  *          map, then a cell in the core zone is returned instead.                             *
   7935  *                                                                                             *
   7936  * WARNINGS:   none                                                                            *
   7937  *                                                                                             *
   7938  * HISTORY:                                                                                    *
   7939  *   11/04/1996 JLB : Created.                                                                 *
   7940  *=============================================================================================*/
   7941 CELL HouseClass::Random_Cell_In_Zone(ZoneType zone) const
   7942 {
   7943 	COORDINATE coord = 0;
   7944 	int maxdist = 0;
   7945 	switch (zone) {
   7946 		case ZONE_CORE:
   7947 			coord = Coord_Scatter(Center, Random_Pick(0, Radius), true);
   7948 			break;
   7949 
   7950 		case ZONE_NORTH:
   7951 			maxdist = min(Radius*3, (Coord_Y(Center) - Cell_To_Lepton(Map.MapCellY)) - CELL_LEPTON_H);
   7952 			if (maxdist < 0) break;
   7953 			coord = Coord_Move(Center, (DirType)(Random_Pick(DIR_N, DIR_E)-((DirType)32)), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));
   7954 			break;
   7955 
   7956 		case ZONE_EAST:
   7957 			maxdist = min(Radius*3, (Cell_To_Lepton(Map.MapCellX + Map.MapCellWidth) - Coord_X(Center)) - CELL_LEPTON_W);
   7958 			if (maxdist < 0) break;
   7959 			coord = Coord_Move(Center, Random_Pick(DIR_NE, DIR_SE), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));
   7960 			break;
   7961 
   7962 		case ZONE_SOUTH:
   7963 			maxdist = min(Radius*3, (Cell_To_Lepton(Map.MapCellY + Map.MapCellHeight) - Coord_Y(Center)) - CELL_LEPTON_H);
   7964 			if (maxdist < 0) break;
   7965 			coord = Coord_Move(Center, Random_Pick(DIR_SE, DIR_SW), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));
   7966 			break;
   7967 
   7968 		case ZONE_WEST:
   7969 			maxdist = min(Radius*3, (Coord_X(Center) - Cell_To_Lepton(Map.MapCellX)) - CELL_LEPTON_W);
   7970 			if (maxdist < 0) break;
   7971 			coord = Coord_Move(Center, Random_Pick(DIR_SW, DIR_NW), Random_Pick(min(Radius*2, maxdist), min(Radius*3, maxdist)));
   7972 			break;
   7973 	}
   7974 
   7975 	/*
   7976 	**	Double check that the location is valid and if so, convert it into a cell
   7977 	**	number.
   7978 	*/
   7979 	CELL cell;
   7980 	if (coord == 0 || !Map.In_Radar(Coord_Cell(coord))) {
   7981 		if (zone == ZONE_CORE) {
   7982 
   7983 			/*
   7984 			**	Finding a cell within the core failed, so just pick the center
   7985 			**	cell. This cell is guaranteed to be valid.
   7986 			*/
   7987 			cell = Coord_Cell(Center);
   7988 		} else {
   7989 
   7990 			/*
   7991 			**	If the edge fails, then try to find a cell within the core.
   7992 			*/
   7993 			cell = Random_Cell_In_Zone(ZONE_CORE);
   7994 		}
   7995 	} else {
   7996 		cell = Coord_Cell(coord);
   7997 	}
   7998 
   7999 	/*
   8000 	**	If the randomly picked location is not in the legal map area, then clip it to
   8001 	**	the legal map area.
   8002 	*/
   8003 	if (!Map.In_Radar(cell)) {
   8004 		int x = Cell_X(cell);
   8005 		int y = Cell_Y(cell);
   8006 
   8007 		if (x < Map.MapCellX) x = Map.MapCellX;
   8008 		if (y < Map.MapCellY) y = Map.MapCellY;
   8009 		if (x >= Map.MapCellX + Map.MapCellWidth) x = Map.MapCellX + Map.MapCellWidth -1;
   8010 		if (y >= Map.MapCellY + Map.MapCellHeight) y = Map.MapCellY + Map.MapCellHeight -1;
   8011 		cell = XY_Cell(x, y);
   8012 	}
   8013 	return(cell);
   8014 }
   8015 
   8016 /***********************************************************************************************
   8017  * HouseClass::Get_Ally_Flags --  Get the bit flags denoting the allies this house has.		  *
   8018  *                                                                                             *
   8019  * INPUT:   none																										  *
   8020  *                                                                                             *
   8021  * OUTPUT:  Returns the bit field storing which houses this house is allied with.              *
   8022  *                                                                                             *
   8023  * WARNINGS:   none                                                                            *
   8024  *                                                                                             *
   8025  * HISTORY:                                                                                    *
   8026  *   09/12/2019 JAS : Created.                                                                 *
   8027  *=============================================================================================*/
   8028 unsigned HouseClass::Get_Ally_Flags()
   8029 {
   8030 	return Allies;
   8031 }
   8032 
   8033 
   8034 
   8035 /***********************************************************************************************
   8036  * HouseClass::Check_Pertinent_Structures -- See if any useful structures remain               *
   8037  *                                                                                             *
   8038  * INPUT:   none                                                                               *
   8039  *                                                                                             *
   8040  * OUTPUT:  none                                                                               *
   8041  *                                                                                             *
   8042  * WARNINGS:   none                                                                            *
   8043  *                                                                                             *
   8044  * HISTORY:                                                                                    *
   8045  *   1/31/2020 3:34PM ST : Created.                                                            *
   8046  *=============================================================================================*/
   8047 void HouseClass::Check_Pertinent_Structures(void)
   8048 {
   8049 	/*
   8050 	** New default win mode to avoid griefing. ST - 1/31/2020 3:33PM
   8051 	**
   8052 	** Game is over when no pertinent structures remain
   8053 	*/
   8054 
   8055 	if (!Special.IsEarlyWin) {
   8056 		return;
   8057 	}
   8058 		  
   8059 	if (IsToDie || IsToWin || IsToLose) {
   8060 		return;
   8061 	}
   8062 
   8063 	// MBL 07.15.2020 - Prevention of recent issue with constant "player defeated logic" and message to client spamming
   8064 	// Per https://jaas.ea.com/browse/TDRA-7433
   8065 	//
   8066 	if (IsDefeated) {
   8067 		return;
   8068 	}
   8069 
   8070 	bool any_good_buildings = false;
   8071 	
   8072 	for (int index = 0; index < Buildings.Count(); index++) {
   8073 		BuildingClass *b = Buildings.Ptr(index);
   8074 
   8075 		if (b && b->IsActive && b->House == this) {
   8076 			if (!b->Class->IsWall && *b != STRUCT_APMINE && *b != STRUCT_AVMINE) {
   8077 				if (!Special.ModernBalance || (*b != STRUCT_SHIP_YARD && *b != STRUCT_FAKE_YARD && *b != STRUCT_SUB_PEN && *b != STRUCT_FAKE_PEN)) {
   8078 					if (!b->IsInLimbo && b->Strength > 0) {
   8079 						any_good_buildings = true;
   8080 						break;
   8081 					}
   8082 				}
   8083 			}
   8084 		}
   8085 	}
   8086 	
   8087 	if (!any_good_buildings) {
   8088 		for (int index = 0; index < Units.Count(); index++) {
   8089 			UnitClass * unit = Units.Ptr(index);
   8090 
   8091 			if (unit && unit->IsActive && *unit == UNIT_MCV && unit->House == this) {
   8092 				if (!unit->IsInLimbo && unit->Strength > 0) {
   8093 					any_good_buildings = true;
   8094 					break;
   8095 				}
   8096 			}
   8097 		}
   8098 	}
   8099 
   8100 	if (!any_good_buildings) {
   8101 		Flag_To_Die();
   8102 	}
   8103 }
   8104 
   8105 
   8106 
   8107 
   8108 
   8109 /***********************************************************************************************
   8110  * HouseClass::Init_Unit_Trackers -- Allocate the unit trackers for the house                  *
   8111  *                                                                                             *
   8112  * INPUT:   none                                                                               *
   8113  *                                                                                             *
   8114  * OUTPUT:  none                                                                               *
   8115  *                                                                                             *
   8116  * WARNINGS:   none                                                                            *
   8117  *                                                                                             *
   8118  * HISTORY:                                                                                    *
   8119  *   4/23/2020 11:06PM ST : Created.                                                           *
   8120  *=============================================================================================*/
   8121 void HouseClass::Init_Unit_Trackers(void)
   8122 {		
   8123 	if (Session.Type == GAME_INTERNET || Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   8124 		AircraftTotals = new UnitTrackerClass( (int) AIRCRAFT_COUNT);
   8125 		InfantryTotals = new UnitTrackerClass( (int) INFANTRY_COUNT);
   8126 		UnitTotals = new UnitTrackerClass ( (int) UNIT_COUNT);
   8127 		BuildingTotals = new UnitTrackerClass ( (int) STRUCT_COUNT);
   8128 		VesselTotals = new UnitTrackerClass ( (int) VESSEL_COUNT);
   8129 
   8130 		DestroyedAircraft = new UnitTrackerClass ( (int) AIRCRAFT_COUNT);
   8131 		DestroyedInfantry = new UnitTrackerClass( (int) INFANTRY_COUNT);
   8132 		DestroyedUnits = new UnitTrackerClass ( (int) UNIT_COUNT);
   8133 		DestroyedBuildings = new UnitTrackerClass ( (int) STRUCT_COUNT);
   8134 		DestroyedVessels = new UnitTrackerClass ( (int) VESSEL_COUNT);
   8135 
   8136 		CapturedBuildings = new UnitTrackerClass ( (int) STRUCT_COUNT);
   8137 		TotalCrates = new UnitTrackerClass ( CRATE_COUNT );
   8138 	} else {
   8139 		
   8140 		AircraftTotals = NULL;
   8141 		InfantryTotals = NULL;
   8142 		UnitTotals = NULL;
   8143 		BuildingTotals = NULL;
   8144 		VesselTotals = NULL;
   8145 
   8146 		DestroyedAircraft = NULL;
   8147 		DestroyedInfantry = NULL;
   8148 		DestroyedUnits = NULL;
   8149 		DestroyedBuildings = NULL;
   8150 		DestroyedVessels = NULL;
   8151 
   8152 		CapturedBuildings = NULL;
   8153 		TotalCrates = NULL;
   8154 	}	
   8155 }
   8156 
   8157 
   8158 
   8159 /***********************************************************************************************
   8160  * HouseClass::Free_Unit_Trackers -- Free the unit trackers for the house                      *
   8161  *                                                                                             *
   8162  * INPUT:   none                                                                               *
   8163  *                                                                                             *
   8164  * OUTPUT:  none                                                                               *
   8165  *                                                                                             *
   8166  * WARNINGS:   none                                                                            *
   8167  *                                                                                             *
   8168  * HISTORY:                                                                                    *
   8169  *   4/23/2020 11:06PM ST : Created.                                                           *
   8170  *=============================================================================================*/
   8171 void HouseClass::Free_Unit_Trackers(void)
   8172 {		
   8173 	if (AircraftTotals) {
   8174 		delete AircraftTotals;
   8175 		AircraftTotals = NULL;
   8176 	}
   8177 
   8178 	if (InfantryTotals) {
   8179 		delete InfantryTotals;
   8180 		InfantryTotals = NULL;
   8181 	}
   8182 
   8183 	if (UnitTotals) {
   8184 		delete UnitTotals;
   8185 		UnitTotals = NULL;
   8186 	}
   8187 
   8188 	if (BuildingTotals) {
   8189 		delete BuildingTotals;
   8190 		BuildingTotals = NULL;
   8191 	}
   8192 
   8193 	if (VesselTotals) {
   8194 		delete VesselTotals;
   8195 		VesselTotals = NULL;
   8196 	}
   8197 
   8198 	if (DestroyedAircraft) {
   8199 		delete DestroyedAircraft;
   8200 		DestroyedAircraft = NULL;
   8201 	}
   8202 
   8203 	if (DestroyedInfantry) {
   8204 		delete DestroyedInfantry;
   8205 		DestroyedInfantry = NULL;
   8206 	}
   8207 
   8208 	if (DestroyedUnits) {
   8209 		delete DestroyedUnits;
   8210 		DestroyedUnits = NULL;
   8211 	}
   8212 
   8213 	if (DestroyedBuildings) {
   8214 		delete DestroyedBuildings;
   8215 		DestroyedBuildings = NULL;
   8216 	}
   8217 
   8218 	if (DestroyedVessels) {
   8219 		delete DestroyedVessels;
   8220 		DestroyedVessels = NULL;
   8221 	}
   8222 
   8223 	if (CapturedBuildings) {
   8224 		delete CapturedBuildings;
   8225 		CapturedBuildings = NULL;
   8226 	}
   8227 
   8228 	if (TotalCrates) {
   8229 		delete TotalCrates;
   8230 		TotalCrates = NULL;
   8231 	}
   8232 }