void AddItemsInSectorToBox(void)
{
	CHAR16 wString[ 64 ];
	UINT32 hStringHandle = 0;

	// items in sector (this works even for underground)

	swprintf( wString, L"%s:", pwMiscSectorStrings[ 2 ] );
	AddMonoString( &hStringHandle, wString );

//	swprintf( wString, L"%d", GetSizeOfStashInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY, bCurrentTownMineSectorZ, FALSE ));
	swprintf( wString, L"%d", GetNumberOfVisibleWorldItemsFromSectorStructureForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY, bCurrentTownMineSectorZ ));
	AddSecondColumnMonoString( &hStringHandle, wString );
}
void AddSectorToBox(void)
{
	CHAR16 wString[ 64 ];
	CHAR16 wString2[ 10 ];
	UINT32 hStringHandle = 0;

	// sector
	swprintf( wString, L"%s:", pwMiscSectorStrings[ 1 ]);
	AddMonoString( &hStringHandle, wString );

	GetShortSectorString( bCurrentTownMineSectorX, bCurrentTownMineSectorY, wString );
	if (bCurrentTownMineSectorZ != 0 )
	{
		swprintf( wString2, L"-%d", bCurrentTownMineSectorZ );
		wcscat( wString, wString2 );
	}

	AddSecondColumnMonoString( &hStringHandle, wString );
}
void AddCommonInfoToBox(void)
{
	CHAR16 wString[ 64 ];
	UINT32 hStringHandle = 0;
	BOOLEAN fKnownSite = FALSE;
	UINT8 ubMilitiaTotal = 0;
	UINT8 ubNumEnemies;
	UINT16 usSectorValue = 0;

	// get the sector value
	usSectorValue = SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY );

	BOOLEAN fVisited = (SectorInfo[ usSectorValue ].uiFlags & SF_ALREADY_VISITED);
	UINT8 ubTownId = GetTownIdForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY );

	// visited sector check
	if ( fVisited )
		fKnownSite = TRUE;

	// known town check, to exclude non-town sectors
	else if( gfHiddenTown[ ubTownId ] && ubTownId != BLANK_SECTOR )
		fKnownSite = TRUE;
	
	// known SAM Site check
	else
	{
		for (UINT16 x=0; x < MAX_NUMBER_OF_SAMS; x++)
		{
			if ( pSamList[x] == usSectorValue )
			{
				if ( fSamSiteFound[ x ] )
					fKnownSite = TRUE;
			}
		}
	}
	
	/*// ABOVE GROUND HARDCODED
	fKnownSite = TRUE;
	switch( usSectorValue )
	{
		case SEC_D2: //Chitzena SAM
			if( !fSamSiteFound[ SAM_SITE_ONE ] )
				fKnownSite = FALSE;
			break;
		case SEC_D15: //Drassen SAM
			if( !fSamSiteFound[ SAM_SITE_TWO ] )
				fKnownSite = FALSE;
			break;
		case SEC_I8: //Cambria SAM
			if( !fSamSiteFound[ SAM_SITE_THREE ] )
				fKnownSite = FALSE;
			break;
		// SAM Site 4 in Meduna is within town limits, so it's always controllable
		default:
			break;
	}
	*/

	// in sector where militia can be trained,
	// control of the sector matters, display who controls this sector.	Map brightness no longer gives this!
	if ( MilitiaTrainingAllowedInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY, 0 ) && fKnownSite )
	{
		// controlled:
		swprintf( wString, L"%s:", pwMiscSectorStrings[ 4 ] );
		AddMonoString( &hStringHandle, wString );

		// No/Yes
		swprintf( wString, L"%s", pwMiscSectorStrings[ ( StrategicMap[ CALCULATE_STRATEGIC_INDEX( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ].fEnemyControlled ) ? 6 : 5 ] );
		AddSecondColumnMonoString( &hStringHandle, wString );


		// militia - is there any?
		swprintf( wString, L"%s:", pwTownInfoStrings[ 11 ] );
		AddMonoString( &hStringHandle, wString );

		ubMilitiaTotal = CountAllMilitiaInSector(bCurrentTownMineSectorX, bCurrentTownMineSectorY);
		if (ubMilitiaTotal > 0)
		{
			// some militia, show total & their breakdown by level
			swprintf( wString, L"%d (%d/%d/%d)", ubMilitiaTotal,
												MilitiaInSectorOfRank(bCurrentTownMineSectorX, bCurrentTownMineSectorY, GREEN_MILITIA),
												MilitiaInSectorOfRank(bCurrentTownMineSectorX, bCurrentTownMineSectorY, REGULAR_MILITIA),
												MilitiaInSectorOfRank(bCurrentTownMineSectorX, bCurrentTownMineSectorY, ELITE_MILITIA));
			AddSecondColumnMonoString( &hStringHandle, wString );
		}
		else
		{
			// no militia: don't bother displaying level breakdown
			wcscpy( wString, L"0");
			AddSecondColumnMonoString( &hStringHandle, wString );
		}

		// HEADROCK HAM 3.6: Only show these for sectors that have a training facility
		BOOLEAN fMilitiaTrainingAllowed = FALSE;
		BOOLEAN fMobileTrainingAllowed = FALSE;

		// percentage of current militia squad training completed
		swprintf( wString, L"%s:", pwTownInfoStrings[ 10 ] );
		AddMonoString( &hStringHandle, wString );

		// Sector contains Militia training facility?
		for (UINT8 ubCounter = 0; ubCounter < MAX_NUM_FACILITY_TYPES; ubCounter++)
		{
			if (gFacilityLocations[usSectorValue][ubCounter].fFacilityHere)
			{
				if (gFacilityTypes[ubCounter].ubMilitiaTrainersAllowed)
				{
					fMilitiaTrainingAllowed = TRUE;
				}
			}
		}
		if (fMilitiaTrainingAllowed)
		{
			// Show percent completed
			swprintf( wString, L"%d%%%%", SectorInfo[ usSectorValue ].ubMilitiaTrainingPercentDone );
			AddSecondColumnMonoString( &hStringHandle, wString );
		}
		else
		{
			// Show N/A
			AddSecondColumnMonoString( &hStringHandle, New113HAMMessage[19] );
		}

		// HEADROCK HAM 3.6: percentage of current Mobile Militia squad training completed
		swprintf( wString, L"%s:", pwTownInfoStrings[ 12 ] );
		AddMonoString( &hStringHandle, wString );

		// Sector contains Mobile training facility?
		for (UINT8 ubCounter = 0; ubCounter < MAX_NUM_FACILITY_TYPES; ubCounter++)
		{
			if (gFacilityLocations[usSectorValue][ubCounter].fFacilityHere)
			{
				if (gFacilityTypes[ubCounter].ubMobileMilitiaTrainersAllowed)
				{
					fMobileTrainingAllowed = TRUE;
				}
			}
		}

		if (fMobileTrainingAllowed)
		{
			// Show percentage completed
			swprintf( wString, L"%d%%%%", SectorInfo[ usSectorValue ].ubMobileMilitiaTrainingPercentDone );
			AddSecondColumnMonoString( &hStringHandle, wString );
		}
		else
		{
			// Show N/A
			AddSecondColumnMonoString( &hStringHandle, New113HAMMessage[19] );
		}
	}


	// enemy forces
	swprintf( wString, L"%s:", pwMiscSectorStrings[ 0 ] );
	AddMonoString( &hStringHandle, wString );

	// how many are there, really?
	ubNumEnemies = NumEnemiesInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY );
	AssertGE(gGameExternalOptions.ubGameMaximumNumberOfEnemies, NumFreeEnemySlots());
	unsigned numEnemiesOnMap = gGameExternalOptions.ubGameMaximumNumberOfEnemies - NumFreeEnemySlots();

	switch ( WhatPlayerKnowsAboutEnemiesInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) )
	{
		case KNOWS_NOTHING:
			// show "Unknown"
			wcscpy(wString, pwMiscSectorStrings[ 3 ] );
			break;

		// HEADROCK HAM 5: New Case
		case KNOWS_THEYRE_THERE:
		case KNOWS_THEYRE_THERE_AND_WHERE_GOING:
			// if there are any there
			if ( ubNumEnemies > 0 )
			{
				// show "?", but not exactly how many
				wcscpy(wString, L"?" );
			}
			else
			{
				// we know there aren't any (or we'd be seing them on map, too)
				wcscpy(wString, L"0" );
			}
			break;

		// HEADROCK HAM 5: New case
		case KNOWS_HOW_MANY:
		case KNOWS_HOW_MANY_AND_WHERE_GOING:
			// show exactly how many
			if (numEnemiesOnMap != ubNumEnemies)
				swprintf( wString, L"%d (%d)", numEnemiesOnMap, ubNumEnemies );
			else
				swprintf( wString, L"%d", ubNumEnemies );
			break;
	}

	AddSecondColumnMonoString( &hStringHandle, wString );
}
// adds text to mine info box
void AddTextToMineBox( void )
{
	UINT8 ubMineIndex;
	UINT8 ubTown;
	UINT32 hStringHandle;
	CHAR16 wString[ 64 ];


	ubMineIndex = GetMineIndexForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY );

	// name of town followed by "mine"
	//swprintf( wString, L"%s %s", pTownNames[ GetTownAssociatedWithMine( ubMineIndex ) ], pwMineStrings[ 0 ] );
	swprintf( wString, L"%s %s", pTownNames[ GetTownAssociatedWithMine( ubMineIndex ) ], MineralsName[gMineStatus[ubMineIndex].ubMineType].sType );
	AddMonoString( &hStringHandle, wString );

	// blank line
	AddMonoString( &hStringHandle, L"" );


	// sector
	AddSectorToBox();

	// mine status
	swprintf( wString, L"%s:", pwMineStrings[ 9 ]);
	AddMonoString( &hStringHandle, wString );

	// check if mine is empty (abandoned) or running out
	if (gMineStatus[ ubMineIndex ].fEmpty)
	{
		// abandonded
		wcscpy( wString, pwMineStrings[ 5 ] );
	}
	else
	if (gMineStatus[ ubMineIndex ].fShutDown)
	{
		// shut down
		wcscpy( wString, pwMineStrings[ 6 ] );
	}
	else
	if (gMineStatus[ ubMineIndex ].fRunningOut)
	{
		// running out
		wcscpy( wString, pwMineStrings[ 7 ] );
	}
	else
	{
		// producing
		wcscpy( wString, pwMineStrings[ 8 ] );
	}
	AddSecondColumnMonoString( &hStringHandle, wString );


	// if still producing
	if (!gMineStatus[ ubMineIndex ].fEmpty)
	{
		// current production
		swprintf( wString, L"%s:", pwMineStrings[ 3 ]);
		AddMonoString( &hStringHandle, wString );

		swprintf( wString, L"%d", PredictDailyIncomeFromAMine( ubMineIndex, TRUE ) );
		InsertCommasForDollarFigure( wString );
		InsertDollarSignInToString( wString );
		AddSecondColumnMonoString( &hStringHandle, wString );


		// potential production
		swprintf( wString, L"%s:", pwMineStrings[ 4 ]);
		AddMonoString( &hStringHandle, wString );

		swprintf( wString, L"%d", GetMaxDailyRemovalFromMine( ubMineIndex ) );
		InsertCommasForDollarFigure( wString );
		InsertDollarSignInToString( wString );
		AddSecondColumnMonoString( &hStringHandle, wString );


		// if potential is not nil
		if (GetMaxPeriodicRemovalFromMine(ubMineIndex) > 0)
		{
			// production rate (current production as a percentage of potential production)
			swprintf( wString, L"%s:", pwMineStrings[ 10 ]);
			AddMonoString( &hStringHandle, wString );
			swprintf( wString, L"%d%%%%", (PredictDailyIncomeFromAMine(ubMineIndex, TRUE) * 100 ) / GetMaxDailyRemovalFromMine(ubMineIndex) );
			AddSecondColumnMonoString( &hStringHandle, wString );
		}


		// town control percentage
		swprintf( wString, L"%s:", pwMineStrings[ 12 ]);
		AddMonoString( &hStringHandle, wString );
		//swprintf( wString, L"%d%%%%", (GetTownSectorsUnderControl( gMineLocation[ ubMineIndex ].bAssociatedTown ) *	100) / GetTownSectorSize( gMineLocation[ ubMineIndex ].bAssociatedTown ));
		swprintf( wString, L"%d%%%%", (GetTownSectorsUnderControl( gMineStatus[ ubMineIndex ].bAssociatedTown ) *	100) / GetTownSectorSize( gMineStatus[ ubMineIndex ].bAssociatedTown ));
		AddSecondColumnMonoString( &hStringHandle, wString );

		//ubTown = gMineLocation[ ubMineIndex ].bAssociatedTown;
		ubTown = gMineStatus[ ubMineIndex ].bAssociatedTown;
		if( gTownLoyalty[ ubTown ].fStarted && gfTownUsesLoyalty[ ubTown ])
		{
			// town loyalty percentage
			swprintf( wString, L"%s:", pwMineStrings[ 13 ]);
			AddMonoString( &hStringHandle, wString );
			//swprintf( wString, L"%d%%%%", gTownLoyalty[ gMineLocation[ ubMineIndex ].bAssociatedTown ].ubRating);
			swprintf( wString, L"%d%%%%", gTownLoyalty[ gMineStatus[ ubMineIndex ].bAssociatedTown ].ubRating);
			AddSecondColumnMonoString( &hStringHandle, wString );
		}

/* gradual monster infestation concept was ditched, now simply IN PRODUCTION or SHUT DOWN
		// percentage of miners working
		swprintf( wString, L"%s:", pwMineStrings[ 14 ]);
		AddMonoString( &hStringHandle, wString );
		swprintf( wString, L"%d%%%%", gubMonsterMineInfestation[ gMineStatus[ ubMineIndex ].bMonsters ]);
		AddSecondColumnMonoString( &hStringHandle, wString );
*/

		// ore type (silver/gold
		swprintf( wString, L"%s:", pwMineStrings[ 11 ]);
		AddMonoString( &hStringHandle, wString );
		AddSecondColumnMonoString( &hStringHandle, MineralsName[gMineStatus[ubMineIndex].ubMineType].sMinerals );
		//AddSecondColumnMonoString( &hStringHandle, (gMineStatus[ubMineIndex].ubMineType == SILVER_MINE) ? pwMineStrings[ 1 ] : pwMineStrings[ 2 ] );
	}


#ifdef _DEBUG
	// dollar amount remaining in mine
	wcscpy( wString, L"Remaining (DEBUG):");
	AddMonoString( &hStringHandle, wString );

	swprintf( wString, L"%d", GetTotalLeftInMine( ubMineIndex ) );
	InsertCommasForDollarFigure( wString );
	InsertDollarSignInToString( wString );
	AddSecondColumnMonoString( &hStringHandle, wString );
#endif

}
// adds text to town info box
void AddTextToTownBox( void )
{
	UINT32 hStringHandle = 0;
	CHAR16 wString[ 64 ];
	UINT8 ubTownId = 0;
	UINT16 usTownSectorIndex;
	INT16 sMineSector = 0;


	// remember town id
	ubTownId = GetTownIdForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY );
	Assert((ubTownId >= FIRST_TOWN) && (ubTownId < NUM_TOWNS));

	usTownSectorIndex = SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY );

	AssertGE(usTownSectorIndex, 0);
	AssertLT(usTownSectorIndex,256);

	////////////////////////////////////
	// HEADROCK HAM 5:
	// Read and verify XML sector names
	BOOLEAN fSectorHasXMLNames = TRUE;
	CHAR16 zUnexplored[MAX_SECTOR_NAME_LENGTH];
	CHAR16 zExplored[MAX_SECTOR_NAME_LENGTH];
	
	wcscpy( zUnexplored, gzSectorNames[ usTownSectorIndex ][0] );
	wcscpy( zExplored, gzSectorNames[ usTownSectorIndex ][2] );

	if (zUnexplored[0] == 0 || zExplored[0] == 0)
	{
		fSectorHasXMLNames = FALSE;
	}

	if (fSectorHasXMLNames) // ABOVE GROUND XML
	{
		// HEADROCK HAM 3.6: The program can now read custom names from XML for all above-ground sectors.
		// In the event that a specific name or set of names is missing, the program generates a default
		// name as it always has.
		// I've also updated the SAM Site sectors to rely on SamSite.XML data.
		
		BOOLEAN fVisited = (SectorInfo[ usTownSectorIndex ].uiFlags & SF_ALREADY_VISITED);
		BOOLEAN fSAMSiteKnown = FALSE;

		// Test for known SAM Site at this location
		for (UINT16 x=0; x < MAX_NUMBER_OF_SAMS; x++)
		{
			if ( pSamList[x] == usTownSectorIndex )
			{
				if ( fSamSiteFound[ x ] )
				{
					fSAMSiteKnown = TRUE;
				}
			}
		}

		if (fVisited || fSAMSiteKnown)
		{
			AddMonoString( &hStringHandle, zExplored );
		}
		else
		{
			AddMonoString( &hStringHandle, zUnexplored );
		}
	}
	else // ABOVE GROUND HARDCODED
	{
		switch( usTownSectorIndex )
		{
			case SEC_B13:
				AddMonoString( &hStringHandle, pLandTypeStrings[ DRASSEN_AIRPORT_SITE ] );
				break;
			case SEC_F8:
				AddMonoString( &hStringHandle, pLandTypeStrings[ CAMBRIA_HOSPITAL_SITE ] );
				break;
			case SEC_J9: //Tixa
				//if( !fFoundTixa )
				if( gfHiddenTown[ TIXA ] == FALSE )
					AddMonoString( &hStringHandle, pLandTypeStrings[ SAND ] );
				else
					AddMonoString( &hStringHandle, pTownNames[ TIXA ] );
				break;
			case SEC_K4: //Orta
				//if( !fFoundOrta )
				if( gfHiddenTown[ ORTA ] == FALSE )
					AddMonoString( &hStringHandle, pLandTypeStrings[ SWAMP ] );
				else
					AddMonoString( &hStringHandle, pTownNames[ ORTA ] );
				break;
			case SEC_N3:
				AddMonoString( &hStringHandle, pLandTypeStrings[ MEDUNA_AIRPORT_SITE ] );
				break;
			default:
				if( usTownSectorIndex == SEC_N4 && fSamSiteFound[ SAM_SITE_FOUR ] )
				{	//Meduna's SAM site
					AddMonoString( &hStringHandle, pLandTypeStrings[ MEDUNA_SAM_SITE ] );
				}
				else
				{ // town name
					swprintf( wString, L"%s", pTownNames[ ubTownId ] );
					AddMonoString( &hStringHandle, wString );
				}
				break;
		}
	}

	// blank line
	AddMonoString( &hStringHandle, L"" );

	// sector
	AddSectorToBox();

	// town size
	if( gfHiddenTown[ GetTownIdForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ] )
	{
	swprintf( wString, L"%s:", pwTownInfoStrings[ 0 ] );
	AddMonoString( &hStringHandle, wString );
	swprintf( wString, L"%d",	GetTownSectorSize( ubTownId ) );
	AddSecondColumnMonoString( &hStringHandle, wString );
	}

	// main facilities
	// HEADROCK HAM 3.6: This function now does all the work of assembling a facility entry.
	AddFacilitiesToBox( bCurrentTownMineSectorX, bCurrentTownMineSectorY, &hStringHandle, TRUE );

	// the concept of control is only meaningful in sectors where militia can be trained
	if ( MilitiaTrainingAllowedInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY, 0 ) &&
		gfHiddenTown[ GetTownIdForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ] )
	{
		// town control
		swprintf( wString, L"%s:", pwTownInfoStrings[ 2 ] );
		AddMonoString( &hStringHandle, wString );
		swprintf( wString, L"%d%%%%",	(GetTownSectorsUnderControl( ubTownId ) * 100) / GetTownSectorSize( ubTownId ));
		AddSecondColumnMonoString( &hStringHandle, wString );
	}

	// the concept of town loyalty is only meaningful in towns where loyalty is tracked
	if( gTownLoyalty[ ubTownId ].fStarted && gfTownUsesLoyalty[ ubTownId ] &&
		gfHiddenTown[ GetTownIdForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ] )
	{
		// town loyalty
		swprintf( wString, L"%s:", pwTownInfoStrings[ 5 ] );
		AddMonoString( &hStringHandle, wString );
		swprintf( wString, L"%d%%%%", gTownLoyalty[ ubTownId ].ubRating );
		AddSecondColumnMonoString( &hStringHandle, wString );
	}

	// if the town has a mine
	sMineSector = GetMineSectorForTown( ubTownId );
	if( sMineSector != -1 && gfHiddenTown[ GetTownIdForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ] )
	{
		// Associated Mine: Sector
	swprintf( wString, L"%s:",	pwTownInfoStrings[ 4 ] );
		AddMonoString( &hStringHandle, wString );
	GetShortSectorString( ( INT16 )( sMineSector % MAP_WORLD_X ), ( INT16 )( sMineSector / MAP_WORLD_X ), wString );
		AddSecondColumnMonoString( &hStringHandle, wString );
	}
}
void AddCommonInfoToBox(void)
{
	CHAR16 wString[ 64 ];
	UINT32 hStringHandle = 0;
	BOOLEAN fUnknownSAMSite = FALSE;
	UINT8 ubMilitiaTotal = 0;
	UINT8 ubNumEnemies;


	switch( SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) )
	{
		case SEC_D2: //Chitzena SAM
			if( !fSamSiteFound[ SAM_SITE_ONE ] )
				fUnknownSAMSite = TRUE;
			break;
		case SEC_D15: //Drassen SAM
			if( !fSamSiteFound[ SAM_SITE_TWO ] )
				fUnknownSAMSite = TRUE;
			break;
		case SEC_I8: //Cambria SAM
			if( !fSamSiteFound[ SAM_SITE_THREE ] )
				fUnknownSAMSite = TRUE;
			break;
		// SAM Site 4 in Meduna is within town limits, so it's always controllable
		default:
			break;
	}


	// in sector where militia can be trained,
	// control of the sector matters, display who controls this sector.  Map brightness no longer gives this!
	if ( MilitiaTrainingAllowedInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY, 0 ) && !fUnknownSAMSite )
	{
		// controlled:
		swprintf( wString, L"%s:", pwMiscSectorStrings[ 4 ] );
		AddMonoString( &hStringHandle, wString );

		// No/Yes
		swprintf( wString, L"%s", pwMiscSectorStrings[ ( StrategicMap[ CALCULATE_STRATEGIC_INDEX( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ].fEnemyControlled ) ? 6 : 5 ] );
		AddSecondColumnMonoString( &hStringHandle, wString );


		// militia - is there any?
		swprintf( wString, L"%s:", pwTownInfoStrings[ 11 ] );
		AddMonoString( &hStringHandle, wString );

		ubMilitiaTotal = CountAllMilitiaInSector(bCurrentTownMineSectorX, bCurrentTownMineSectorY);
		if (ubMilitiaTotal > 0)
		{
			// some militia, show total & their breakdown by level
	 		swprintf( wString, L"%d  (%d/%d/%d)", ubMilitiaTotal,
												MilitiaInSectorOfRank(bCurrentTownMineSectorX, bCurrentTownMineSectorY, GREEN_MILITIA),
												MilitiaInSectorOfRank(bCurrentTownMineSectorX, bCurrentTownMineSectorY, REGULAR_MILITIA),
												MilitiaInSectorOfRank(bCurrentTownMineSectorX, bCurrentTownMineSectorY, ELITE_MILITIA));
			AddSecondColumnMonoString( &hStringHandle, wString );
		}
		else
		{
			// no militia: don't bother displaying level breakdown
			wcscpy( wString, L"0");
			AddSecondColumnMonoString( &hStringHandle, wString );
		}


		// percentage of current militia squad training completed
		swprintf( wString, L"%s:", pwTownInfoStrings[ 10 ] );
		AddMonoString( &hStringHandle, wString );
		swprintf( wString, L"%d%%%%", SectorInfo[ SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ].ubMilitiaTrainingPercentDone );
		AddSecondColumnMonoString( &hStringHandle, wString );
	}


	// enemy forces
	swprintf( wString, L"%s:", pwMiscSectorStrings[ 0 ] );
	AddMonoString( &hStringHandle, wString );

	// how many are there, really?
	ubNumEnemies = NumEnemiesInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY );
	
	switch ( WhatPlayerKnowsAboutEnemiesInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) )
	{
		case KNOWS_NOTHING:
			// show "Unknown"
			wcscpy(wString, pwMiscSectorStrings[ 3 ] );
			break;

		case KNOWS_THEYRE_THERE:
			// if there are any there
			if ( ubNumEnemies > 0 )
			{
				// show "?", but not exactly how many
				wcscpy(wString, L"?" );
			}
			else
			{
				// we know there aren't any (or we'd be seing them on map, too)
				wcscpy(wString, L"0" );
			}
			break;

		case KNOWS_HOW_MANY:
			// show exactly how many
			swprintf( wString, L"%d", ubNumEnemies );
			break;
	}

	AddSecondColumnMonoString( &hStringHandle, wString );
}
// adds text to town info box
void AddTextToTownBox( void )
{
	UINT32 hStringHandle = 0;
	CHAR16 wString[ 64 ];
	UINT8 ubTownId = 0;
	UINT16 usTownSectorIndex;
	INT16 sMineSector = 0;


	// remember town id
	ubTownId = GetTownIdForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY );
	Assert((ubTownId >= FIRST_TOWN) && (ubTownId < NUM_TOWNS));

	usTownSectorIndex = SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY );

	switch( usTownSectorIndex )
	{
		case SEC_B13:
			AddMonoString( &hStringHandle, pLandTypeStrings[ DRASSEN_AIRPORT_SITE ] );
			break;
		case SEC_F8:
			AddMonoString( &hStringHandle, pLandTypeStrings[ CAMBRIA_HOSPITAL_SITE ] );
			break;
		case SEC_J9: //Tixa
			if( !fFoundTixa )
				AddMonoString( &hStringHandle, pLandTypeStrings[ SAND ] );
			else
				AddMonoString( &hStringHandle, pTownNames[ TIXA ] );
			break;
		case SEC_K4: //Orta
			if( !fFoundOrta )
				AddMonoString( &hStringHandle, pLandTypeStrings[ SWAMP ] );
			else
				AddMonoString( &hStringHandle, pTownNames[ ORTA ] );
			break;
		case SEC_N3:
			AddMonoString( &hStringHandle, pLandTypeStrings[ MEDUNA_AIRPORT_SITE ] );
			break;
		default:
			if( usTownSectorIndex == SEC_N4 && fSamSiteFound[ SAM_SITE_FOUR ] )
			{	//Meduna's SAM site
				AddMonoString( &hStringHandle, pLandTypeStrings[ MEDUNA_SAM_SITE ] );
			}
			else
			{ // town name
				swprintf( wString, L"%s", pTownNames[ ubTownId ] );
				AddMonoString( &hStringHandle, wString );
			}
			break;
	}
	// blank line
	AddMonoString( &hStringHandle, L"" );

	// sector
	AddSectorToBox();

	// town size
	swprintf( wString, L"%s:", pwTownInfoStrings[ 0 ] );
	AddMonoString( &hStringHandle, wString );
	swprintf( wString, L"%d",  GetTownSectorSize( ubTownId ) );
	AddSecondColumnMonoString( &hStringHandle, wString );

	// main facilities
	swprintf( wString, L"%s:", pwTownInfoStrings[ 8 ] );
	AddMonoString( &hStringHandle, wString );
	wcscpy(wString, L"");
	GetSectorFacilitiesFlags( bCurrentTownMineSectorX, bCurrentTownMineSectorY, wString );
	AddSecondColumnMonoString( &hStringHandle, wString );

	// the concept of control is only meaningful in sectors where militia can be trained
	if ( MilitiaTrainingAllowedInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY, 0 ) )
	{
		// town control
		swprintf( wString, L"%s:", pwTownInfoStrings[ 2 ] );
		AddMonoString( &hStringHandle, wString );
		swprintf( wString, L"%d%%%%",  (GetTownSectorsUnderControl( ubTownId ) * 100) / GetTownSectorSize( ubTownId ));
		AddSecondColumnMonoString( &hStringHandle, wString );
	}

	// the concept of town loyalty is only meaningful in towns where loyalty is tracked
	if( gTownLoyalty[ ubTownId ].fStarted && gfTownUsesLoyalty[ ubTownId ])
	{
		// town loyalty
		swprintf( wString, L"%s:", pwTownInfoStrings[ 5 ] );
		AddMonoString( &hStringHandle, wString );
		swprintf( wString, L"%d%%%%", gTownLoyalty[ ubTownId ].ubRating );
		AddSecondColumnMonoString( &hStringHandle, wString );
	}

	// if the town has a mine
	sMineSector = GetMineSectorForTown( ubTownId );
	if( sMineSector != -1 )
	{
		// Associated Mine: Sector
	  swprintf( wString, L"%s:",  pwTownInfoStrings[ 4 ] );
		AddMonoString( &hStringHandle, wString );
	  GetShortSectorString( ( INT16 )( sMineSector % MAP_WORLD_X ), ( INT16 )( sMineSector / MAP_WORLD_X ), wString );
		AddSecondColumnMonoString( &hStringHandle, wString );
	}
}