////////////////////////////////////////////////////////////////////// // sonstige Funktionen ////////////////////////////////////////////////////////////////////// /// Diese Funktion erteilt allen Schiffen aller computergesteuerten Rassen Befehle. void CShipAI::CalculateShipOrders(CSectorAI* SectorAI) { ASSERT(SectorAI); m_pSectorAI = SectorAI; // einen möglichen Angriffssektor berechnen lassen CalcAttackSector(); // danach einen möglichen Bombardierungssektor finden CalcBombardSector(); for(CShipMap::iterator i = m_pDoc->m_ShipMap.begin(); i != m_pDoc->m_ShipMap.end(); ++i) { if(i->second->IsAlien()) { CalculateAlienShipOrders(*i->second); continue; } const CString& sOwner = i->second->GetOwnerOfShip(); CMajor* pOwner = dynamic_cast<CMajor*>(m_pDoc->GetRaceCtrl()->GetRace(sOwner)); // gilt erstmal nur für Majors if (!pOwner || !pOwner->IsMajor()) continue; // gilt nicht für menschliche Spieler if (pOwner->AHumanPlays()) continue; // Flotte versuchen zu erstellen DoMakeFleet(i); // Vielleicht haben unsere Schiffe ein Ziel, welches sie angreifen müssen/können if (DoAttackMove(i->second, pOwner)) { DoCamouflage(i->second); continue; } // haben Kolonieschiffe einen Sektor zum Terraformen als Ziel, welcher kurz zuvor aber von einer // anderen Rasse weggeschnappt wurde, so wird ihr Kurs gelöscht if (i->second->GetShipType() == SHIP_TYPE::COLONYSHIP) { CPoint ptKO = i->second->GetKO(); // hat das Kolonieschiff den Befehl zum Terraformen, so wird dieser rückgängig gemacht, wenn der Sektor // schon einer anderen Rasse gehört if (i->second->GetCurrentOrder() == SHIP_ORDER::TERRAFORM) { if (m_pDoc->GetSector(ptKO.x, ptKO.y).GetOwnerOfSector() != "" && m_pDoc->GetSector(ptKO.x, ptKO.y).GetOwnerOfSector() != sOwner) { // Terraforming abbrechen i->second->UnsetCurrentOrder(); i->second->SetCombatTactic(COMBAT_TACTIC::CT_AVOID); } } CPoint ptTarget = i->second->GetTargetKO(); // nur wenn der Sektor noch niemandem gehört bzw. uns selbst ist, sollen Planeten terraformt werden if (ptTarget != CPoint(-1,-1) && m_pDoc->GetSector(ptTarget.x, ptTarget.y).GetOwnerOfSector() != "" && m_pDoc->GetSector(ptTarget.x, ptTarget.y).GetOwnerOfSector() != sOwner) { // nicht weiter fliegen und Kurs löschen i->second->SetTargetKO(CPoint(-1, -1)); i->second->GetPath()->RemoveAll(); } } // exisitiert kein aktueller Kurs, so wird dieser hier versucht dem Schiff zu erteilen if (i->second->GetPath()->GetSize() == 0) { // Scouts und Kriegsschiffe fliegen zuerst einmal zu den Minorracesystemen if (i->second->GetShipType() > SHIP_TYPE::COLONYSHIP) { // Zeiger auf Vektor mit Minorracessektoren holen vector<CPoint>* vMinorraceSectors = m_pSectorAI->GetMinorraceSectors(sOwner); bool bSet = false; int nCount = vMinorraceSectors->size() * 2; while (vMinorraceSectors->size() && nCount--) { int j = rand()%vMinorraceSectors->size(); CPoint ko = vMinorraceSectors->at(j); // Wenn Gefahr der anderen Rassen kleiner als die der meinen ist if (m_pSectorAI->GetCompleteDanger(sOwner, ko) == NULL || (m_pSectorAI->GetCompleteDanger(sOwner, ko) <= m_pSectorAI->GetDangerOnlyFromCombatShips(sOwner, i->second->GetKO()))) if (pOwner->GetStarmap()->GetRange(ko) <= i->second->GetRange(false)) { // Zielkoordinate für das Schiff setzen i->second->SetTargetKO(ko); MYTRACE("shipai")(MT::LEVEL_DEBUG, "Race %s: Ship to Minor: %s (%s) - Target: %d,%d\n",sOwner, i->second->GetShipName(), i->second->GetShipTypeAsString(), ko.x,ko.y); vMinorraceSectors->erase(vMinorraceSectors->begin() + j--); bSet = true; break; } } if (bSet) { DoCamouflage(i->second); continue; } } // Kolonieschiffe zum Terraformen schicken. Andere Schiffe fliegen manchmal auch dort hin, wenn // sie gerade keinen anderen Flugauftrag haben. if (i->second->GetShipType() >= SHIP_TYPE::COLONYSHIP && i->second->GetCurrentOrder() != SHIP_ORDER::TERRAFORM) { // Zeiger auf Vektor mit Terraformsektoren holen vector<CSectorAI::SectorToTerraform>* vSectorsToTerrform = m_pSectorAI->GetSectorsToTerraform(sOwner); for (UINT j = 0; j < vSectorsToTerrform->size(); j++) { CPoint ko = vSectorsToTerrform->at(j).p; // Wenn das Kolonieschiff schon auf einem Sektor für unser Terraforming steht, so fliegt es nicht weiter if (i->second->GetShipType() == SHIP_TYPE::COLONYSHIP && i->second->GetKO() == ko) break; // Wenn Gefahr der anderen Rassen kleiner als die der meinen ist if (m_pSectorAI->GetCompleteDanger(sOwner, ko) == NULL || (m_pSectorAI->GetCompleteDanger(sOwner, ko) < m_pSectorAI->GetDanger(sOwner, i->second->GetKO()))) { if (pOwner->GetStarmap()->GetRange(ko) <= i->second->GetRange(false)) { // Zielkoordinate für das Schiff setzen i->second->SetTargetKO(ko == i->second->GetKO() ? CPoint(-1, -1) : ko); MYTRACE("shipai")(MT::LEVEL_DEBUG, "Race %s: Ship %s (%s) has terraforming target: %d,%d\n",sOwner, i->second->GetShipName(), i->second->GetShipTypeAsString(), ko.x,ko.y); break; } } } } // Truppentransporter zu einem möglichen Sektor fliegen lassen um dort einen Außenposten bauen zu können if (m_pSectorAI->GetStationBuildSector(sOwner).points > MINBASEPOINTS && i->second->GetCurrentOrder() != SHIP_ORDER::BUILD_OUTPOST) { // nur Truppentransporter oder andere Schiffe ohne Ziel fliegen zu diesem Punkt, niemals aber // Kolonieschiffe if (i->second->GetShipType() == SHIP_TYPE::TRANSPORTER || (i->second->GetShipType() != SHIP_TYPE::COLONYSHIP && !i->second->HasTarget())) { CPoint ko(m_pSectorAI->GetStationBuildSector(sOwner).position.x, m_pSectorAI->GetStationBuildSector(sOwner).position.y); // Wenn Gefahr der anderen Rassen kleiner als die der meinen ist if (m_pSectorAI->GetCompleteDanger(sOwner, ko) == 0 || (m_pSectorAI->GetCompleteDanger(sOwner, ko) < m_pSectorAI->GetDanger(sOwner, i->second->GetKO()))) { if (pOwner->GetStarmap()->GetRange(ko) <= i->second->GetRange(false)) { // Zielkoordinate für das Schiff setzen i->second->SetTargetKO(ko == i->second->GetKO() ? CPoint(-1, -1) : ko); MYTRACE("shipai")(MT::LEVEL_DEBUG, "Race %s: Ship %s (%s) has stationbuild target: %d,%d\n",sOwner, i->second->GetShipName(), i->second->GetShipTypeAsString(), ko.x,ko.y); } } } } DoCamouflage(i->second); if (m_pDoc->GetSector(i->second->GetKO().x, i->second->GetKO().y).GetSunSystem()) { if (!DoTerraform(i->second)) DoColonize(i->second); } DoStationBuild(i->second); } else { DoCamouflage(i->second); } } }
void CResearchAI::Calc(CBotEDoc* pDoc) { ASSERT(pDoc); // Forschungsdurchschnitt aller Rassen berechnen map<CString, CMajor*>* pmMajors = pDoc->GetRaceCtrl()->GetMajors(); ASSERT(pmMajors); // Map mit zum Major zugehörigen Techlevel map<CMajor*, double> mTechLevels; list<double> lTechLevels; for (map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) { CMajor* pMajor = it->second; // für menschliche Spieler wird die KI nichts tun if (!pMajor || pMajor->AHumanPlays()) continue; double dTechLevel = pMajor->GetEmpire()->GetResearch()->GetBioTech() + pMajor->GetEmpire()->GetResearch()->GetEnergyTech() + pMajor->GetEmpire()->GetResearch()->GetCompTech() + pMajor->GetEmpire()->GetResearch()->GetPropulsionTech() + pMajor->GetEmpire()->GetResearch()->GetConstructionTech() + pMajor->GetEmpire()->GetResearch()->GetWeaponTech(); dTechLevel /= 6.0; lTechLevels.push_back(dTechLevel); // Hat die Rasse überhaupt eine Spezialforschung zur Auswahl? (auf FALSE prüfen!) if (!pMajor->GetEmpire()->GetResearch()->GetUniqueReady()) // Hat die Rasse noch keinen Bereich gewählt? if (pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetChoiceTaken() == false) mTechLevels[pMajor] = dTechLevel; } // absteigend sortieren lTechLevels.sort(); lTechLevels.reverse(); // auf die besten zwei begrenzen lTechLevels.resize(2); // nur die Majors mit dem besten oder zweitbesten Techlevel versuchen eine Spezialforschung // zu beginnen. Dies machen sie aber nur, wenn sie mindestens eine Techstufe weiter sind, als // sie für die Spezialforschung benötigt haben for (list<double>::const_iterator it = lTechLevels.begin(); it != lTechLevels.end(); ++it) { // Major mit diesem Techlevel suchen for (map<CMajor*, double>::const_iterator it2 = mTechLevels.begin(); it2 != mTechLevels.end(); ++it2) { if (*it == it2->second) { CMajor* pMajor = it2->first; if (pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetChoiceTaken()) break; BYTE nUniqueTech = pMajor->GetEmpire()->GetResearch()->GetUniqueTech() + 1; // Prüfen ob die Rasse schon ein Level weiter ist, als das was sie für die Spezialforschung braucht if (nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetBioTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetEnergyTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetCompTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetConstructionTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetPropulsionTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetWeaponTech()) { // zufällig einen Bereich wählen (1 bis 3) int nComplex = rand()%3 + 1; pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->SetUniqueResearchChoosePossibility(nComplex); // 100% zuteilen pMajor->GetEmpire()->GetResearch()->SetPercentage(6, 100); CString sName = pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetCurrentResearchComplex()->GetComplexName(); MYTRACE("general")(MT::LEVEL_INFO, "CResearchAI::Calc(): %s choose in unique complex '%s' field %d and set level to 100%%\n", pMajor->GetRaceID(), sName, nComplex); } } } } }