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