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