/// Funktion überprüft ob das in der Designansicht angeklickte Schiff in einem unserer Systeme gerade gebaut wird /// Man benötigt diesen Check da man keine Schiffe ändern kann, welche gerade gebaut werden. /// @param pShipInfo Zeiger des zu prüfenden Schiffes aus der Schiffsliste /// @return CString mit dem Namen des Systems, wird das Schiff nirgends gebaut ist der String leer CString CShipDesignMenuView::CheckIfShipIsBuilding(const CShipInfo* pShipInfo) const { if (!pShipInfo) return ""; CBotEDoc* pDoc = resources::pDoc; ASSERT(pDoc); CMajor* pMajor = m_pPlayersRace; ASSERT(pMajor); if (!pMajor) return ""; USHORT ID = pShipInfo->GetID(); // alle eigenen Systeme durchgehen und schauen, ob an erster Stelle in der Bauliste so ein Schiff steht for (int y = 0; y < STARMAP_SECTORS_VCOUNT; y++) for (int x = 0; x < STARMAP_SECTORS_HCOUNT; x++) if (pDoc->GetSystem(x,y).GetOwnerOfSystem() == pMajor->GetRaceID()) for (int i = 0; i < ALE; i++) if (pDoc->GetSystem(x,y).GetAssemblyList()->GetAssemblyListEntry(i) == ID) return pDoc->GetSector(x,y).GetName(); return ""; }
void CIntelBottomView::OnDraw(CDC* dc) { CBotEDoc* pDoc = resources::pDoc; AssertBotE(pDoc); if (!pDoc->m_bDataReceived) return; CMajor* pMajor = m_pPlayersRace; AssertBotE(pMajor); if (!pMajor) return; // TODO: add draw code here // Doublebuffering wird initialisiert CMyMemDC pDC(dc); CRect client; GetClientRect(&client); // Graphicsobjekt, in welches gezeichnet wird anlegen Graphics g(pDC->GetSafeHdc()); g.Clear(static_cast<Gdiplus::ARGB>(Color::Black)); g.SetSmoothingMode(SmoothingModeHighSpeed); g.SetInterpolationMode(InterpolationModeLowQuality); g.SetPixelOffsetMode(PixelOffsetModeHighSpeed); g.SetCompositingQuality(CompositingQualityHighSpeed); g.ScaleTransform((REAL)client.Width() / (REAL)m_TotalSize.cx, (REAL)client.Height() / (REAL)m_TotalSize.cy); CString fontName = ""; Gdiplus::REAL fontSize = 0.0; StringFormat fontFormat; SolidBrush fontBrush(static_cast<Gdiplus::ARGB>(Color::White)); Color color; color.SetFromCOLORREF(pMajor->GetDesign()->m_clrGalaxySectorText); fontBrush.SetColor(color); Bitmap* graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Backgrounds\\" + pMajor->GetPrefix() + "diplomacyV3.boj"); // Grafik zeichnen if (graphic) { g.DrawImage(graphic, 0, 0, 1075, 249); graphic = NULL; } // Nur in bestimmten Submenüs werden in der View3 Berichte angezeigt BYTE curIntelSubMenu = resources::pMainFrame->GetSubMenu(RUNTIME_CLASS(CIntelMenuView)); if (curIntelSubMenu == 4 || curIntelSubMenu == 5) { CRect r; r.SetRect(0,0,m_TotalSize.cx,m_TotalSize.cy); short n = pMajor->GetEmpire()->GetIntelligence()->GetIntelReports()->GetActiveReport(); if (n != -1) { CFontLoader::CreateGDIFont(pMajor, 4, fontName, fontSize); fontFormat.SetAlignment(StringAlignmentNear); fontFormat.SetLineAlignment(StringAlignmentNear); fontFormat.SetFormatFlags(StringFormatFlagsNoWrap); CIntelObject* report = pMajor->GetEmpire()->GetIntelligence()->GetIntelReports()->GetReport(n); CString s; if (report->GetIsSpy()) s = CLoc::GetString("SPY"); else s = CLoc::GetString("SABOTAGE"); g.DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40, 40, r.right-100, r.bottom-20), &fontFormat, &fontBrush); CFontLoader::CreateGDIFont(pMajor, 2, fontName, fontSize); fontBrush.SetColor(Color(200,200,250)); fontFormat.SetFormatFlags(!StringFormatFlagsNoWrap); if (report->GetOwner() == pMajor->GetRaceID()) s = *report->GetOwnerDesc(); else s = *report->GetEnemyDesc(); g.DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40, 100, r.right-250, r.bottom-20), &fontFormat, &fontBrush); } } g.ReleaseHDC(pDC->GetSafeHdc()); }
void CRandomEventCtrl::CalcShipEvents() const { if (!IsActivated()) return; CBotEDoc* pDoc = resources::pDoc; AssertBotE(pDoc); // Hüllenvirus for (int x = 0; x < STARMAP_SECTORS_HCOUNT; x++) { for (int y = 0; y < STARMAP_SECTORS_VCOUNT; y++) { // 0.1% Wahrscheinlichkeit für einen Hüllenvirus pro Sektor if (rand()%1000 != 0) continue; // gibt es keine Schiffe im Sektor, dann macht ein Hüllenvirus auch nichts CSector* pSector = &(pDoc->GetSystem(x, y)); if (!pSector->GetIsShipInSector()) continue; // allen Schiffe im Sektor die Hülle auf 1 reduzieren (außer Aliens) for (CShipMap::iterator i = pDoc->m_ShipMap.begin(); i != pDoc->m_ShipMap.end(); ++i) { if (i->second->IsAlien()) continue; if (i->second->GetCo() != pSector->GetCo()) continue; int nCurrentHull = i->second->GetHull()->GetCurrentHull(); i->second->GetHull()->SetCurrentHull(-(nCurrentHull - 1), true); // allen Schiffen in der Flotte ebenfalls die Hülle auf 1 setzen for (CShips::iterator j = i->second->begin(); j != i->second->end(); ++j) { nCurrentHull = j->second->GetHull()->GetCurrentHull(); j->second->GetHull()->SetCurrentHull(-(nCurrentHull - 1), true); } } // Nachrichten an alle Major welche Schiffe in diesem Sektor hatten const std::map<CString, CMajor*>* pmMajors = pDoc->GetRaceCtrl()->GetMajors(); for (map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) { if (!pSector->GetOwnerOfShip(it->first, true)) continue; CMajor* pMajor = it->second; if (!pMajor) continue; const CString& sSectorName = pSector->CoordsName(true); CString sMessageText = CLoc::GetString("EVENTHULLVIRUS", false, sSectorName); CEmpireNews message; message.CreateNews(sMessageText,EMPIRE_NEWS_TYPE::MILITARY,pSector->GetName(),pSector->GetCo()); pMajor->GetEmpire()->AddMsg(message); if (pMajor->IsHumanPlayer()) { resources::pClientWorker->SetToEmpireViewFor(*pMajor); pMajor->GetEmpire()->PushEvent(boost::make_shared<CEventRandom>(pMajor->GetRaceID(), "HullVirus", sMessageText, "")); } } } } }
////////////////////////////////////////////////////////////////////// // sonstige Funktionen ////////////////////////////////////////////////////////////////////// /// Funktion berechnet den Umgang mit dem Geheimdienst für die KI. Sie trifft Zuteilungen für die einzelnen Rassen. void CIntelAI::CalcIntelligence(CBotEDoc* pDoc) { AssertBotE(pDoc); // Struktur für eine Liste mit Rassen-ID und Geheimdienstpunkten struct INTELLIST { CString sRace; UINT points; bool operator< (const INTELLIST& elem2) const { return points < elem2.points;} bool operator> (const INTELLIST& elem2) const { return points > elem2.points;} INTELLIST() : sRace(""), points(0) {} INTELLIST(const CString& _sRace, UINT _points) : sRace(_sRace), points(_points) {} }; // produzierte Geheimdienstpunkte und Punkte aus allen Geheimdienstlagern einer Rasse zusammenaddieren CArray<INTELLIST> intellist; std::map<CString, CMajor*>* pmMajors = pDoc->GetRaceCtrl()->GetMajors(); for (std::map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) { CIntelligence* pIntel = it->second->GetEmpire()->GetIntelligence(); UINT points = pIntel->GetSecurityPoints() + pIntel->GetInnerSecurityStorage(); for (map<CString, CMajor*>::const_iterator itt = pmMajors->begin(); itt != pmMajors->end(); ++itt) if (itt->first != it->first) points += pIntel->GetSPStorage(0, itt->first) + pIntel->GetSPStorage(1, itt->first); intellist.Add(INTELLIST(it->first, points)); } // nun Feld nach den gesammten Geheimdienstpunkten absteigend sortiren lassen. c_arraysort<CArray<INTELLIST>, INTELLIST> (intellist, sort_desc); // unere Priorität ist der Index der Rasse im Feld. // wenn die Punkte sich nicht mehr als 10% bzw. 100SP unterscheiden, dann wird die Priorität des vorherigen // Indexes benutzt. m_byIntelPrio[intellist.GetAt(0).sRace] = rand()%2; for (int i = 1; i < intellist.GetSize(); i++) // beim zweiten Index starten! Da das erste Element eine 0er Priorität hat { if (intellist.GetAt(i-1).points - intellist.GetAt(i).points > 100 && (intellist.GetAt(i).points * 100 / (intellist.GetAt(i-1).points+1) < 90)) m_byIntelPrio[intellist.GetAt(i).sRace] = i; // ansonsten ist die Priorität der des Vorgängers else m_byIntelPrio[intellist.GetAt(i).sRace] = m_byIntelPrio[intellist.GetAt(i-1).sRace]; } // jeder Geheimdienstbericht mit uns als Ziel aus den letzten 5 Runden erhöht die Priorität nochmal um eins, sofern // es sich dabei um eine Sabotageaktion handelte std::map<CString, int> badReports; for (std::map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) if (it->second->AHumanPlays() == false) { CIntelligence* pIntel = it->second->GetEmpire()->GetIntelligence(); for (int l = 0; l < pIntel->GetIntelReports()->GetNumberOfReports(); l++) { CIntelObject* intelObj = pIntel->GetIntelReports()->GetReport(l); if (intelObj->GetEnemy() == it->first && pDoc->GetCurrentRound() - intelObj->GetRound() < 6 && intelObj->GetIsSabotage()) badReports[it->first] += 1; } m_byIntelPrio[it->first] += badReports[it->first]; } for (std::map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) MYTRACE("intelai")(MT::LEVEL_INFO, "Intel-AI: Intel Prio of %s is %d\n", it->first, m_byIntelPrio[it->first]); // nun liegen die Prioritäten und die Listen mit den Punkten vor. Jetzt kann begonnen werde die Rassen zu // vergeheimdiensteln. Ab hier kommt die KI für den Geheimdienst richtig ins Spiel. for (std::map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) { if (it->second->AHumanPlays() == false) { CIntelligence* pIntel = it->second->GetEmpire()->GetIntelligence(); // wenn in den letzten 5 Runden Geheimdienstberichte mit uns als Ziel vorliegen, so wird die innere // Sicherheit maximiert if (badReports[it->first] > NULL) { // Es liegt mindst. ein Bericht mit uns als Ziel aus den letzten 5 Runden vor. // Dann wird die Innere Sicherheit auf 100% gesetzt pIntel->SetAssignment()->SetGlobalPercentage(2, 100, it->second, "", pmMajors); continue; } // wenn die innere Sicherheit nicht verändert werden musste, dann können wir vielleicht selbst aktiv werden // KI benutzt nur Sabotage // Wie wird ein mögliches Geheimdienstopfer ermittelt? // - haben die schlechteste Beziehung zum Opfer // - Beziehung unter 50% oder aktueller Vertrag kleiner Freundschaft und kein Verteidigungsbündnis USHORT worstRel = MAXBYTE; CMajor* pWorstRace = NULL; for (std::map<CString, CMajor*>::const_iterator jt = pmMajors->begin(); jt != pmMajors->end(); ++jt) if (jt->first != it->first && it->second->IsRaceContacted(jt->first) == true) { // zufällig wird hier eine bekannte andere Rasse als ResponsibleRace ausgewählt pIntel->SetResponsibleRace(it->first); // erstmal uns wieder auf die ResponsibleRace setzen if (jt->second->GetEmpire()->CountSystems() > 0 && rand()%3 == NULL) { pIntel->SetResponsibleRace(jt->first); break; } // vertragliche Situation und Mindestbeziehung checken if ((it->second->GetAgreement(jt->first) < DIPLOMATIC_AGREEMENT::FRIENDSHIP && it->second->GetDefencePact(jt->first) == false) || it->second->GetRelation(jt->first) < 50) { // schlechteste Beziehung ermitteln if (it->second->GetRelation(jt->first) < worstRel) { worstRel = it->second->GetRelation(jt->first); pWorstRace = jt->second; } // bei Gleichheit zu 50% die neue Rasse mit schlechtester Bezeihung else if (it->second->GetRelation(jt->first) == worstRel && rand()%2 == NULL) { worstRel = it->second->GetRelation(jt->first); pWorstRace = jt->second; } } } // jetzt der ausgesuchten Rasse Geheimdienstpunkte zuweisen if (pWorstRace != NULL) { CIntelligence* pWorstIntel = pWorstRace->GetEmpire()->GetIntelligence(); MYTRACE("intelai")(MT::LEVEL_INFO, "Intel-AI: assigned intel victim of %s is %s\n", it->first, pWorstRace->GetRaceID()); // jede Rasse läßt immer einen bestimmten prozentualen Anteil in der inneren Sicherheit. int innerSecPerc = 25; if (it->second->IsRaceProperty(RACE_PROPERTY::FINANCIAL)) innerSecPerc += 15; if (it->second->IsRaceProperty(RACE_PROPERTY::WARLIKE)) innerSecPerc += 25; if (it->second->IsRaceProperty(RACE_PROPERTY::AGRARIAN)) innerSecPerc += 25; if (it->second->IsRaceProperty(RACE_PROPERTY::INDUSTRIAL)) innerSecPerc += 10; if (it->second->IsRaceProperty(RACE_PROPERTY::SECRET)) innerSecPerc -= 10; if (it->second->IsRaceProperty(RACE_PROPERTY::SCIENTIFIC)) innerSecPerc += 0; if (it->second->IsRaceProperty(RACE_PROPERTY::PRODUCER)) innerSecPerc += 5; if (it->second->IsRaceProperty(RACE_PROPERTY::PACIFIST)) innerSecPerc += 35; if (it->second->IsRaceProperty(RACE_PROPERTY::SNEAKY)) innerSecPerc -= 15; if (it->second->IsRaceProperty(RACE_PROPERTY::SOLOING)) innerSecPerc += 40; if (it->second->IsRaceProperty(RACE_PROPERTY::HOSTILE)) innerSecPerc += 0; if (innerSecPerc > 100) innerSecPerc = 100; else if (innerSecPerc < 0) innerSecPerc = 0; if (pIntel->GetAssignment()->GetGlobalSabotagePercentage(pWorstRace->GetRaceID()) != 100 - innerSecPerc) pIntel->SetAssignment()->SetGlobalPercentage(2, 100, it->second, "", pmMajors); pIntel->SetAssignment()->SetGlobalPercentage(1, 100 - innerSecPerc, it->second, pWorstRace->GetRaceID(), pmMajors); // Wann wird die Geheimdiensaktion gestartet // - wenn unsere Geheimdienstpunkte + Punkte aus Depot > gegnerische Innere Sicherheit + deren Inneres Depot int type = rand()%4; // Typ der Aktion (Wirtschaft, Wissenschaft, Militär oder Diplomatie) UINT ourPoints = pIntel->GetSecurityPoints() * pIntel->GetAssignment()->GetGlobalSabotagePercentage(pWorstRace->GetRaceID()) / 100 + pIntel->GetSPStorage(1, pWorstRace->GetRaceID()) * pIntel->GetAssignment()->GetSabotagePercentages(pWorstRace->GetRaceID(), type) / 100; ourPoints += ourPoints * pIntel->GetBonus(type, 1) / 100; UINT enemyPoints = pWorstIntel->GetSecurityPoints() * pWorstIntel->GetAssignment()->GetInnerSecurityPercentage() / 100; // + Bonus auf innere Sicherheit enemyPoints += enemyPoints * pWorstIntel->GetInnerSecurityBoni() / 100; // + Punkte aus dem Lager (darin ist der Bonus schon vorhanden) enemyPoints += pWorstIntel->GetInnerSecurityStorage(); if (ourPoints > enemyPoints + rand()%1500) { // zuerst komplette Zuteilung ins Lager übernehmen, damit man dann auch wirklich 100% einem einzelnen // Ressort zuweisen kann pIntel->SetAssignment()->SetSabotagePercentage(4, 100, pWorstRace->GetRaceID()); pIntel->SetAssignment()->SetSabotagePercentage(type, 100, pWorstRace->GetRaceID()); } else pIntel->SetAssignment()->SetSabotagePercentage(4, 100, pWorstRace->GetRaceID()); MYTRACE("intelai")(MT::LEVEL_INFO, "Intel-AI: our SP: %d - enemies SP: %d\n", ourPoints, enemyPoints); } // finden wir keine Rasse zum vergeheimdiensteln, so die innere Sicherheit auf 100% stellen else pIntel->SetAssignment()->SetGlobalPercentage(2, 100, it->second, "", pmMajors); } } }
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); } } } } }