Пример #1
0
//////////////////////////////////////////////////////////////////////
// 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);
		}
	}
}
Пример #2
0
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);
				}
			}
		}
	}
}