Ejemplo n.º 1
0
bool CDockingPorts::ShipsNearPort (CSpaceObject *pOwner, CSpaceObject *pRequestingObj, const CVector &vPortPos)

//	ShipsNearPort
//
//	Returns TRUE if there are ships near the given port

	{
	int i;
	CSystem *pSystem = pOwner->GetSystem();

	for (i = 0; i < pSystem->GetObjectCount(); i++)
		{
		CSpaceObject *pObj = pSystem->GetObject(i);
		if (pObj
				&& pObj->GetCategory() == CSpaceObject::catShip
				&& !pObj->IsInactive()
				&& pObj != pRequestingObj)
			{
			Metric rDist2 = (pObj->GetPos() - vPortPos).Length2();
			if (rDist2 < MIN_PORT_DISTANCE2 && !IsDockedOrDocking(pObj))
				return true;
			}
		}

	return false;
	}
Ejemplo n.º 2
0
bool CSystemManager::CheckFamine(const CSystem& system)
{
	const int food_prod = system.GetProduction()->GetFoodProd();
	if(food_prod >= 0)
		return false;
	const int food_store = system.GetFoodStore();
	return food_store + food_prod < 0;
}
Ejemplo n.º 3
0
	void Finish() const
	{
		AssertBotE(m_WorkersLeftToSet >= 0);
		#ifdef CONSISTENCY_CHECKS
			AssertBotE(m_pSystem->SanityCheckWorkers());
		#endif
		m_pSystem->CalculateVariables();
	}
Ejemplo n.º 4
0
	//puts an additional worker into industry, to prevent not finishing the project because
	//industry prod decreased due to loss of moral
	void SafeMoral()
	{
		const CAssemblyList& assembly_list = *m_pSystem->GetAssemblyList();
		AssertBotE(m_WorkersLeftToSet >= 0);
		if(assembly_list.IsEmpty() || m_WorkersLeftToSet == 0)
			return;
		const int max_buildings = m_pSystem->GetNumberOfWorkbuildings(WORKER::INDUSTRY_WORKER, 0);
		if(m_pSystem->GetWorker(WORKER::INDUSTRY_WORKER) < max_buildings)
			SetWorker(WORKER::INDUSTRY_WORKER, CSystem::SET_WORKER_MODE_INCREMENT);
	}
Ejemplo n.º 5
0
bool CFerianShipAI::InRangeOfThreat (CSpaceObject **retpThreat)

//	InRangeOfThreat
//
//	Returns the nearest threat

	{
	if (m_pShip->IsDestinyTime(19))
		{
		CSystem *pSystem = m_pShip->GetSystem();
		int iDestiny = m_pShip->GetDestiny();

		//	Get the list of objects that intersect the object

		SSpaceObjectGridEnumerator i;
		pSystem->EnumObjectsInBoxStart(i, m_pShip->GetPos(), MAX_THREAT_DIST);

		//	Loop over all objects

		Metric rNearestDist2 = MAX_THREAT_DIST * MAX_THREAT_DIST2;
		CSpaceObject *pNearestObj = NULL;

		while (pSystem->EnumObjectsInBoxHasMore(i))
			{
			CSpaceObject *pObj = pSystem->EnumObjectsInBoxGetNext(i);

			//	If the object is in the bounding box then remember
			//	it so that we can do a more accurate calculation.

			if (pObj->GetCategory() == CSpaceObject::catShip
					&& (!m_pShip->IsFriend(pObj) || pObj->GetDestiny() < iDestiny)
					&& pObj->CanAttack())
				{
				Metric rDist2 = m_pShip->GetDistance2(pObj);
				if (rDist2 < rNearestDist2)
					{
					pNearestObj = pObj;
					rNearestDist2 = rDist2;
					}
				}
			}

		//	Done

		if (pNearestObj)
			{
			*retpThreat = pNearestObj;
			return true;
			}
		}

	return false;
	}
Ejemplo n.º 6
0
	//fills all remaining empty buildings of the given cathegory, only considering available workers and buildings
	bool FillRemainingSlots(WORKER::Typ type)
	{
		AssertBotE(m_WorkersLeftToSet >= 0);
		if(m_WorkersLeftToSet == 0)
			return false;
		m_WorkersLeftToSet += m_pSystem->GetWorker(type);
		m_pSystem->SetWorker(type, CSystem::SET_WORKER_MODE_SET, 0);
		const int buildings = m_pSystem->GetNumberOfWorkbuildings(type, 0);
		const int to_set = min(buildings, m_WorkersLeftToSet);
		SetWorker(type, CSystem::SET_WORKER_MODE_SET,to_set);
		return true;
	}
Ejemplo n.º 7
0
void CPlayerGameStats::OnKeyEvent (EEventTypes iType, CSpaceObject *pObj, DWORD dwCauseUNID)

//	OnKeyEvent
//
//	Adds a key event involving an object

	{
	ASSERT(pObj);

	CSystem *pSystem = pObj->GetSystem();
	if (pSystem == NULL)
		return;

	//	Get the NodeID where the event happened

	CTopologyNode *pNode = pSystem->GetTopology();
	if (pNode == NULL)
		return;

	const CString &sNodeID = pNode->GetID();

	//	Get the object's type

	CDesignType *pType = pObj->GetType();
	if (pType == NULL)
		return;

	//	Get the object's name

	DWORD dwNameFlags;
	CString sName = pObj->GetName(&dwNameFlags);
	
	//	If the object name is the same as the type name then we don't bother
	//	storing it in the event (to save memory)

	if (strEquals(sName, pType->GetTypeName()))
		{
		sName = NULL_STR;
		dwNameFlags = 0;
		}

	//	Look for the list of events for this NodeID

	TArray<SKeyEventStats> *pEventList = m_KeyEventStats.Set(sNodeID);
	SKeyEventStats *pStats = pEventList->Insert();
	pStats->iType = iType;
	pStats->dwTime = g_pUniverse->GetTicks();
	pStats->dwObjUNID = pObj->GetType()->GetUNID();
	pStats->sObjName = sName;
	pStats->dwObjNameFlags = dwNameFlags;
	pStats->dwCauseUNID = dwCauseUNID;
	}
int main(void) {
	int testCase = 0;	// 测试用例数
	cin >> testCase;
	for(int t = 0; t < testCase; t++) {
		int eqNum = 0;	// 设备数
		cin >> eqNum;

		CSystem* cSystem = new CSystem(eqNum);
		cSystem->init();	// 初始化路由系统参数
		cSystem->solve();	// 使用DP计算路由系统各种设备组合下的性价比
		cSystem->print();	// 打印结果(最优性价比)
		delete cSystem;
	}
	return 0;
}
Ejemplo n.º 9
0
	//removes workers from factories until they are the minimum number to finish the current project
	//in still the same number of turns (as at the start of the function)
	int DecrementDueToWastedIndustry(bool max_industry)
	{
		m_pSystem->CalculateVariables();
		const CAssemblyList& assembly_list = *m_pSystem->GetAssemblyList();
		int unset = 0;
		if(assembly_list.IsEmpty() || assembly_list.GetWasBuildingBought())
			return unset;
		const int min_rounds = m_pSystem->NeededRoundsToBuild(0, true);
		AssertBotE(min_rounds >= 1);
		if(max_industry && min_rounds > 1 || m_pSystem->GetWorker(WORKER::INDUSTRY_WORKER) == 0)
			return unset;
		while(true)
		{
			SetWorker(WORKER::INDUSTRY_WORKER, CSystem::SET_WORKER_MODE_DECREMENT);
			++unset;
			m_pSystem->CalculateVariables();
			const int current_rounds = m_pSystem->NeededRoundsToBuild(0, true, false);
			if(m_pSystem->GetWorker(WORKER::INDUSTRY_WORKER) == 0)
			{
				if(min_rounds < current_rounds)
					OnBestIndustryWorkerCountFound(unset);
				return unset;
			}
			if(min_rounds < current_rounds)
			{
				OnBestIndustryWorkerCountFound(unset);
				return unset;
			}
		}
	}
Ejemplo n.º 10
0
	bool CheckShips(const std::map<CString, CShipMap>& ships) const
	{
		const int scan_power = m_pSystem->GetScanPower(m_pSystem->OwnerID(), true);
		for(std::map<CString, CShipMap>::const_iterator race = ships.begin(); race != ships.end(); ++race)
			for(CShipMap::const_iterator ship = race->second.begin(); ship != race->second.end(); ++ship)
			{
				if(ship->second->GetTorpedoWeapons()->IsEmpty())
				{
					const boost::shared_ptr<CMajor> owner =
						boost::dynamic_pointer_cast<CMajor>(ship->second->Owner());
					if(owner && !owner->IsHumanPlayer())
						continue;
				}
				if(!ship->second->GetCloak() && m_pSystem->GetNeededScanPower(ship->second->OwnerID()) <= scan_power)
					return true;
			}
		return false;
	}
Ejemplo n.º 11
0
// Actualizar el sistema (emuladores)
void CSystem::update(CSystem& p_system){
	Gtk::TreeModel::iterator l_iter;
	CEmulator l_emulator;

	GELIDE_DEBUG("System " << getName().data() << ": Updating...");
	// Intentamos añadir cada uno de los emuladores del sistema
	for(l_iter = p_system.getEmulatorList()->children().begin();
		l_iter != p_system.getEmulatorList()->children().end(); l_iter++){
		l_emulator.setId(0);
		l_emulator.setIconFile((*l_iter)[m_emulator_columns.m_icon_file]);
		l_emulator.setName((*l_iter)[m_emulator_columns.m_name]);
		l_emulator.setDescription((*l_iter)[m_emulator_columns.m_description]);
		l_emulator.setVersion((*l_iter)[m_emulator_columns.m_version]);
		l_emulator.setAuthor((*l_iter)[m_emulator_columns.m_author]);
		l_emulator.setHomepage((*l_iter)[m_emulator_columns.m_homepage]);
		l_emulator.setPath((*l_iter)[m_emulator_columns.m_path]);
		l_emulator.setParams((*l_iter)[m_emulator_columns.m_params]);
		addEmulator(l_emulator);
	}
}
Ejemplo n.º 12
0
	//Indreases workers in cathegories energy and food until we produce enough to suffice for the consumption we have
	bool IncreaseWorkersUntilSufficient(WORKER::Typ type, bool allow_insufficient)
	{
		AssertBotE(type == WORKER::ENERGY_WORKER || type == WORKER::FOOD_WORKER);
		if(m_pSystem->GetDisabledProductions()[type])
			return true;
		while(true)
		{
			const int value = (type == WORKER::ENERGY_WORKER) ? m_pProd->GetEnergyProd() : m_pProd->GetFoodProd();
			if(value >= 0)
				return true;
			if(m_WorkersLeftToSet <= 0)
				return allow_insufficient;
			const int number_of_buildings = m_pSystem->GetNumberOfWorkbuildings(type, 0);
			const int workers_set = m_pSystem->GetWorker(type);
			AssertBotE(workers_set <= number_of_buildings);
			if(workers_set == number_of_buildings)
				return allow_insufficient;
			SetWorker(type, CSystem::SET_WORKER_MODE_INCREMENT);
			m_pSystem->CalculateVariables();
		}
	}
Ejemplo n.º 13
0
void CTranscendenceWnd::DestroyIntroShips (void)

//	DestroyIntroShips
//
//	Destroys all ships of the same class as the POV

	{
	int i;

	CShip *pShip = g_pUniverse->GetPOV()->AsShip();
	if (pShip == NULL)
		return;

	//	Destroy all ships of the current class

	CSystem *pSystem = pShip->GetSystem();
	CShipClass *pClassToDestroy = pShip->GetClass();
	TArray<CSpaceObject *> ShipsToDestroy;
	CSpaceObject *pOtherShip = NULL;
	for (i = 0; i < pSystem->GetObjectCount(); i++)
		{
		CSpaceObject *pObj = pSystem->GetObject(i);
		CShip *pShip;
		if (pObj 
				&& !pObj->IsInactive()
				&& !pObj->IsVirtual()
				&& (pShip = pObj->AsShip()))
			{
			if (pShip->GetClass() == pClassToDestroy)
				ShipsToDestroy.Insert(pObj);
			else if (pOtherShip == NULL)
				pOtherShip = pObj;
			}
		}

	//	Destroy ships

	for (i = 0; i < ShipsToDestroy.GetCount(); i++)
		ShipsToDestroy[i]->Destroy(removedFromSystem, CDamageSource());
	}
Ejemplo n.º 14
0
	//worker setting function which makes according changes to m_WorkersLeftToSet, tracking how many
	//we still have to distribute at all
	void SetWorker(WORKER::Typ type, CSystem::SetWorkerMode mode, int value = -1)
	{
		if(mode == CSystem::SET_WORKER_MODE_INCREMENT)
		{
			AssertBotE(value == -1);
			m_pSystem->SetWorker(type, mode);
			--m_WorkersLeftToSet;
		}
		else if(mode == CSystem::SET_WORKER_MODE_DECREMENT)
		{
			AssertBotE(value == -1);
			m_pSystem->SetWorker(type, mode);
			++m_WorkersLeftToSet;
		}
		else if(mode == CSystem::SET_WORKER_MODE_SET)
		{
			AssertBotE(value >= 0);
			m_pSystem->SetWorker(type, mode, value);
			m_WorkersLeftToSet -= value;
		}
		AssertBotE(m_WorkersLeftToSet >= 0);
	}
Ejemplo n.º 15
0
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
#if _DEBUG
	AllocConsole();
	freopen("CONOUT$", "w", stdout);
#endif
	CSystem system;

	// 초기화에 실패하면?
	if (!(system.Init()))
		system.Release();
	
	// 루프
	if (DataManager->bIsGameRun)
		system.MessageLoop();

	// 초기화
	system.Release();
}
Ejemplo n.º 16
0
CSpaceObject *CDamageSource::GetObj (void) const

//	GetObj
//
//	Returns the source object

	{
	CSpaceObject *pOrderGiver;

	//	If the source is the player then always return the player
	//	object (regardless of m_pSource). We do this in case
	//	the player changes ships.

	if (m_dwFlags & FLAG_IS_PLAYER)
		{
		CSystem *pSystem = g_pUniverse->GetCurrentSystem();
		return (pSystem ? pSystem->GetPlayer() : NULL);
		}

	//	Otherwise, if we're a subordinate and our order giver
	//	has changed, switch back to the player.

	else if ((m_dwFlags & FLAG_IS_PLAYER_SUBORDINATE)
			&& (m_pSource == NULL
				|| (pOrderGiver = m_pSource->GetOrderGiver()) == NULL
				|| !pOrderGiver->IsPlayer()))
		{
		CSystem *pSystem = g_pUniverse->GetCurrentSystem();
		return (pSystem ? pSystem->GetPlayer() : NULL);
		}

	//	Otherwise, return the source (even if NULL)

	else
		return m_pSource;
	}
Ejemplo n.º 17
0
	//distributes workers onto priorities remaining after max priorities have been processed
	//workers that cannot be set because of number of buildings are tried to be set into
	//the cathegory with next less workers
	void DoPriorities(const std::map<WORKER::Typ, int>& priorities, bool max_industry, bool safe_moral)
	{
		SafeMoralWorkerReserve reserve(*this, safe_moral);
		std::map<WORKER::Typ, int> prios(priorities);
		DoMaxPriorities(prios, max_industry);
		DefaultDistributionCalculator decalc(m_WorkersLeftToSet, prios);
		const std::vector<DistributionElem>& result = decalc.Calc();
		int failed_to_set = 0;
		for(std::vector<DistributionElem>::const_iterator it = result.begin(); it != result.end(); ++it)
		{
			const int buildings = m_pSystem->GetNumberOfWorkbuildings(it->m_Type, 0);
			if(buildings >= it->m_iCount) {
				int try_set = it->m_iCount;
				if(it->m_Type != WORKER::INDUSTRY_WORKER)
					try_set += failed_to_set;
				if(buildings >= try_set) {
					if(it->m_Type != WORKER::INDUSTRY_WORKER)
						failed_to_set = 0;
					SetWorker(it->m_Type, CSystem::SET_WORKER_MODE_SET, try_set);
				}
				else {
					if(it->m_Type != WORKER::INDUSTRY_WORKER)
						failed_to_set -= buildings -it->m_iCount;
					SetWorker(it->m_Type, CSystem::SET_WORKER_MODE_SET, buildings);
				}
			}
			else {
				failed_to_set += it->m_iCount - buildings;
				SetWorker(it->m_Type, CSystem::SET_WORKER_MODE_SET, buildings);
			}
			AssertBotE(m_WorkersLeftToSet >= 0 && failed_to_set >= 0);
			failed_to_set += DecrementDueToFullStore(it->m_Type);
			if(it->m_Type == WORKER::INDUSTRY_WORKER) {
				failed_to_set += DecrementDueToWastedIndustry(max_industry);
			}
		}
	}
Ejemplo n.º 18
0
	//removes workers from a cathegory which has a store until production + store <= store,
	//so that nothing will be wasted on next turn change
	int DecrementDueToFullStore(WORKER::Typ type)
	{
		int unset = 0;
		if(!m_pSystem->HasStore(type))
			return unset;
		const int store = m_pSystem->GetResourceStore(type);
		while(true)
		{
			const int workers = m_pSystem->GetWorker(type);
			if(workers == 0)
				break;
			m_pSystem->CalculateVariables();
			const int prod = m_pSystem->GetProduction()->GetXProd(type);
			if(store + prod <= m_pSystem->GetXStoreMax(type))
				break;
			SetWorker(type, CSystem::SET_WORKER_MODE_DECREMENT);
			++unset;
		}
		return unset;
	}
Ejemplo n.º 19
0
void DoTradeSim (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	ALERROR error;
	int i, j;
	CSovereign *pPlayer = Universe.FindSovereign(g_PlayerSovereignUNID);

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

	//	For each station type we keep track of the items that it sells and the
	//	various prices that each instances charges.

	SStationData AllStations;

	//	For each item type we keep track of the stations that sell and/or
	//	buy it.

	SItemData AllItems;

	//	Generate systems for multiple games

	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;
				}

			//	For all active stations in the system, get their trading information

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

				if (pObj && pObj->GetCategory() == CSpaceObject::catStation)
					CompileTradeData(pObj, &AllStations, &AllItems);
				}

			//	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 STATISTICS\n\n");

	//	Loop over each item and output the best trading strategy

	printf("Item\tSeller\tSell Price\tBuyer\tBuy Price\tProfit\n");
	for (i = 0; i < AllItems.GetCount(); i++)
		{
		ComputeAverages(&AllItems[i]);
		OutputTradingStrategy(AllItems[i]);
		}
	}
Ejemplo n.º 20
0
void GenerateEncounterCount (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	int i, j, k, l;

	//	Options

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

	//	Additional columns

	TArray<CString> Cols;
	for (i = 0; i < pCmdLine->GetAttributeCount(); i++)
		{
		CString sAttrib = pCmdLine->GetAttributeName(i);

		if (!IsMainCommandParam(sAttrib)
				&& !strEquals(sAttrib, CONSTLIT("count"))
				&& !strEquals(sAttrib, CONSTLIT("encountercount")))
			{
			CString sValue = pCmdLine->GetAttribute(i);
			
			if (!strEquals(sValue, CONSTLIT("true")))
				Cols.Insert(strPatternSubst(CONSTLIT("%s:%s"), sAttrib, sValue));
			else
				Cols.Insert(sAttrib);
			}
		}

	//	Generate systems for multiple games

	TSortMap<CString, SNodeDesc> NodeTable;

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

		//	Initialize the game

		CString sError;
		if (Universe.InitGame(0, &sError) != NOERROR)
			{
			printf("%s\n", sError.GetASCIIZPointer());
			return;
			}

		for (j = 0; j < Universe.GetTopologyNodeCount(); j++)
			{
			CTopologyNode *pNode = Universe.GetTopologyNode(j);
			if (pNode->IsEndGame())
				continue;

			//	Create the system

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

			//	Create a sort string for this system

			CString sSort = strPatternSubst(CONSTLIT("%02d-%s"), pSystem->GetLevel(), pNode->GetID());

			//	Get the table

			bool bNew;
			SNodeDesc *pResult = NodeTable.SetAt(sSort, &bNew);
			if (bNew)
				{
				pResult->iLevel = pNode->GetLevel();
				pResult->sNodeID = pNode->GetID();
				}

			//	Accumulate data

			AddSystemData(pSystem, bAll, pResult);

			//	Done with old system

			Universe.DestroySystem(pSystem);
			}

		Universe.Reinit();
		}

	//	Header

	printf("Level\tNode\tSystemType\tCategory\tSovereign\tEncounter\tCount");
	for (i = 0; i < Cols.GetCount(); i++)
		printf("\t%s", Cols[i].GetASCIIZPointer());
	printf("\n");

	//	Output all rows

	for (i = 0; i < NodeTable.GetCount(); i++)
		{
		for (j = 0; j < NodeTable[i].Table.GetCount(); j++)
			{
			CCountTable &Encounters = NodeTable[i].Table[j];

			for (k = 0; k < Encounters.GetCount(); k++)
				{
				int iCount = Encounters[k] / iSystemSample;
				int iCountFrac = 1000 * (Encounters[k] % iSystemSample) / iSystemSample;
				CStationType *pEncounterType = Universe.FindStationType(Encounters.GetKey(k));
				if (pEncounterType == NULL)
					continue;

				CSovereign *pSovereign = pEncounterType->GetControllingSovereign();
				CString sSovereign = (pSovereign ? pSovereign->GetTypeName() : CONSTLIT("(Unknown)"));

				printf("%d\t%s\t0x%08x\t%s\t%s\t%s\t%d.%03d",
						NodeTable[i].iLevel,
						NodeTable[i].sNodeID.GetASCIIZPointer(),
						NodeTable[i].Table.GetKey(j),
						pEncounterType->GetDataField(CONSTLIT("category")).GetASCIIZPointer(),
						sSovereign.GetASCIIZPointer(),
						pEncounterType->GetName().GetASCIIZPointer(),
						iCount,
						iCountFrac);

				for (l = 0; l < Cols.GetCount(); l++)
					{
					CString sValue = pEncounterType->GetDataField(Cols[l]);
					printf("\t%s", sValue.GetASCIIZPointer());
					}

				printf("\n");
				}
			}
		}
	}
Ejemplo n.º 21
0
void GenerateSnapshot (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	ALERROR error;
	int i;

	//	Get some parameters

	int iInitialUpdateTime = 10;
	int iUpdateTime = pCmdLine->GetAttributeInteger(CONSTLIT("wait"));

	//	Criteria

	CString sNode = pCmdLine->GetAttribute(CONSTLIT("node"));
	CString sCriteria = pCmdLine->GetAttribute(CONSTLIT("criteria"));

	//	Output

	int cxWidth;
	int cyHeight;
	if (pCmdLine->FindAttributeInteger(CONSTLIT("size"), &cxWidth))
		{
		cyHeight = cxWidth;
		}
	else
		{
		cxWidth = 1024;
		cyHeight = 1024;
		}

	//	Paint flags

	DWORD dwPaintFlags = 0;
	if (pCmdLine->GetAttributeBool(CONSTLIT("noStars")))
		dwPaintFlags |= CSystem::VWP_NO_STAR_FIELD;

	//	Output file

	CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output"));
	if (!sFilespec.IsBlank())
		sFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp"));

	//	Update context

	SSystemUpdateCtx Ctx;
	Ctx.bForceEventFiring = true;
	Ctx.bForcePainted = true;

	//	Loop over all systems until we find what we're looking for

	int iLoops = 20;
	int iNodeIndex = 0;
	CTopologyNode *pNode = Universe.GetTopologyNode(iNodeIndex);
	while (true)
		{
		//	Create the system

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

		//	If this is the node we want, then search

		CSpaceObject *pTarget;
		if (sNode.IsBlank() || strEquals(sNode, pNode->GetID()))
			{
			printf("Searching %s...\n", pNode->GetSystemName().GetASCIIZPointer());

			//	Set the POV

			CSpaceObject *pPOV = pSystem->GetObject(0);
			Universe.SetPOV(pPOV);
			pSystem->SetPOVLRS(pPOV);

			//	Prepare system

			Universe.UpdateExtended();
			Universe.GarbageCollectLibraryBitmaps();

			//	Update for a while

			for (i = 0; i < iInitialUpdateTime; i++)
				Universe.Update(Ctx);

			//	Compose the criteria

			CSpaceObject::Criteria Criteria;
			CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria);

			//	Get the list of all objects in the system that match the criteria

			CSpaceObject::SCriteriaMatchCtx Ctx(Criteria);
			TArray<CSpaceObject *> Results;
			for (i = 0; i < pSystem->GetObjectCount(); i++)
				{
				CSpaceObject *pObj = pSystem->GetObject(i);
				if (pObj && pObj->MatchesCriteria(Ctx, Criteria))
					Results.Insert(pObj);
				}

			//	Pick the appropriate object from the list

			if (Results.GetCount() == 0)
				pTarget = NULL;
			else if (Criteria.bNearestOnly || Criteria.bFarthestOnly)
				pTarget = Ctx.pBestObj;
			else
				pTarget = Results[mathRandom(0, Results.GetCount() - 1)];
			}
		else
			pTarget = NULL;

		//	If we found the target, then output

		if (pTarget)
			{
			//	If we found the target, take a snapshot

			printf("Found %s.\n", pTarget->GetNounPhrase(0).GetASCIIZPointer());

			//	Wait a bit

			for (i = 0; i < iUpdateTime; i++)
				{
				if ((i % 100) == 99)
					printf(".");

				Universe.Update(Ctx);
				}

			if (iUpdateTime >= 99)
				printf("\n");

			//	Paint

			CG16bitImage Output;
			Output.CreateBlank(cxWidth, cyHeight, false);
			RECT rcViewport;
			rcViewport.left = 0;
			rcViewport.top = 0;
			rcViewport.right = cxWidth;
			rcViewport.bottom = cyHeight;
			
			pSystem->PaintViewport(Output, rcViewport, pTarget, dwPaintFlags);

			//	Write to file

			if (!sFilespec.IsBlank())
				{
				CFileWriteStream OutputFile(sFilespec);
				if (OutputFile.Create() != NOERROR)
					{
					printf("ERROR: Unable to create '%s'\n", sFilespec.GetASCIIZPointer());
					return;
					}

				Output.WriteToWindowsBMP(&OutputFile);
				OutputFile.Close();
				printf("%s\n", sFilespec.GetASCIIZPointer());
				}

			//	Otherwise, clipboard

			else
				{
				if (error = Output.CopyToClipboard())
					{
					printf("ERROR: Unable to copy image to clipboard.\n");
					return;
					}

				printf("Image copied to clipboard.\n");
				}

			//	Done

			break;
			}

		//	Done with old system

		Universe.DestroySystem(pSystem);

		//	Loop to the next node

		do
			{
			iNodeIndex = ((iNodeIndex + 1) % Universe.GetTopologyNodeCount());
			pNode = Universe.GetTopologyNode(iNodeIndex);
			}
		while (pNode == NULL || pNode->IsEndGame());

		//	If we're back to the first node again, restart

		if (iNodeIndex == 0)
			{
			if (--iLoops > 0)
				{
				Universe.Reinit();

				iNodeIndex = 0;
				pNode = Universe.GetTopologyNode(iNodeIndex);
				}
			else
				{
				printf("ERROR: Specified target could not be found.\n");
				return;
				}
			}
		}
	}
Ejemplo n.º 22
0
EResults RunEncounter (CUniverse &Universe, CSimViewer &Viewer, CStationType *pDefenderType, CShipClass *pAttackerClass, CSovereign *pAttackerSovereign)
	{
	int iTimeOut = DEFAULT_TIME_OUT;

	//	Make sure the universe is clean

	CString sError;
	if (Universe.InitGame(0, &sError) != NOERROR)
		{
		printf("ERROR: %s", sError.GetASCIIZPointer());
		return resultError;
		}

	//	Create an empty system

	CSystem *pSystem;
	if (Universe.CreateEmptyStarSystem(&pSystem) != NOERROR)
		{
		printf("ERROR: Unable to create empty star system.\n");
		return resultError;
		}

	//	Create a station in the center of the system

	CSpaceObject *pStation;
	if (pSystem->CreateStation(pDefenderType, NULL, CVector(), &pStation) != NOERROR)
		{
		printf("ERROR: Unable to create station.\n");
		return resultError;
		}

	//	Set the POV

	Universe.SetPOV(pStation);
	pSystem->SetPOVLRS(pStation);

	//	Prepare system

	Universe.UpdateExtended();
	Universe.GarbageCollectLibraryBitmaps();
	Universe.StartGame(true);

	//	Now create an attacker some distance away

	CVector vPos = PolarToVector(mathRandom(0, 359), INITIAL_DISTANCE);

	CShip *pAttacker;
	if (pSystem->CreateShip(pAttackerClass->GetUNID(), NULL, NULL, pAttackerSovereign, vPos, CVector(), 0, NULL, NULL, &pAttacker) != NOERROR)
		{
		printf("ERROR: Unable to create attacking ship.\n");
		return resultError;
		}

	//	Set the attacker to attack the station

	IShipController *pController = pAttacker->GetController();
	if (pController == NULL)
		{
		printf("ERROR: No controller for ship.\n");
		return resultError;
		}

	pController->AddOrder(IShipController::orderAttackStation, pStation, IShipController::SData());

	//	Watch the attacker

	Universe.SetPOV(pAttacker);
	pSystem->SetPOVLRS(pAttacker);

	//	Update context

	SSystemUpdateCtx Ctx;
	Ctx.bForceEventFiring = true;
	Ctx.bForcePainted = true;

	//	Now keep updating until either the station is destroyed, the ship is destroyed, or we time-out

	int iTime = 0;
	int iDestroyedTime = (Viewer.IsEmpty() ? 0 : DESTROY_TIME);
	bool bDestroyed = false;
	EResults iResult = resultTimeout;
	while (iTime < iTimeOut && (!bDestroyed || iDestroyedTime > 0))
		{
		iTime++;
		Universe.Update(Ctx);

		if (!Viewer.IsEmpty())
			Viewer.PaintViewport(Universe);

		if (bDestroyed)
			iDestroyedTime--;
		else if (pStation->IsDestroyed() || pStation->IsAbandoned())
			{
			bDestroyed = true;
			iResult = resultDefenderDestroyed;
			}
		else if (pAttacker->IsDestroyed())
			{
			bDestroyed = true;
			iResult = resultAttackerDestroyed;
			}
		}

	//	Done

	return iResult;
	}
Ejemplo n.º 23
0
// Funktion löscht einen Eintrag aus der Bauliste, wenn das Gebäude fertig wurde oder wir den ersten
// Eintrag manuell löschen möchten. Nach Aufruf dieser Funktion muß unbedingt die Funktion
// CalculateVariables() aufgerufen werden.
void CAssemblyList::ClearAssemblyList(const CPoint &ko, std::vector<CSystem>& systems)
{
	// Alle prozentualen Anteile eines womöglich früheren Bauauftrages aus den Ressourcenrouten löschen
	CSystem* system = &systems.at(ko.x+(ko.y)*STARMAP_SECTORS_HCOUNT);

	CArray<CPoint> routesFrom;
	ULONG resourcesFromRoutes[DERITIUM + 1];
	ULONG nResInDistSys[DERITIUM + 1];
	CPoint ptResourceDistributorKOs[DERITIUM + 1];

	for (int i = 0; i <= DERITIUM; i++)
	{
		resourcesFromRoutes[i] = 0;
		nResInDistSys[i] = 0;
		ptResourceDistributorKOs[i] = CPoint(-1,-1);
	}

	// Ressourcenrouten durchgehen und womöglich die möglichen max. zusätzlichen Ressourcen erfragen
	for (int y = 0; y < STARMAP_SECTORS_VCOUNT; y++)
	{
		for (int x = 0; x < STARMAP_SECTORS_HCOUNT; x++)
		{
			if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetOwnerOfSystem() == system->GetOwnerOfSystem() && CPoint(x,y) != ko)
			{
				for (int i = 0; i < systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetSize(); i++)
				{
					if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetAt(i).GetKO() == ko)
					{
						// prozentualen Anteil vom alten Auftrag zurücksetzen
						systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->ElementAt(i).SetPercent(0);
						// Ressourcen über Route holen
						if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetBlockade() == NULL && systems.at(ko.x+(ko.y)*STARMAP_SECTORS_HCOUNT).GetBlockade() == NULL)
						{
							routesFrom.Add(CPoint(x,y));
							BYTE res = systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetAt(i).GetResource();
							resourcesFromRoutes[res] += systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceStore(res);
						}
					}
				}
				// gilt nicht bei Blockaden
				if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetBlockade() == NULL && systems.at(ko.x+(ko.y)*STARMAP_SECTORS_HCOUNT).GetBlockade() == NULL)
				{
					for (int res = TITAN; res <= DERITIUM; res++)
					{
						if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetProduction()->GetResourceDistributor(res))
						{
							ptResourceDistributorKOs[res] = CPoint(x,y);
							nResInDistSys[res] = systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceStore(res);
						}
					}
				}
			}
		}
	}

	// AssemblyList Eintrag des gebauten Gebäudes/Updates/Schiffes löschen, wenn wir noch den
	// Eintrag an der nächsten Stelle haben (sprich AssemblyList[1] != 0), dann alle
	// anderen Einträge um eins nach vorn verschieben -> letzter wird frei
	m_iEntry[0] = 0;
	m_iNeededIndustryInAssemblyList[0] = 0;
	m_iNeededTitanInAssemblyList[0]    = 0;
	m_iNeededDeuteriumInAssemblyList[0]= 0;
	m_iNeededDuraniumInAssemblyList[0] = 0;
	m_iNeededCrystalInAssemblyList[0]  = 0;
	m_iNeededIridiumInAssemblyList[0]  = 0;
	m_iNeededDeritiumInAssemblyList[0]= 0;

	for (int i = 0; i < ALE - 1; i++)
	{
		// wenn der nächste Eintrag ungleich 0 ist
		if (m_iEntry[i + 1] != 0)
		{
			m_iEntry[i] = m_iEntry[i + 1];
			m_iNeededIndustryInAssemblyList[i] = m_iNeededIndustryInAssemblyList[i + 1];
			m_iNeededTitanInAssemblyList[i]	   = m_iNeededTitanInAssemblyList[i + 1];
			m_iNeededDeuteriumInAssemblyList[i]= m_iNeededDeuteriumInAssemblyList[i + 1];
			m_iNeededDuraniumInAssemblyList[i] = m_iNeededDuraniumInAssemblyList[i + 1];
			m_iNeededCrystalInAssemblyList[i]  = m_iNeededCrystalInAssemblyList[i + 1];
			m_iNeededIridiumInAssemblyList[i]  = m_iNeededIridiumInAssemblyList[i + 1];
			m_iNeededDeritiumInAssemblyList[i]= m_iNeededDeritiumInAssemblyList[i + 1];

			// den Nachfolger überall auf NULL setzen
			m_iEntry[i + 1] = 0;
			m_iNeededIndustryInAssemblyList[i + 1] = 0;
			m_iNeededTitanInAssemblyList[i + 1]    = 0;
			m_iNeededDeuteriumInAssemblyList[i + 1]= 0;
			m_iNeededDuraniumInAssemblyList[i + 1] = 0;
			m_iNeededCrystalInAssemblyList[i + 1]  = 0;
			m_iNeededIridiumInAssemblyList[i + 1]  = 0;
		}
		else
			break;
	}

	// Checken, ob der nächste Eintrag auch baubar ist -> genügend RES im Lager
	// normalerweise kann man in der Bauliste ja nur Einträge vornehmen, wenn
	// man genügend RES hat. Also sollte er auch baubar sein, wenn die IP
	// erbracht wurden. Aber durch Zufallsereignisse oder Börsenverkäufe von RES
	// kann man später ja zu wening davon haben. Und weil die RES erst abgezogen
	// wird, wenn das Gebäude an erster Stelle in der Bauliste rückt, müssen
	// wird das überprüfen. Haben wir nicht genug RES, wird der Bauauftrag
	// gecancelt

	// Überprüfen, ob wir genügend Rohstoffe in dem Lager haben
	for (int res = TITAN; res <= DERITIUM; res++)
	{
		UINT nNeededRes = this->GetNeededResourceInAssemblyList(0, res);
		if (*system->GetResourceStorages(res) + resourcesFromRoutes[res] < nNeededRes && nResInDistSys[res] < nNeededRes)
		{
			// Wenn nicht -> dann Eintrag wieder entfernen
			ClearAssemblyList(ko, systems);
			return;
		}
	}

	// Wenn er baubar ist, dann die Ressourcen entfernen
	for (int res = TITAN; res <= DERITIUM; res++)
	{
		UINT nNeededRes = this->GetNeededResourceInAssemblyList(0, res);
		if (nNeededRes > 0)
		{
			// Ressource wird aus eigenem System bzw. über Ressourcenroute geholt
			if (*system->GetResourceStorages(res) + resourcesFromRoutes[res] >= nNeededRes)
				RemoveResourceFromStorage(res, ko, systems, &routesFrom);
			// reicht das nicht, so wird Ressource aus dem Verteiler geholt
			else
			{
				CArray<CPoint> vNullRoutes;
				RemoveResourceFromStorage(res, ptResourceDistributorKOs[res], systems, &vNullRoutes);
			}
		}
	}
}
Ejemplo n.º 24
0
BOOLEAN CAssemblyList::MakeEntry(int runningNumber, const CPoint &ko, std::vector<CSystem>& systems, bool bOnlyTest)
{
	// Die Assemblylist durchgehen, ob wir einen Eintrag finden, der noch 0 ist
	// dort können wir den nächsten speichern, gibt es keinen, dann ist die
	// Bauliste voll
	int entry = -1;
	if (!bOnlyTest)
	{
		for (int i = 0; i < ALE; i++)
		{
			if (m_iEntry[i] == 0)
			{
				entry = i;
				break;
			}
		}

		// prüfen ob Bauliste schon voll!
		if (entry == -1)
			return FALSE;
	}

	CSystem* system = &systems.at(ko.x+(ko.y)*STARMAP_SECTORS_HCOUNT);
	// Ressourcenrouten durchgehen und womöglich die möglichen max. zusätzlichen Ressourcen erfragen
	CArray<CPoint> routesFrom;
	ULONG resourcesFromRoutes[DERITIUM + 1];
	ULONG nResInDistSys[DERITIUM + 1];
	CPoint ptResourceDistributorKOs[DERITIUM + 1];

	for (int i = 0; i <= DERITIUM; i++)
	{
		resourcesFromRoutes[i] = 0;
		nResInDistSys[i] = 0;
		ptResourceDistributorKOs[i] = CPoint(-1,-1);
	}

	for (int y = 0; y < STARMAP_SECTORS_VCOUNT; y++)
	{
		for (int x = 0; x < STARMAP_SECTORS_HCOUNT; x++)
		{
			if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetOwnerOfSystem() == system->GetOwnerOfSystem() && CPoint(x,y) != ko)
			{
				for (int i = 0; i < systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetSize(); i++)
				{
					if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetAt(i).GetKO() == ko)
					{
						if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetBlockade() == NULL && systems.at(ko.x+(ko.y)*STARMAP_SECTORS_HCOUNT).GetBlockade() == NULL)
						{
							routesFrom.Add(CPoint(x,y));
							BYTE res = systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetAt(i).GetResource();
							resourcesFromRoutes[res] += systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceStore(res);
						}
					}
				}
				// gilt nicht bei Blockaden
				if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetBlockade() == NULL && systems.at(ko.x+(ko.y)*STARMAP_SECTORS_HCOUNT).GetBlockade() == NULL)
				{
					for (int res = TITAN; res <= DERITIUM; res++)
					{
						if (systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetProduction()->GetResourceDistributor(res))
						{
							ptResourceDistributorKOs[res] = CPoint(x,y);
							nResInDistSys[res] = systems.at(x+(y)*STARMAP_SECTORS_HCOUNT).GetResourceStore(res);
						}
					}
				}
			}
		}
	}
	// Überprüfen, ob wir genügend Rohstoffe in dem Lager haben
	for (int res = TITAN; res <= DERITIUM; res++)
	{
		UINT nNeededRes = this->GetNeededResourceForBuild(res);
		if (*system->GetResourceStorages(res) + resourcesFromRoutes[res] < nNeededRes && nResInDistSys[res] < nNeededRes)
			return FALSE;
	}
	if (bOnlyTest)
		return TRUE;

	// Ansonsten gibt es genügend Rohstoffe
	m_iEntry[entry] = runningNumber;
	// Was wir für das notwendige Projekt alles so brauchen speichern
	m_iNeededIndustryInAssemblyList[entry] = m_iNeededIndustryForBuild;
	m_iNeededTitanInAssemblyList[entry]	   = m_iNeededTitanForBuild;
	m_iNeededDeuteriumInAssemblyList[entry]= m_iNeededDeuteriumForBuild;
	m_iNeededDuraniumInAssemblyList[entry] = m_iNeededDuraniumForBuild;
	m_iNeededCrystalInAssemblyList[entry]  = m_iNeededCrystalForBuild;
	m_iNeededIridiumInAssemblyList[entry]  = m_iNeededIridiumForBuild;
	m_iNeededDeritiumInAssemblyList[entry]= m_iNeededDeritiumForBuild;
	// Nur wenn es der erste Eintrag im Baumenü ist wird alles abgezogen
	// ansonsten erst, nachdem das Projekt im ersten Eintrag fertig ist
	if (entry == 0)
	{
		for (int res = TITAN; res <= DERITIUM; res++)
		{
			UINT nNeededRes = this->GetNeededResourceForBuild(res);
			if (nNeededRes > 0)
			{
				// Ressource wird aus eigenem System bzw. über Ressourcenroute geholt
				if (*system->GetResourceStorages(res) + resourcesFromRoutes[res] >= nNeededRes)
					RemoveResourceFromStorage(res, ko, systems, &routesFrom);
				// reicht das nicht, so wird Ressource aus dem Verteier geholt
				else
				{
					CArray<CPoint> vNullRoutes;
					RemoveResourceFromStorage(res, ptResourceDistributorKOs[res], systems, &vNullRoutes);
				}
			}
		}
	}

	// Eintrag konnte gesetzt werden
	return TRUE;
}
Ejemplo n.º 25
0
// Diese Funktion entfernt die benötigten Ressourcen aus dem lokalen Lager des Systems und falls Ressourcenrouten
// bestehen auch die Ressourcen in den Startsystemen der Route. Aber nur falls dies auch notwendig sein sollte.
void CAssemblyList::RemoveResourceFromStorage(BYTE res, const CPoint &ko, std::vector<CSystem>& systems, CArray<CPoint>* routesFrom)
{
	if (ko == CPoint(-1,-1))
		return;

	CSystem *system = &systems.at(ko.x+(ko.y)*STARMAP_SECTORS_HCOUNT);

	// für Deritium gibt es keine Ressourcenroute
	if (res != DERITIUM)
	{
		// zuerst wird immer versucht, die Ressourcen aus dem lokalen Lager zu nehmen
		long remainingRes = GetNeededResourceInAssemblyList(0, res) - system->GetResourceStore(res);
		// werden zusätzliche Ressourcen aus anderen Lagern benötigt, so kann das lokale Lager
		// auf NULL gesetzt werden
		if (remainingRes > 0)
		{
			*system->GetResourceStorages(res) = NULL;
			// zusätzliche Ressourcen müssen aus den Lagern der Systeme mit den Ressourcenrouten
			// bezogen werden. Dafür ein Feld anlegen, indem alle Startsysteme mit der zur Ressouce passenden
			// Ressourcenroute beinhaltet sind.
			struct ROUTELIST {
				CResourceRoute *route;
				CPoint fromSystem;

				ROUTELIST() : route(0), fromSystem(0) {}
				ROUTELIST(CResourceRoute *_route, CPoint _fromSystem) : route(_route), fromSystem(_fromSystem) {}
			};
			CArray<ROUTELIST> routes;
			for (int j = 0; j < routesFrom->GetSize(); j++)
			{
				CPoint p = routesFrom->GetAt(j);
				for (int k = 0; k < systems.at(p.x+(p.y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetSize(); k++)
				{
					// Stimmt die Ressource überein=
					if (systems.at(p.x+(p.y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetAt(k).GetResource() == res)
					{
						// Stimmt das Zielsystem mit unserem überein?
						if (systems.at(p.x+(p.y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetAt(k).GetKO() == ko)
						{
							// prüfen das die Route nicht schon verwendet wird
							bool bUsed = false;
							for (int l = 0; l < routes.GetSize(); l++)
								if (routes.GetAt(l).fromSystem == p)
								{
									bUsed = true;
									break;
								}
							if (!bUsed)
								routes.Add(ROUTELIST(&systems.at(p.x+(p.y)*STARMAP_SECTORS_HCOUNT).GetResourceRoutes()->GetAt(k), p));
						}
					}
				}
			}
			// in routes sind nun die Zeiger auf die richtigen Ressourcenrouten, also die Routen, welche auch den
			// passenden Rohstoff liefern könnten.
			while (routes.GetSize())
			{
				// zufällig eine Route aus den möglichen auswählen, damit nicht immer das gleiche System zuerst
				// die Rohstoffe liefern muss, falls mehrere Routen der selben Art ins System eingehen.
				int random = rand()%routes.GetSize();
				int percent = 0;
				CPoint start = routes.GetAt(random).fromSystem;
				// sind im jeweiligen Lager des Startsystem genügend Rohstoffe vorhanden
				if (systems.at(start.x+(start.y)*STARMAP_SECTORS_HCOUNT).GetResourceStore(res) >= (ULONG)remainingRes)
				{
					*systems.at(start.x+(start.y)*STARMAP_SECTORS_HCOUNT).GetResourceStorages(res) -= remainingRes;
					if (GetNeededResourceInAssemblyList(0, res) > NULL)
						percent = 100 * remainingRes / GetNeededResourceInAssemblyList(0, res);
					CResourceRoute* pResRoute = routes.GetAt(random).route;
					pResRoute->SetPercent((BYTE)percent);
					remainingRes = 0;
				}
				else
				{
					remainingRes -= systems.at(start.x+(start.y)*STARMAP_SECTORS_HCOUNT).GetResourceStore(res);
					if (GetNeededResourceInAssemblyList(0, res) > NULL)
						percent = 100 * systems.at(start.x+(start.y)*STARMAP_SECTORS_HCOUNT).GetResourceStore(res) / GetNeededResourceInAssemblyList(0, res);
					CResourceRoute* pResRoute = routes.GetAt(random).route;
					pResRoute->SetPercent((BYTE)percent);
					*systems.at(start.x+(start.y)*STARMAP_SECTORS_HCOUNT).GetResourceStorages(res) = NULL;
				}
				// ROUTELIST Eintrag entfernen, wenn dieser abgearbeitet wurde
				routes.RemoveAt(random);

				// werden keine Ressourcen mehr benötigt, so kann abgebrochen werden
				if (remainingRes == 0)
				{
					routes.RemoveAll();
					break;
				}
			}
			ASSERT(remainingRes == 0);
		}
		// anderenfalls werden nur die benötigten Ressourcen aus dem lokalen Lager abgezogen
		else
			*system->GetResourceStorages(res) -= GetNeededResourceInAssemblyList(0, res);
	}
	else
		*system->GetResourceStorages(res) -= m_iNeededDeritiumInAssemblyList[0];
}
Ejemplo n.º 26
0
void GenerateSimTables (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	ALERROR error;
	int i, j;

	int iSystemSample = pCmdLine->GetAttributeInteger(CONSTLIT("count"));
	if (iSystemSample == 0)
		iSystemSample = DEFAULT_SYSTEM_SAMPLE;

	//	Generate systems for multiple games

	CSymbolTable AllSystems(TRUE, TRUE);
	for (i = 0; i < iSystemSample; i++)
		{
		printf("sample %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.

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

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

			//	Add the encounters to the appropriate tables

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

				if (pObj)
					{
					//	Add this encounter to the table

					CStationType *pType;
					if (pType = pObj->GetEncounterInfo())
						{
						CString sKey = strFromInt(pType->GetUNID(), false);

						//	See if we have this type in the table

						StationInfo *pEntry;
						if (error = pSystemEntry->Stations.Lookup(sKey, (CObject **)&pEntry))
							{
							pEntry = new StationInfo;
							pEntry->pType = pType;
							pEntry->iSystemCount = 0;
							pEntry->iTotalCount = 1;

							pSystemEntry->Stations.AddEntry(sKey, pEntry);
							}
						else
							pEntry->iTotalCount++;
						}

					//	Enumerate the items in this object

					CItemListManipulator ItemList(pObj->GetItemList());
					ItemList.ResetCursor();
					while (ItemList.MoveCursorForward())
						{
						const CItem &Item(ItemList.GetItemAtCursor());

						if (!Item.IsInstalled() && !Item.IsDamaged())
							{
							CString sKey = strFromInt(Item.GetType()->GetUNID(), false);

							//	Find the item type in the table

							ItemInfo *pEntry;
							if (error = pSystemEntry->Items.Lookup(sKey, (CObject **)&pEntry))
								{
								pEntry = new ItemInfo;
								pEntry->pType = Item.GetType();
								pEntry->iTotalCount = Item.GetCount();

								pSystemEntry->Items.AddEntry(sKey, pEntry);
								}
							else
								pEntry->iTotalCount += Item.GetCount();
							}
						}
					}
				}

			//	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();
		}

	//	Output

	if (error = OutputItemTable(AllSystems, iSystemSample))
		return;

	if (error = OutputEncounterTable(AllSystems, iSystemSample))
		return;

	//	Create a table with the sum of all items for the game

	printf("Total count statistic computed.\n");
	}
Ejemplo n.º 27
0
void Run (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	ALERROR error;
	int i;
	CCodeChain &CC = g_pUniverse->GetCC();
	bool bNoLogo = pCmdLine->GetAttributeBool(NO_LOGO_SWITCH);

	//	Prepare the universe

	CTopologyNode *pNode = g_pUniverse->GetFirstTopologyNode();
	if (pNode == NULL)
		{
		printf("ERROR: No topology node found.\n");
		return;
		}

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

	//	Set the POV

	CSpaceObject *pPOV = pSystem->GetObject(0);
	g_pUniverse->SetPOV(pPOV);
	pSystem->SetPOVLRS(pPOV);

	//	Prepare system

	g_pUniverse->UpdateExtended();
	g_pUniverse->GarbageCollectLibraryBitmaps();

	CString sCommand = pCmdLine->GetAttribute(RUN_SWITCH);
	CString sRunFile = pCmdLine->GetAttribute(RUN_FILE_SWITCH);

	//	If this is a run file, then we parse it and run it

	if (!sRunFile.IsBlank() && !strEquals(sRunFile, CONSTLIT("true")))
		{
		TArray<CString> Files;
		ParseStringList(sRunFile, PSL_FLAG_ALLOW_WHITESPACE, &Files);
		for (i = 0; i < Files.GetCount(); i++)
			RunFile(Files[i], bNoLogo);
		}

	//	If we have a command, invoke it

	else if (!sCommand.IsBlank() && !strEquals(sCommand, CONSTLIT("True")))
		{
		CCodeChainCtx Ctx;
		ICCItem *pCode = Ctx.Link(sCommand, 0, NULL);
		ICCItem *pResult = Ctx.Run(pCode);

		CString sOutput;
		if (pResult->IsIdentifier())
			sOutput = pResult->Print(&CC, PRFLAG_NO_QUOTES | PRFLAG_ENCODE_FOR_DISPLAY);
		else
			sOutput = CC.Unlink(pResult);

		Ctx.Discard(pResult);
		Ctx.Discard(pCode);

		//	Output result

		printf("%s\n", sOutput.GetASCIIZPointer());
		}

	//	Otherwise, we enter a command loop

	else
		{
		//	Welcome

		if (!bNoLogo)
			{
			printf("(help) for function help.\n");
			printf("\\q to quit.\n\n");
			}

		//	Loop

		while (true)
			{
			char szBuffer[1024];
			if (!bNoLogo)
				printf(": ");
			gets_s(szBuffer, sizeof(szBuffer)-1);
			CString sCommand(szBuffer);

			//	Escape codes

			if (*sCommand.GetASCIIZPointer() == '\\')
				{
				//	Quit command

				if (strStartsWith(sCommand, CONSTLIT("\\q")))
					break;
				else if (strStartsWith(sCommand, CONSTLIT("\\?"))
						|| strStartsWith(sCommand, CONSTLIT("\\h")))
					{
					printf("TLisp Shell\n\n");
					printf("\\h      Show this help\n");
					printf("\\q      Quit\n");

					printf("\n(help) for function help.\n");
					}
				}

			//	Null command

			else if (sCommand.IsBlank())
				NULL;

			//	Command

			else
				{
				CCodeChainCtx Ctx;
				ICCItem *pCode = Ctx.Link(sCommand, 0, NULL);
				ICCItem *pResult = Ctx.Run(pCode);

				CString sOutput;
				if (pResult->IsIdentifier())
					sOutput = pResult->Print(&CC, PRFLAG_NO_QUOTES | PRFLAG_ENCODE_FOR_DISPLAY);
				else
					sOutput = CC.Unlink(pResult);

				Ctx.Discard(pResult);
				Ctx.Discard(pCode);

				//	Output result

				printf("%s\n", sOutput.GetASCIIZPointer());
				}
			}
		}
	}
Ejemplo n.º 28
0
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");
	}
Ejemplo n.º 29
0
void GenerateWeaponEffectChart (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	int i;

	//	Compute the list of weapons to show, making sure we filter to weapons
	//	and missiles only.

	CItemTypeTable Selection;
	if (!Selection.Filter(pCmdLine->GetAttribute(CRITERIA_ATTRIB))
			|| (Selection.IsAll() && !Selection.Filter(CONSTLIT("wm"))))
		{
		printf("No entries match criteria.\n");
		return;
		}

	Selection.Sort();

	//	Ship to use

	DWORD dwPlatformUNID;
	if (!pCmdLine->FindAttributeInteger(SHIP_UNID_ATTRIB, (int *)&dwPlatformUNID))
		dwPlatformUNID = WEAPON_PLATFORM_UNID;

	//	Compute some metrics

	int iFramesPerItem = 10;
	int cxFrameHorzMargin = 10;
	int cxMaxDistPerTick = (int)(STD_SECONDS_PER_UPDATE * (LIGHT_SECOND / g_KlicksPerPixel));
	int cyFrame = 64;
	int cxFrame = (2 * cxFrameHorzMargin) + (iFramesPerItem * cxMaxDistPerTick);

	int iHitEffectFramesPerItem = 5;
	int cxHitEffect = 128;
	int cyHitEffect = 128;
	
	int cyRowTitle = 20;
	int cyRow = cyRowTitle + Max(ITEM_ICON_HEIGHT, cyFrame * iFramesPerItem);
	int cxRow = ITEM_ICON_WIDTH + cxFrame;

	int iColumns = Max(1, mathSqrt(Selection.GetCount()));
	int iRows = (Selection.GetCount() + (iColumns - 1)) / iColumns;

	int cxImage = cxRow * iColumns;
	int cyImage = cyRow * iRows;

	//	Initialize the output

	COutputChart Output;
	Output.SetContentSize(cxImage, cyImage);
	Output.SetOutputFilespec(pCmdLine->GetAttribute(CONSTLIT("output")));

	//	Initialize fonts

	Output.SetStyleFont(STYLE_TITLE, pCmdLine->GetAttribute(CONSTLIT("font")));
	Output.SetStyleColor(STYLE_TITLE, CG32bitPixel(0xFF, 0xFF, 0xFF));

	//	Prepare the universe

	CSystem *pSystem;
	if (Universe.CreateEmptyStarSystem(&pSystem) != NOERROR)
		{
		printf("ERROR: Unable to create empty star system.\n");
		return;
		}

	//	Create a target in the center of the system

	CSpaceObject *pStation;
	CStationType *pTargetType = Universe.FindStationType(TARGET_UNID);
	if (pTargetType == NULL 
			|| pSystem->CreateStation(pTargetType, NULL, CVector(), &pStation) != NOERROR)
		{
		printf("ERROR: Unable to create station.\n");
		return;
		}

	//	Create the weapon platform some distance away

	CSovereign *pPlatformSovereign = Universe.FindSovereign(PLAYER_SOVEREIGN_UNID);
	CShip *pPlatform;
	if (pPlatformSovereign == NULL
				|| pSystem->CreateShip(dwPlatformUNID,
					NULL,
					NULL,
					pPlatformSovereign,
					CVector(-5.0 * LIGHT_SECOND, 0.),
					CVector(),
					0,
					NULL,
					NULL,
					&pPlatform) != NOERROR)
		{
		printf("ERROR: Unable to create weapons platform.\n");
		return;
		}

	//	Set the attacker to hold

	IShipController *pController = pPlatform->GetController();
	if (pController == NULL)
		{
		printf("ERROR: No controller for ship.\n");
		return;
		}

	pController->AddOrder(IShipController::orderHold, NULL, IShipController::SData());
	pPlatform->SetControllerEnabled(false);

	//	Install the largest possible reactor on the ship

	CItemType *pReactorType = Universe.FindItemType(REACTOR_UNID);
	if (pReactorType)
		{
		CItem ReactorItem(pReactorType, 1);

		CItemListManipulator ItemList(pPlatform->GetItemList());
		ItemList.AddItem(ReactorItem);
		pPlatform->OnComponentChanged(comCargo);
		pPlatform->ItemsModified();
		pPlatform->InvalidateItemListAddRemove();

		pPlatform->InstallItemAsDevice(ItemList);
		}

	//	Set the POV

	Universe.SetPOV(pStation);
	pSystem->SetPOVLRS(pStation);

	//	Prepare system

	Universe.UpdateExtended();
	Universe.GarbageCollectLibraryBitmaps();
	Universe.StartGame(true);

	//	Output each weapon

	int xOrigin;
	int yOrigin;
	CG32bitImage &Image = Output.GetOutputImage(&xOrigin, &yOrigin);
	const CG16bitFont &TitleFont = Output.GetStyleFont(STYLE_TITLE);
	CG32bitPixel rgbTitleColor = Output.GetStyleColor(STYLE_TITLE);

	for (i = 0; i < Selection.GetCount(); i++)
		{
		CItemType *pType = Selection.GetItemType(i);

		//	Compute the metrics of this row

		int xRow = xOrigin + (i % iColumns) * cxRow;
		int yRow = yOrigin + (i / iColumns) * cyRow;

		//	Paint the weapon title

		Image.Fill(xRow, yRow, cxRow, cyRow, CG32bitPixel(0x40, 0x40, 0x40));
		TitleFont.DrawText(Image, xRow + 8, yRow, rgbTitleColor, pType->GetNounPhrase());

		//	Paint the frames

		PaintWeaponFrames(Image, pType, pPlatform, iFramesPerItem, 
				xRow + ITEM_ICON_WIDTH + cxFrameHorzMargin,
				yRow + cyRowTitle, 
				cxMaxDistPerTick,
				cyFrame);
		}

	//	Done

	Output.Output();
	}
Ejemplo n.º 30
0
void GenerateSnapshot (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	ALERROR error;
	int i;

	//	Get some parameters

	int iInitialUpdateTime = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("initialUpdate"), 0, -1, 10);
	int iUpdateTime = pCmdLine->GetAttributeInteger(CONSTLIT("wait"));
	bool bObjOnly = pCmdLine->GetAttributeBool(CONSTLIT("objOnly"));

	//	Criteria

	CString sNode = pCmdLine->GetAttribute(CONSTLIT("node"));
	CString sCriteria = pCmdLine->GetAttribute(CONSTLIT("criteria"));

	//	Number of snapshots

	int iTotalCount = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1);

	//	Output

	int cxWidth;
	int cyHeight;
	if (pCmdLine->FindAttributeInteger(CONSTLIT("size"), &cxWidth))
		{
		cyHeight = cxWidth;
		}
	else
		{
		cxWidth = 1024;
		cyHeight = 1024;
		}

	//	Paint flags

	DWORD dwPaintFlags = 0;
	if (pCmdLine->GetAttributeBool(CONSTLIT("noStars")))
		dwPaintFlags |= CSystem::VWP_NO_STAR_FIELD;

	//	Output file

	CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output"));
	if (!sFilespec.IsBlank())
		sFilespec = pathStripExtension(sFilespec);

	//	Output image

	CG32bitImage Output;
	Output.Create(cxWidth, cyHeight);

	//	Update context

	SSystemUpdateCtx Ctx;
	Ctx.bForceEventFiring = true;
	Ctx.bForcePainted = true;

	RECT rcViewport;
	rcViewport.left = 0;
	rcViewport.top = 0;
	rcViewport.right = cxWidth;
	rcViewport.bottom = cyHeight;

	//	Loop over all systems until we find what we're looking for

	int iLoops = 20;
	int iNodeIndex = 0;
	int iSnapshotIndex = 0;
	CTopologyNode *pNode = Universe.GetTopologyNode(iNodeIndex);
	while (true)
		{
		//	Create the system

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

		//	If this is the node we want, then search

		CSpaceObject *pTarget;
		if (sNode.IsBlank() || strEquals(sNode, pNode->GetID()))
			{
			printf("Searching %s...\n", pNode->GetSystemName().GetASCIIZPointer());

			//	Set the POV

			CSpaceObject *pPOV = pSystem->GetObject(0);
			Universe.SetPOV(pPOV);
			pSystem->SetPOVLRS(pPOV);

			//	Prepare system

			Universe.UpdateExtended();
			Universe.GarbageCollectLibraryBitmaps();

			//	Update for a while

			for (i = 0; i < iInitialUpdateTime; i++)
				{
				Universe.Update(Ctx);
				Universe.PaintPOV(Output, rcViewport, 0);
				}

			//	Compose the criteria

			CSpaceObject::Criteria Criteria;
			CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria);

			//	Get the list of all objects in the system that match the criteria

			CSpaceObject::SCriteriaMatchCtx Ctx(Criteria);
			TArray<CSpaceObject *> Results;
			for (i = 0; i < pSystem->GetObjectCount(); i++)
				{
				CSpaceObject *pObj = pSystem->GetObject(i);
				if (pObj && pObj->MatchesCriteria(Ctx, Criteria))
					Results.Insert(pObj);
				}

			//	Pick the appropriate object from the list

			if (Results.GetCount() == 0)
				pTarget = NULL;
			else if (Criteria.bNearestOnly || Criteria.bFarthestOnly)
				pTarget = Ctx.pBestObj;
			else
				pTarget = Results[mathRandom(0, Results.GetCount() - 1)];
			}
		else
			pTarget = NULL;

		//	If we found the target, then output

		if (pTarget)
			{
			Universe.SetPOV(pTarget);

			//	Wait a bit
			//
			//	NOTE: After we update, pTarget could be invalid (i.e., destroyed)
			//	so we can't use it again.

			CString sTargetName = pTarget->GetNounPhrase(0);

			for (i = 0; i < iUpdateTime; i++)
				{
				if ((i % 100) == 99)
					printf(".");

				Universe.Update(Ctx);
				Universe.PaintPOV(Output, rcViewport, 0);
				}

			if (iUpdateTime >= 99)
				printf("\n");

			//	Paint

			if (bObjOnly)
				{
				SViewportPaintCtx Ctx;
				Ctx.pObj = Universe.GetPOV();
				Ctx.XForm = ViewportTransform(Universe.GetPOV()->GetPos(), 
						g_KlicksPerPixel, 
						cxWidth / 2, 
						cyHeight / 2);
				Ctx.XFormRel = Ctx.XForm;
				Ctx.fNoRecon = true;
				Ctx.fNoDockedShips = true;
				Ctx.fNoSelection = true;
				Ctx.fNoStarfield = true;

				CSpaceObject *pPOV = pSystem->GetObject(0);
				CSpaceObject::Criteria Criteria;
				CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria);

				//	Paint all objects that match the criteria

				CSpaceObject::SCriteriaMatchCtx CriteriaCtx(Criteria);
				for (i = 0; i < pSystem->GetObjectCount(); i++)
					{
					CSpaceObject *pObj = pSystem->GetObject(i);
					if (pObj && pObj->MatchesCriteria(CriteriaCtx, Criteria))
						{
						Ctx.pObj = pObj;
						int xObj;
						int yObj;
						Ctx.XForm.Transform(pObj->GetPos(), &xObj, &yObj);

						pObj->Paint(Output, xObj, yObj, Ctx);
						}
					}
				}
			else
				{
			
				Universe.PaintPOV(Output, rcViewport, 0);
				}

			//	Write to file

			if (!sFilespec.IsBlank())
				{
				CString sBmpFilespec;
				if (iTotalCount > 100)
					sBmpFilespec = pathAddExtensionIfNecessary(strPatternSubst(CONSTLIT("%s%03d"), sFilespec, iSnapshotIndex + 1), CONSTLIT(".bmp"));
				else if (iTotalCount > 1)
					sBmpFilespec = pathAddExtensionIfNecessary(strPatternSubst(CONSTLIT("%s%02d"), sFilespec, iSnapshotIndex + 1), CONSTLIT(".bmp"));
				else
					sBmpFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp"));

				CFileWriteStream OutputFile(sBmpFilespec);
				if (OutputFile.Create() != NOERROR)
					{
					printf("ERROR: Unable to create '%s'\n", sBmpFilespec.GetASCIIZPointer());
					return;
					}

				Output.WriteToWindowsBMP(&OutputFile);
				OutputFile.Close();
				printf("Found %s: Saved to %s\n", sTargetName.GetASCIIZPointer(), sBmpFilespec.GetASCIIZPointer());
				}

			//	Otherwise, clipboard

			else
				{
				if (error = Output.CopyToClipboard())
					{
					printf("ERROR: Unable to copy image to clipboard.\n");
					return;
					}

				printf("Found %s: Copied to clipboard.\n", sTargetName.GetASCIIZPointer());
				}

			//	Reset maximum loops

			iLoops = 20;

			//	Done

			iSnapshotIndex++;
			if (iSnapshotIndex >= iTotalCount)
				break;
			}

		//	Done with old system

		Universe.DestroySystem(pSystem);

		//	Loop to the next node

		do
			{
			iNodeIndex = ((iNodeIndex + 1) % Universe.GetTopologyNodeCount());
			pNode = Universe.GetTopologyNode(iNodeIndex);
			}
		while (pNode == NULL || pNode->IsEndGame());

		//	If we're back to the first node again, restart

		if (iNodeIndex == 0)
			{
			if (--iLoops > 0)
				{
				//	Reinitialize

				Universe.Reinit();
				CString sError;
				if (Universe.InitGame(0, &sError) != NOERROR)
					{
					printf("ERROR: %s\n", sError.GetASCIIZPointer());
					return;
					}

				iNodeIndex = 0;
				pNode = Universe.GetTopologyNode(iNodeIndex);
				}
			else
				{
				printf("ERROR: Specified target could not be found.\n");
				return;
				}
			}
		}
	}