void GenerateStationPlaceSim (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	ALERROR error;
	int i, j, k;
	CSovereign *pPlayer = Universe.FindSovereign(g_PlayerSovereignUNID);

	int iSystemSample = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1);
	bool bLogo = !pCmdLine->GetAttributeBool(NO_LOGO_SWITCH);

	//	Generate systems for multiple games

	CSymbolTable AllSystems(TRUE, TRUE);
	for (i = 0; i < iSystemSample; i++)
		{
		if (bLogo)
			printf("pass %d...\n", i+1);

		CTopologyNode *pNode = Universe.GetFirstTopologyNode();

		while (true)
			{
			//	Create the system

			CSystem *pSystem;
			if (error = Universe.CreateStarSystem(pNode, &pSystem))
				{
				printf("ERROR: Unable to create star system.\n");
				return;
				}

			//	Find this system in the table.

			SPSimSystemInfo *pSystemEntry;
			if (error = AllSystems.Lookup(pNode->GetSystemName(), (CObject **)&pSystemEntry))
				{
				pSystemEntry = new SPSimSystemInfo;
				pSystemEntry->sName = pNode->GetSystemName();
				pSystemEntry->iLevel = pNode->GetLevel();
				pSystemEntry->dwSystemType = pNode->GetSystemTypeUNID();
				pSystemEntry->iCount = 1;

				for (j = 0; j < DIST_BUCKET_COUNT; j++)
					pSystemEntry->iEnemies[j] = 0;

				AllSystems.AddEntry(pSystemEntry->sName, pSystemEntry);
				}
			else
				pSystemEntry->iCount++;

			//	For all active stations in the system, count the number of enemy stations
			//	within certain distance buckets

			for (j = 0; j < pSystem->GetObjectCount(); j++)
				{
				CSpaceObject *pObj = pSystem->GetObject(j);

				//	Find any objects that are lootable by the player

				if (pObj
						&& pObj->GetCategory() == CSpaceObject::catStation
						&& pObj->CanAttack())
					{
					//	Count to see how many enemy stations are in range

					for (k = 0; k < pSystem->GetObjectCount(); k++)
						{
						CSpaceObject *pEnemy = pSystem->GetObject(k);
						if (pEnemy
								&& pEnemy->GetCategory() == CSpaceObject::catStation
								&& pEnemy->CanAttack()
								&& (pEnemy->IsEnemy(pObj) || pObj->IsEnemy(pEnemy)))
							{
							Metric rDist = pObj->GetDistance(pEnemy);
							int iDist = DistToBucketIndex(rDist);
							if (iDist != -1)
								{
								ASSERT(iDist < DIST_BUCKET_COUNT && iDist >= 0);
								pSystemEntry->iEnemies[iDist]++;

								int iLSDist = (int)((rDist / LIGHT_SECOND) + 0.5);
								if (iLSDist < 30)
									{
									printf("%s: %s (%x) and %s (%x) within %d ls\n",
											pSystem->GetName().GetASCIIZPointer(),
											pObj->GetNounPhrase().GetASCIIZPointer(),
											pObj->GetID(),
											pEnemy->GetNounPhrase().GetASCIIZPointer(),
											pEnemy->GetID(),
											iLSDist);
									}
								}
							}
						}
					}
				}

			//	Get the next node

			CString sEntryPoint;
			pNode = pSystem->GetStargateDestination(CONSTLIT("Outbound"), &sEntryPoint);
			if (pNode == NULL || pNode->IsEndGame())
				break;

			//	Done with old system

			Universe.DestroySystem(pSystem);
			}

		Universe.Reinit();
		}

	if (bLogo)
		printf("FINAL SYSTEM STATISTICS\n\n");

	//	Output total value stats

	printf("Level\tSystem\t<10 ls\t<25 ls\t<50ls\t<100 ls\n");

	int iTotals[DIST_BUCKET_COUNT];
	for (i = 0; i < DIST_BUCKET_COUNT; i++)
		iTotals[i] = 0;

	for (i = 0; i < AllSystems.GetCount(); i++)
		{
		SPSimSystemInfo *pSystemEntry = (SPSimSystemInfo *)AllSystems.GetValue(i);

		printf("%d\t%s",
				pSystemEntry->iLevel,
				pSystemEntry->sName.GetASCIIZPointer());

		for (j = 0; j < DIST_BUCKET_COUNT; j++)
			{
			printf("\t%.2f", (double)pSystemEntry->iEnemies[j] / (double)pSystemEntry->iCount);
			iTotals[j] += pSystemEntry->iEnemies[j];
			}

		printf("\n");
		}

	//	Totals

	printf("\n");
	printf("Within  10 ls: %.2f\n", iTotals[0] / (double)iSystemSample);
	printf("Within  25 ls: %.2f\n", iTotals[1] / (double)iSystemSample);
	printf("Within  50 ls: %.2f\n", iTotals[2] / (double)iSystemSample);
	printf("Within 100 ls: %.2f\n", iTotals[3] / (double)iSystemSample);

	printf("\n");
	}
void CDockingPorts::UpdateAll (SUpdateCtx &Ctx, CSpaceObject *pOwner)

//	UpdateAll
//
//	UpdateAll 

	{
	DEBUG_TRY

	int i;

	CSpaceObject *pPlayer = Ctx.pSystem->GetPlayer();
	Metric rDist2 = (pPlayer ? pPlayer->GetDistance2(pOwner) : 0.0);
	Metric rMaxDist = m_iMaxDist * LIGHT_SECOND;
	Metric rMaxDist2 = rMaxDist * rMaxDist;

	//	If owner is destroyed then don't bother checking for nearest player
	//	port.

	if (pPlayer 
			&& (pOwner->IsDestroyed() 
				|| pOwner->IsInactive() 
				|| pOwner == pPlayer
				|| pPlayer->IsDestroyed()))
		pPlayer = NULL;

	//	Also, don't bother checking if the owner is an enemy of the player.

	if (pPlayer && pPlayer->IsEnemy(pOwner) && !pOwner->IsAbandoned())
		pPlayer = NULL;

	//	Don't bother checking if the station is too far

	if (pPlayer && rDist2 > rMaxDist2)
		pPlayer = NULL;

	//	If this is a stargate and we are at the center (just came through) 
	//	then don't bother showing docking ports.

	if (pPlayer && pOwner->IsStargate() && rDist2 < GATE_DIST2)
		pPlayer = NULL;

	//	Loop over all ports

	for (i = 0; i < m_iPortCount; i++)
		{
		//	If a ship is docking with this port, then maneuver the ship towards
		//	the docking port.

		if (m_pPort[i].iStatus == psDocking)
			UpdateDockingManeuvers(pOwner, m_pPort[i]);

		//	Otherwise, if the port is open, see if this is the nearest port to
		//	the current player position.

		else if (m_pPort[i].iStatus == psEmpty)
			{
			if (pPlayer)
				{
				//	Compute the distance from the player to the port

				CVector vPortPos = pOwner->GetPos() + m_pPort[i].vPos;
				Metric rDist2 = (vPortPos - pPlayer->GetPos()).Length2();

				//	If this is a better port, then replace the existing 
				//	solution.

				if (Ctx.pDockingObj == NULL
							|| rDist2 < Ctx.rDockingPortDist2)
					{
					Ctx.pDockingObj = pOwner;
					Ctx.iDockingPort = i;
					Ctx.rDockingPortDist2 = rDist2;
					Ctx.vDockingPort = vPortPos;
					}
				}
			}
		}

	DEBUG_CATCH
	}