CnC_Remastered_Collection

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

HOUSE.CPP (358314B)


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