void GenerateEncounterTable (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i, j; // Get the criteria from the command line SEncounterCriteria Criteria; ParseEncounterCriteria(pCmdLine->GetAttribute(CRITERIA_ATTRIB), &Criteria); bool bAll = pCmdLine->GetAttributeBool(ALL_ATTRIB); // Generate a table of all matching encounters CSymbolTable Table(FALSE, TRUE); // Loop over all items for this level and add them to // a sorted table. for (i = 0; i < Universe.GetStationTypeCount(); i++) { CStationType *pType = Universe.GetStationType(i); int iLevel = pType->GetLevel(); if (iLevel == 0 && !bAll) continue; // If we don't match the criteria, then continue if (!MatchesEncounterCriteria(Criteria, pType->GetAttributes())) continue; // Get the category and name CString sCategory = pType->GetDataField(FIELD_CATEGORY); CString sName = pType->GetDataField(FIELD_NAME); if (*sName.GetASCIIZPointer() == '(') sName = strSubString(sName, 1, -1); // Figure out the sort order char szBuffer[1024]; wsprintf(szBuffer, "%02d%s%s", pType->GetLevel(), sCategory.GetASCIIZPointer(), sName.GetASCIIZPointer()); Table.AddEntry(CString(szBuffer), (CObject *)pType); } // Generate a list of columns to display CStringArray Cols; Cols.AppendString(FIELD_LEVEL); Cols.AppendString(FIELD_CATEGORY); Cols.AppendString(FIELD_NAME); if (pCmdLine->GetAttributeBool(FIELD_ARMOR_CLASS)) Cols.AppendString(FIELD_ARMOR_CLASS); if (pCmdLine->GetAttributeBool(FIELD_HP)) Cols.AppendString(FIELD_HP); if (pCmdLine->GetAttributeBool(FIELD_FIRE_RATE_ADJ)) Cols.AppendString(FIELD_FIRE_RATE_ADJ); if (pCmdLine->GetAttributeBool(FIELD_TOTAL_COUNT)) Cols.AppendString(FIELD_TOTAL_COUNT); if (pCmdLine->GetAttributeBool(FIELD_CAN_ATTACK)) Cols.AppendString(FIELD_CAN_ATTACK); if (pCmdLine->GetAttributeBool(FIELD_EXPLOSION_TYPE)) Cols.AppendString(FIELD_EXPLOSION_TYPE); // If we need to output total count, then load the table CSymbolTable TotalCount(TRUE, TRUE); if (pCmdLine->GetAttributeBool(FIELD_TOTAL_COUNT)) { if (error = LoadTotalCount(TOTAL_COUNT_FILENAME, TotalCount)) return; } // If we've got any entries in the table, output now if (Table.GetCount()) { // Output the header for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); printf(Cols.GetStringValue(j).GetASCIIZPointer()); } printf("\n"); // Output each row for (i = 0; i < Table.GetCount(); i++) { CStationType *pType = (CStationType *)Table.GetValue(i); for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); CString sField = Cols.GetStringValue(j); CString sValue = pType->GetDataField(sField); if (strEquals(sField, FIELD_FIRE_RATE_ADJ)) printf("%.2f", strToInt(sValue, 0, NULL) / 1000.0); else if (strEquals(sField, FIELD_TOTAL_COUNT)) { double rCount = 0.0; CString sKey = strFromInt(pType->GetUNID(), FALSE); EntryInfo *pEntry; if (TotalCount.Lookup(sKey, (CObject **)&pEntry) == NOERROR) rCount = pEntry->rTotalCount; printf("%.2f", rCount); } else printf(sValue.GetASCIIZPointer()); } printf("\n"); } printf("\n"); } else printf("No entries match criteria.\n"); }
void RunEncounterSim (CUniverse &Universe, CXMLElement *pCmdLine) { int iRuns = pCmdLine->GetAttributeIntegerBounded(COUNT_ATTRIB, 1, -1, DEFAULT_RUN_COUNT); int iTimeOut = DEFAULT_TIME_OUT; // Get the station criteria CString sCriteria = strPatternSubst(CONSTLIT("%s t"), pCmdLine->GetAttribute(DEFENDERS_ATTRIB)); CDesignTypeCriteria DefenderCriteria; if (CDesignTypeCriteria::ParseCriteria(sCriteria, &DefenderCriteria) != NOERROR) { printf("ERROR: Unable to parse defenders criteria.\n"); return; } bool bAll = pCmdLine->GetAttributeBool(CONSTLIT("all")); // Get the criteria from the command line. Always append 's' because we // want ship classes. sCriteria = strPatternSubst(CONSTLIT("%s s"), pCmdLine->GetAttribute(ATTACKERS_ATTRIB)); CDesignTypeCriteria AttackerCriteria; if (CDesignTypeCriteria::ParseCriteria(sCriteria, &AttackerCriteria) != NOERROR) { printf("ERROR: Unable to parse attackers criteria.\n"); return; } // Create a viewer, if desired CSimViewer Viewer; if (pCmdLine->GetAttributeBool(VIEWER_ATTRIB)) Viewer.Create(); // Print headers printf("Encounter\tLevel"); int iAttacker; for (iAttacker = 0; iAttacker < Universe.GetShipClassCount(); iAttacker++) { CShipClass *pAttackerClass = Universe.GetShipClass(iAttacker); if (!pAttackerClass->MatchesCriteria(AttackerCriteria)) continue; printf("\t%s", pAttackerClass->GetName().GetASCIIZPointer()); } printf("\n"); // Loop over all defenders int iDefender; for (iDefender = 0; iDefender < Universe.GetStationTypeCount(); iDefender++) { CStationType *pDefenderType = Universe.GetStationType(iDefender); if (!bAll && pDefenderType->GetLevel() == 0) continue; if (!pDefenderType->MatchesCriteria(DefenderCriteria)) continue; // Compute an enemy of the station CSovereign *pAttackerSovereign = GetAttackerSovereign(Universe, pDefenderType); if (pAttackerSovereign == NULL) { printf("ERROR: Unable to find enemy sovereign of encounter: %s [%x].\n", pDefenderType->GetNounPhrase().GetASCIIZPointer(), pDefenderType->GetUNID()); return; } printf("%s [%x]\t%d", pDefenderType->GetNounPhrase().GetASCIIZPointer(), pDefenderType->GetUNID(), pDefenderType->GetLevel()); // Loop over all attackers for (iAttacker = 0; iAttacker < Universe.GetShipClassCount(); iAttacker++) { CShipClass *pAttackerClass = Universe.GetShipClass(iAttacker); if (!pAttackerClass->MatchesCriteria(AttackerCriteria)) continue; // Do several runs so we can get some statistical data int iAttackerSurvived = 0; int iRun; for (iRun = 0; iRun < iRuns; iRun++) { EResults iResult = RunEncounter(Universe, Viewer, pDefenderType, pAttackerClass, pAttackerSovereign); if (iResult == resultError) return; // Did the attacker survive? if (iResult != resultAttackerDestroyed) iAttackerSurvived++; } // Output results for this attacker int iSurvivability = 100 * iAttackerSurvived / iRuns; printf("\t%d%%", iSurvivability); } printf("\n"); } Viewer.Destroy(); }
void GenerateEncounterTable (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i, j; // Get the criteria from the command line. Always append 't' because we // want station types. CString sCriteria = strPatternSubst(CONSTLIT("%s t"), pCmdLine->GetAttribute(CRITERIA_ATTRIB)); // Parse it CDesignTypeCriteria Criteria; if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR) { printf("ERROR: Unable to parse criteria.\n"); return; } bool bAll = pCmdLine->GetAttributeBool(ALL_ATTRIB); // Generate a table of all matching encounters CSymbolTable Table(FALSE, TRUE); // Loop over all items for this level and add them to // a sorted table. for (i = 0; i < Universe.GetStationTypeCount(); i++) { CStationType *pType = Universe.GetStationType(i); int iLevel = pType->GetLevel(); if (iLevel == 0 && !bAll) continue; // If we don't match the criteria, then continue if (!pType->MatchesCriteria(Criteria)) continue; // Get the category and name CString sCategory = pType->GetDataField(FIELD_CATEGORY); CString sName = pType->GetDataField(FIELD_NAME); if (*sName.GetASCIIZPointer() == '(') sName = strSubString(sName, 1, -1); // Figure out the sort order char szBuffer[1024]; wsprintf(szBuffer, "%02d%s%s", pType->GetLevel(), sCategory.GetASCIIZPointer(), sName.GetASCIIZPointer()); Table.AddEntry(CString(szBuffer), (CObject *)pType); } // Generate a list of columns to display TArray<CString> Cols; Cols.Insert(FIELD_LEVEL); Cols.Insert(FIELD_CATEGORY); Cols.Insert(FIELD_NAME); for (i = 0; i < pCmdLine->GetAttributeCount(); i++) { CString sAttrib = pCmdLine->GetAttributeName(i); if (!strEquals(sAttrib, CONSTLIT("all")) && !strEquals(sAttrib, CONSTLIT("criteria")) && !strEquals(sAttrib, CONSTLIT("encountertable")) && !strEquals(sAttrib, CONSTLIT("nologo"))) { CString sValue = pCmdLine->GetAttribute(i); if (!strEquals(sValue, CONSTLIT("true"))) Cols.Insert(strPatternSubst(CONSTLIT("%s:%s"), sAttrib, sValue)); else Cols.Insert(sAttrib); } } #if 0 if (pCmdLine->GetAttributeBool(FIELD_ARMOR_CLASS)) Cols.Insert(FIELD_ARMOR_CLASS); if (pCmdLine->GetAttributeBool(FIELD_HP)) Cols.Insert(FIELD_HP); if (pCmdLine->GetAttributeBool(FIELD_FIRE_RATE_ADJ)) Cols.Insert(FIELD_FIRE_RATE_ADJ); if (pCmdLine->GetAttributeBool(FIELD_TOTAL_COUNT)) Cols.Insert(FIELD_TOTAL_COUNT); if (pCmdLine->GetAttributeBool(FIELD_CAN_ATTACK)) Cols.Insert(FIELD_CAN_ATTACK); if (pCmdLine->GetAttributeBool(FIELD_EXPLOSION_TYPE)) Cols.Insert(FIELD_EXPLOSION_TYPE); #endif // If we need to output total count, then load the table CSymbolTable TotalCount(TRUE, TRUE); if (pCmdLine->GetAttributeBool(FIELD_TOTAL_COUNT)) { if (error = LoadTotalCount(TOTAL_COUNT_FILENAME, TotalCount)) return; } // If we've got any entries in the table, output now if (Table.GetCount()) { // Output the header for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); printf(Cols[j].GetASCIIZPointer()); } printf("\n"); // Output each row for (i = 0; i < Table.GetCount(); i++) { CStationType *pType = (CStationType *)Table.GetValue(i); for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); const CString &sField = Cols[j]; CString sValue = pType->GetDataField(sField); if (strEquals(sField, FIELD_FIRE_RATE_ADJ)) printf("%.2f", strToInt(sValue, 0, NULL) / 1000.0); else if (strEquals(sField, FIELD_TOTAL_COUNT)) { double rCount = 0.0; CString sKey = strFromInt(pType->GetUNID(), false); EntryInfo *pEntry; if (TotalCount.Lookup(sKey, (CObject **)&pEntry) == NOERROR) rCount = pEntry->rTotalCount; printf("%.2f", rCount); } else printf(sValue.GetASCIIZPointer()); } printf("\n"); } printf("\n"); } else printf("No entries match criteria.\n"); }
void GenerateEncounterTable (CUniverse &Universe, CXMLElement *pCmdLine, CIDTable &EntityTable) { ALERROR error; int i, j; // Get the criteria from the command line. Always append 't' because we // want station types. CString sCriteria = strPatternSubst(CONSTLIT("%s t"), pCmdLine->GetAttribute(CRITERIA_ATTRIB)); // Parse it CDesignTypeCriteria Criteria; if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR) { printf("ERROR: Unable to parse criteria.\n"); return; } bool bAll = pCmdLine->GetAttributeBool(ALL_ATTRIB); bool bOnlyNotRandom = pCmdLine->GetAttributeBool(ONLY_NOT_RANDOM_ATTRIB); // Generate a table of all matching encounters CSymbolTable Table(FALSE, TRUE); // Loop over all items for this level and add them to // a sorted table. for (i = 0; i < Universe.GetStationTypeCount(); i++) { CStationType *pType = Universe.GetStationType(i); int iLevel = pType->GetLevel(); // If we're selecting all types, then do it if (bAll) ; // If we only want non-random types, then skip any random encounters. else if (bOnlyNotRandom) { if (pType->CanBeEncounteredRandomly()) continue; } // Otherwise we skip anything except random encounters. else { if (!pType->CanBeEncounteredRandomly()) continue; } // If we don't match the criteria, then continue if (!pType->MatchesCriteria(Criteria)) continue; // Get the category and name CString sCategory = pType->GetDataField(FIELD_CATEGORY); CString sName = pType->GetDataField(FIELD_NAME); if (*sName.GetASCIIZPointer() == '(') sName = strSubString(sName, 1, -1); // Figure out the sort order char szBuffer[1024]; wsprintf(szBuffer, "%02d%s%s%08x", iLevel, sCategory.GetASCIIZPointer(), sName.GetASCIIZPointer(), pType->GetUNID()); Table.AddEntry(CString(szBuffer), (CObject *)pType); } // Generate a list of columns to display TArray<CString> Cols; Cols.Insert(FIELD_LEVEL); Cols.Insert(FIELD_CATEGORY); Cols.Insert(FIELD_NAME); for (i = 0; i < pCmdLine->GetAttributeCount(); i++) { CString sAttrib = pCmdLine->GetAttributeName(i); if (!IsMainCommandParam(sAttrib) && !strEquals(sAttrib, ONLY_NOT_RANDOM_ATTRIB) && !strEquals(sAttrib, CONSTLIT("encountertable"))) { CString sValue = pCmdLine->GetAttribute(i); if (!strEquals(sValue, CONSTLIT("true"))) Cols.Insert(strPatternSubst(CONSTLIT("%s:%s"), sAttrib, sValue)); else Cols.Insert(sAttrib); } } // If we need to output total count, then load the table CDesignTypeStats TotalCount; if (pCmdLine->GetAttributeBool(FIELD_TOTAL_COUNT) || pCmdLine->GetAttributeBool(FIELD_COUNT_DISTRIBUTION)) { if (error = LoadDesignTypeStats(&TotalCount)) return; } // If we've got any entries in the table, output now if (Table.GetCount()) { // Output the header for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); printf(Cols[j].GetASCIIZPointer()); } printf("\n"); // Output each row for (i = 0; i < Table.GetCount(); i++) { CStationType *pType = (CStationType *)Table.GetValue(i); for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); const CString &sField = Cols[j]; // Get the value CString sValue; if (strEquals(sField, FIELD_ENTITY)) { CString *pValue; if (EntityTable.Lookup(pType->GetUNID(), (CObject **)&pValue) == NOERROR) sValue = *pValue; else sValue = CONSTLIT("?"); } else sValue = pType->GetDataField(sField); // Format and output if (strEquals(sField, FIELD_FIRE_RATE_ADJ)) printf("%.2f", strToInt(sValue, 0, NULL) / 1000.0); else if (strEquals(sField, FIELD_TOTAL_COUNT)) { SDesignTypeInfo *pInfo = TotalCount.GetAt(pType->GetUNID()); double rCount = (pInfo ? pInfo->rPerGameMeanCount : 0.0); printf("%.2f", rCount); } else if (strEquals(sField, FIELD_COUNT_DISTRIBUTION)) { SDesignTypeInfo *pInfo = TotalCount.GetAt(pType->GetUNID()); printf("%s", (pInfo ? pInfo->sDistribution : NULL_STR).GetASCIIZPointer()); } else printf(sValue.GetASCIIZPointer()); } printf("\n"); } printf("\n"); } else printf("No entries match criteria.\n"); }
void CPlayerGameStats::GenerateGameStats (CGameStats &Stats, CSpaceObject *pPlayerShip, bool bGameOver) const // GenerateGameStats // // Generates a stats for everything we track { int j; CShip *pShip = (pPlayerShip ? pPlayerShip->AsShip() : NULL); if (pShip == NULL) return; CPlayerShipController *pPlayer = (CPlayerShipController *)pShip->GetController(); if (pPlayer == NULL) return; CSovereign *pPlayerSovereign = g_pUniverse->FindSovereign(g_PlayerSovereignUNID); if (pPlayerSovereign == NULL) return; // Base stats Stats.Insert(CONSTLIT("Genome"), strCapitalize(GetGenomeName(pPlayer->GetPlayerGenome()))); Stats.Insert(CONSTLIT("Score"), strFormatInteger(CalcEndGameScore(), -1, FORMAT_THOUSAND_SEPARATOR | FORMAT_UNSIGNED)); Stats.Insert(CONSTLIT("Ship class"), pShip->GetNounPhrase(0)); CTimeSpan Time = GetPlayTime(); if (!Time.IsBlank()) Stats.Insert(CONSTLIT("Time played"), Time.Format(NULL_STR)); #ifdef REAL_TIME Time = GetGameTime(); if (!Time.IsBlank()) Stats.Insert(CONSTLIT("Time elapsed in game"), Time.Format(NULL_STR)); #endif // Some combat stats CString sDestroyed = GetStat(ENEMY_SHIPS_DESTROYED_STAT); if (!sDestroyed.IsBlank()) Stats.Insert(CONSTLIT("Enemy ships destroyed"), sDestroyed, CONSTLIT("combat")); sDestroyed = GetStat(FRIENDLY_SHIPS_DESTROYED_STAT); if (!sDestroyed.IsBlank()) Stats.Insert(CONSTLIT("Friendly ships destroyed"), sDestroyed, CONSTLIT("combat")); sDestroyed = GetStat(ENEMY_STATIONS_DESTROYED_STAT); if (!sDestroyed.IsBlank()) Stats.Insert(CONSTLIT("Enemy stations destroyed"), sDestroyed, CONSTLIT("combat")); sDestroyed = GetStat(FRIENDLY_STATIONS_DESTROYED_STAT); if (!sDestroyed.IsBlank()) Stats.Insert(CONSTLIT("Friendly stations destroyed"), sDestroyed, CONSTLIT("combat")); // Add stat for every station destroyed CStatCounterArray CounterArray; CMapIterator i; m_StationStats.Reset(i); while (m_StationStats.HasMore(i)) { SStationTypeStats *pStats; DWORD dwUNID = m_StationStats.GetNext(i, &pStats); CStationType *pType = g_pUniverse->FindStationType(dwUNID); if (pType == NULL) continue; CString sName = pType->GetNounPhrase(0); CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - pType->GetLevel(), sName); if (pType->GetSovereign()->IsEnemy(pPlayerSovereign)) CounterArray.Insert(sName, pStats->iDestroyed, CONSTLIT("Enemy stations destroyed"), sSort); else CounterArray.Insert(sName, pStats->iDestroyed, CONSTLIT("Friendly stations destroyed"), sSort); } CounterArray.GenerateGameStats(Stats); // Add stat for every ship class destroyed CounterArray.DeleteAll(); m_ShipStats.Reset(i); while (m_ShipStats.HasMore(i)) { SShipClassStats *pStats; DWORD dwUNID = m_ShipStats.GetNext(i, &pStats); CShipClass *pClass = g_pUniverse->FindShipClass(dwUNID); if (pClass == NULL) continue; CString sName = pClass->GetNounPhrase(0); CString sSort = strPatternSubst(CONSTLIT("%09d%s"), 100000000 - pClass->GetScore(), sName); if (pStats->iEnemyDestroyed > 0) CounterArray.Insert(sName, pStats->iEnemyDestroyed, CONSTLIT("Enemy ships destroyed"), sSort); if (pStats->iFriendDestroyed > 0) CounterArray.Insert(sName, pStats->iFriendDestroyed, CONSTLIT("Friendly ships destroyed"), sSort); } CounterArray.GenerateGameStats(Stats); // Add stat for every weapon fired m_ItemStats.Reset(i); while (m_ItemStats.HasMore(i)) { SItemTypeStats *pStats; DWORD dwUNID = m_ItemStats.GetNext(i, &pStats); CItemType *pItemType = g_pUniverse->FindItemType(dwUNID); if (pItemType == NULL) continue; CString sName = pItemType->GetNounPhrase(nounShort); CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - pItemType->GetLevel(), sName); // Installed items if (pStats->dwFirstInstalled != INVALID_TIME) Stats.Insert(sName, NULL_STR, CONSTLIT("Items installed"), sSort); if (pStats->iCountFired > 0) Stats.Insert(sName, strFormatInteger(pStats->iCountFired, -1, FORMAT_THOUSAND_SEPARATOR | FORMAT_UNSIGNED), CONSTLIT("Weapons fired"), sSort); } // Stats for player equipment (but only if the game is done) if (bGameOver) { TSortMap<CString, CItem> InstalledItems; // First we generate a sorted list of installed items // (We do this in case there are multiple of the same device/armor so that // we can coalesce them together into a single line). CItemListManipulator ItemList(pShip->GetItemList()); ItemList.ResetCursor(); while (ItemList.MoveCursorForward()) { const CItem &Item(ItemList.GetItemAtCursor()); if (Item.IsInstalled()) { CString sEnhancement = Item.GetEnhancedDesc(pShip); CString sItemName = Item.GetNounPhrase(nounActual | nounCountOnly | nounShort); CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement)); bool bInserted; CItem *pEntry = InstalledItems.SetAt(sLine, &bInserted); if (bInserted) { *pEntry = Item; pEntry->SetCount(1); } else pEntry->SetCount(pEntry->GetCount() + 1); } } // Now add all the installed items to the stats for (j = 0; j < InstalledItems.GetCount(); j++) { // Redo the line now that we know the proper count CString sEnhancement = InstalledItems[j].GetEnhancedDesc(pShip); CString sItemName = InstalledItems[j].GetNounPhrase(nounActual | nounCountOnly); CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement)); // Compute the sort order int iOrder; switch (InstalledItems[j].GetType()->GetCategory()) { case itemcatWeapon: iOrder = 0; break; case itemcatLauncher: iOrder = 1; break; case itemcatShields: iOrder = 2; break; case itemcatArmor: iOrder = 3; break; case itemcatReactor: iOrder = 4; break; case itemcatDrive: iOrder = 5; break; default: iOrder = 6; break; } CString sSort = strPatternSubst(CONSTLIT("%d%03d%s"), iOrder, 100 - InstalledItems[j].GetType()->GetLevel(), sLine); Stats.Insert(sLine, NULL_STR, CONSTLIT("Final equipment"), sSort); } // Add the remaining items ItemList.ResetCursor(); while (ItemList.MoveCursorForward()) { const CItem &Item(ItemList.GetItemAtCursor()); if (!Item.IsInstalled()) { CString sEnhancement = Item.GetEnhancedDesc(pShip); CString sItemName = Item.GetNounPhrase(nounActual | nounCountOnly); CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement)); CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - Item.GetType()->GetLevel(), sLine); Stats.Insert(sLine, NULL_STR, CONSTLIT("Final items"), sSort); } } } }
void GenerateEncounterFrequency (CUniverse &Universe, CXMLElement *pCmdLine) { enum ETypes { outputFreq, outputFillLocations, }; int i, j; // Options int iSystemSample = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1); bool bLogo = !pCmdLine->GetAttributeBool(CONSTLIT("noLogo")); bool bAll = pCmdLine->GetAttributeBool(CONSTLIT("all")); bool bRawData = pCmdLine->GetAttributeBool(CONSTLIT("rawData")); ETypes iType; if (pCmdLine->GetAttributeBool(CONSTLIT("fillLocations"))) iType = outputFillLocations; else iType = outputFreq; // Additional columns TArray<CString> Cols; for (i = 0; i < pCmdLine->GetAttributeCount(); i++) { CString sAttrib = pCmdLine->GetAttributeName(i); if (!IsMainCommandParam(sAttrib) && !strEquals(sAttrib, CONSTLIT("count")) && !strEquals(sAttrib, CONSTLIT("fillLocations")) && !strEquals(sAttrib, CONSTLIT("rawData")) && !strEquals(sAttrib, CONSTLIT("encounterfreq"))) { CString sValue = pCmdLine->GetAttribute(i); if (!strEquals(sValue, CONSTLIT("true"))) Cols.Insert(strPatternSubst(CONSTLIT("%s:%s"), sAttrib, sValue)); else Cols.Insert(sAttrib); } } // Generate systems for multiple games CSystemCreateStats Stats; for (i = 0; i < iSystemSample; i++) { if (bLogo) printf("pass %d...\n", i+1); // Initialize the game CString sError; if (Universe.InitGame(0, &sError) != NOERROR) { printf("%s\n", sError.GetASCIIZPointer()); return; } for (j = 0; j < Universe.GetTopologyNodeCount(); j++) { CTopologyNode *pNode = Universe.GetTopologyNode(j); if (pNode->IsEndGame()) continue; // Create the system CSystem *pSystem; if (Universe.CreateStarSystem(pNode, &pSystem, NULL, &Stats) != NOERROR) { printf("ERROR: Unable to create star system.\n"); return; } // Done with old system Universe.DestroySystem(pSystem); } Universe.Reinit(); } // Output based on type if (iType == outputFreq) { // Generate a table for each encounter TSortMap<CStationType *, SEncounterFreqEntry> EncounterFreq; for (i = 0; i < Stats.GetEncounterTableCount(); i++) { const CSystemCreateStats::SEncounterTable &Table = Stats.GetEncounterTable(i); // Skip if only planets and asteroids if (!Table.bHasStation && !bAll) continue; // For each entry in the table, add to the frequency table for (j = 0; j < Table.Table.GetCount(); j++) { CStationType *pEncounterType = Table.Table.GetAt(j); int iChance = Table.Table.GetChance(j); SEncounterFreqEntry *pEntry = EncounterFreq.SetAt(pEncounterType); pEntry->iCount += Table.iCount; pEntry->iTotalChance += Table.iCount * iChance; if (pEntry->pMaxTable == NULL || iChance > pEntry->iMaxChance) { pEntry->pMaxTable = &Table; pEntry->iMaxChance = iChance; } if (pEntry->pMinTable == NULL || iChance < pEntry->iMinChance) { pEntry->pMinTable = &Table; pEntry->iMinChance = iChance; } } } // Output encounter frequency distribution printf("Level\tCategory\tEncounter\tTotal Chances\tAverage Chance\tMin Chance\tMax Chance"); for (i = 0; i < Cols.GetCount(); i++) printf("\t%s", Cols[i].GetASCIIZPointer()); printf("\n"); for (i = 0; i < EncounterFreq.GetCount(); i++) { CStationType *pEncounterType = EncounterFreq.GetKey(i); int iAveWhole = EncounterFreq[i].iTotalChance / EncounterFreq[i].iCount; int iAveFrac = 1000 * (EncounterFreq[i].iTotalChance % EncounterFreq[i].iCount) / EncounterFreq[i].iCount; printf("%d\t%s\t%s\t%d\t%d.%03d\t%d\t%d", pEncounterType->GetLevel(), pEncounterType->GetDataField(CONSTLIT("category")).GetASCIIZPointer(), pEncounterType->GetName().GetASCIIZPointer(), EncounterFreq[i].iCount, iAveWhole, iAveFrac, EncounterFreq[i].iMinChance, EncounterFreq[i].iMaxChance); for (j = 0; j < Cols.GetCount(); j++) { CString sValue = pEncounterType->GetDataField(Cols[j]); printf("\t%s", sValue.GetASCIIZPointer()); } printf("\n"); } // Output raw data if (bRawData) { // Loop over stats and output tables for (i = 0; i < Stats.GetEncounterTableCount(); i++) { const CSystemCreateStats::SEncounterTable &Table = Stats.GetEncounterTable(i); // Skip if only planets and asteroids if (!Table.bHasStation && !bAll) continue; // Header printf("LEVEL %d (%d location%s)\nSystem Type: %08x\nStations: %s\n", Table.iLevel, Table.iCount, (Table.iCount == 1 ? "" : "s"), Table.pSystemType->GetUNID(), Table.sStationCriteria.GetASCIIZPointer()); // Location attributes printf("Location: "); for (j = 0; j < Table.LabelAttribs.GetCount(); j++) { if (j != 0) printf(", "); printf(Table.LabelAttribs[j].GetASCIIZPointer()); } printf("\n"); // Entries for (j = 0; j < Table.Table.GetCount(); j++) printf("%s\t%d\n", Table.Table.GetAt(j)->GetName().GetASCIIZPointer(), Table.Table.GetChance(j)); printf("\n"); } } } else if (iType == outputFillLocations) { printf("Level\tSystem\tEncounter\tChance\n"); for (i = 0; i < Stats.GetFillLocationsTableCount(); i++) { const CSystemCreateStats::SFillLocationsTable &Entry = Stats.GetFillLocationsTable(i); for (j = 0; j < Entry.Table.GetCount(); j++) { int iPercent = (int)(1000.0 * Entry.Table.GetChance(j) / (Metric)Entry.Table.GetTotalChance()); printf("%d\t%s\t%s\t%d.%d\n", Entry.iLevel, Entry.sSystemName.GetASCIIZPointer(), Entry.Table[j]->GetName().GetASCIIZPointer(), iPercent / 10, iPercent % 10); } } } }