void AddTypeToIsland (CUniverse &Universe, ReverseIndexMap &ReverseIndex, IslandMap *pIsland, CDesignType *pType) { int i; // Skip images if (pType->GetType() == designImage) return; if (pType->GetType() == designShipTable) return; // Exclude default types if (g_DefaultTypes.Find(pType->GetUNID())) return; // If this type is already on the island, then there is nothing to do. if (pIsland->Find(pType->GetUNID())) return; // Add the type to the island (we do this first because we want it to be // here in case we recurse below). pIsland->Insert(pType->GetUNID(), true); // Now get the list of all types that this type uses and add them to the // island. IslandMap TypesUsed; pType->AddTypesUsed(&TypesUsed); for (i = 0; i < TypesUsed.GetCount(); i++) { CDesignType *pTypeUsed = Universe.FindDesignType(TypesUsed.GetKey(i)); if (pTypeUsed == NULL) continue; AddTypeToIsland(Universe, ReverseIndex, pIsland, pTypeUsed); } // Now get the lists that use this type and add them to the island. #if 0 TArray<DWORD> *pList = ReverseIndex.GetAt(pType->GetUNID()); if (pList) { for (i = 0; i < pList->GetCount(); i++) { CDesignType *pTypeUsing = Universe.FindDesignType(pList->GetAt(i)); if (pTypeUsing == NULL) continue; AddTypeToIsland(Universe, ReverseIndex, pIsland, pTypeUsing); } } #endif }
void GenerateTopology (CUniverse &Universe, CXMLElement *pCmdLine) { int i; for (i = 0; i < Universe.GetTopologyNodeCount(); i++) { CTopologyNode *pNode = Universe.GetTopologyNode(i); OutputTopologyNode(pNode); } }
void GenerateStats (CUniverse &Universe, CXMLElement *pCmdLine) { int i; printf("STATS\n\n"); int iItemTypes = 0; for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pType = Universe.GetItemType(i); // Do not count virtual items if (pType->IsVirtual()) continue; iItemTypes++; } printf("Item types:\t\t%d\n", iItemTypes); printf("Ship classes:\t\t%d\n", Universe.GetShipClassCount()); printf("Station types:\t\t%d\n", Universe.GetStationTypeCount()); }
void AddTypesUsedRecursive (CUniverse &Universe, DWORD dwUNID, TSortMap<DWORD, bool> *retTypesUsed) { int i; // If already added, don't bother if (retTypesUsed->Find(dwUNID)) return; CDesignType *pType = Universe.FindDesignType(dwUNID); if (pType == NULL) return; retTypesUsed->SetAt(dwUNID, true); // Recurse TSortMap<DWORD, bool> TypesUsed; pType->AddTypesUsed(&TypesUsed); for (i = 0; i < TypesUsed.GetCount(); i++) AddTypesUsedRecursive(Universe, TypesUsed.GetKey(i), retTypesUsed); }
void GenerateWeaponEffectChart (CUniverse &Universe, CXMLElement *pCmdLine) { int i; // Compute the list of weapons to show, making sure we filter to weapons // and missiles only. CItemTypeTable Selection; if (!Selection.Filter(pCmdLine->GetAttribute(CRITERIA_ATTRIB)) || (Selection.IsAll() && !Selection.Filter(CONSTLIT("wm")))) { printf("No entries match criteria.\n"); return; } Selection.Sort(); // Ship to use DWORD dwPlatformUNID; if (!pCmdLine->FindAttributeInteger(SHIP_UNID_ATTRIB, (int *)&dwPlatformUNID)) dwPlatformUNID = WEAPON_PLATFORM_UNID; // Compute some metrics int iFramesPerItem = 10; int cxFrameHorzMargin = 10; int cxMaxDistPerTick = (int)(STD_SECONDS_PER_UPDATE * (LIGHT_SECOND / g_KlicksPerPixel)); int cyFrame = 64; int cxFrame = (2 * cxFrameHorzMargin) + (iFramesPerItem * cxMaxDistPerTick); int iHitEffectFramesPerItem = 5; int cxHitEffect = 128; int cyHitEffect = 128; int cyRowTitle = 20; int cyRow = cyRowTitle + Max(ITEM_ICON_HEIGHT, cyFrame * iFramesPerItem); int cxRow = ITEM_ICON_WIDTH + cxFrame; int iColumns = Max(1, mathSqrt(Selection.GetCount())); int iRows = (Selection.GetCount() + (iColumns - 1)) / iColumns; int cxImage = cxRow * iColumns; int cyImage = cyRow * iRows; // Initialize the output COutputChart Output; Output.SetContentSize(cxImage, cyImage); Output.SetOutputFilespec(pCmdLine->GetAttribute(CONSTLIT("output"))); // Initialize fonts Output.SetStyleFont(STYLE_TITLE, pCmdLine->GetAttribute(CONSTLIT("font"))); Output.SetStyleColor(STYLE_TITLE, CG32bitPixel(0xFF, 0xFF, 0xFF)); // Prepare the universe CSystem *pSystem; if (Universe.CreateEmptyStarSystem(&pSystem) != NOERROR) { printf("ERROR: Unable to create empty star system.\n"); return; } // Create a target in the center of the system CSpaceObject *pStation; CStationType *pTargetType = Universe.FindStationType(TARGET_UNID); if (pTargetType == NULL || pSystem->CreateStation(pTargetType, NULL, CVector(), &pStation) != NOERROR) { printf("ERROR: Unable to create station.\n"); return; } // Create the weapon platform some distance away CSovereign *pPlatformSovereign = Universe.FindSovereign(PLAYER_SOVEREIGN_UNID); CShip *pPlatform; if (pPlatformSovereign == NULL || pSystem->CreateShip(dwPlatformUNID, NULL, NULL, pPlatformSovereign, CVector(-5.0 * LIGHT_SECOND, 0.), CVector(), 0, NULL, NULL, &pPlatform) != NOERROR) { printf("ERROR: Unable to create weapons platform.\n"); return; } // Set the attacker to hold IShipController *pController = pPlatform->GetController(); if (pController == NULL) { printf("ERROR: No controller for ship.\n"); return; } pController->AddOrder(IShipController::orderHold, NULL, IShipController::SData()); pPlatform->SetControllerEnabled(false); // Install the largest possible reactor on the ship CItemType *pReactorType = Universe.FindItemType(REACTOR_UNID); if (pReactorType) { CItem ReactorItem(pReactorType, 1); CItemListManipulator ItemList(pPlatform->GetItemList()); ItemList.AddItem(ReactorItem); pPlatform->OnComponentChanged(comCargo); pPlatform->ItemsModified(); pPlatform->InvalidateItemListAddRemove(); pPlatform->InstallItemAsDevice(ItemList); } // Set the POV Universe.SetPOV(pStation); pSystem->SetPOVLRS(pStation); // Prepare system Universe.UpdateExtended(); Universe.GarbageCollectLibraryBitmaps(); Universe.StartGame(true); // Output each weapon int xOrigin; int yOrigin; CG32bitImage &Image = Output.GetOutputImage(&xOrigin, &yOrigin); const CG16bitFont &TitleFont = Output.GetStyleFont(STYLE_TITLE); CG32bitPixel rgbTitleColor = Output.GetStyleColor(STYLE_TITLE); for (i = 0; i < Selection.GetCount(); i++) { CItemType *pType = Selection.GetItemType(i); // Compute the metrics of this row int xRow = xOrigin + (i % iColumns) * cxRow; int yRow = yOrigin + (i / iColumns) * cyRow; // Paint the weapon title Image.Fill(xRow, yRow, cxRow, cyRow, CG32bitPixel(0x40, 0x40, 0x40)); TitleFont.DrawText(Image, xRow + 8, yRow, rgbTitleColor, pType->GetNounPhrase()); // Paint the frames PaintWeaponFrames(Image, pType, pPlatform, iFramesPerItem, xRow + ITEM_ICON_WIDTH + cxFrameHorzMargin, yRow + cyRowTitle, cxMaxDistPerTick, cyFrame); } // Done Output.Output(); }
void GenerateSnapshot (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i; // Get some parameters int iInitialUpdateTime = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("initialUpdate"), 0, -1, 10); int iUpdateTime = pCmdLine->GetAttributeInteger(CONSTLIT("wait")); bool bObjOnly = pCmdLine->GetAttributeBool(CONSTLIT("objOnly")); // Criteria CString sNode = pCmdLine->GetAttribute(CONSTLIT("node")); CString sCriteria = pCmdLine->GetAttribute(CONSTLIT("criteria")); // Number of snapshots int iTotalCount = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1); // Output int cxWidth; int cyHeight; if (pCmdLine->FindAttributeInteger(CONSTLIT("size"), &cxWidth)) { cyHeight = cxWidth; } else { cxWidth = 1024; cyHeight = 1024; } // Paint flags DWORD dwPaintFlags = 0; if (pCmdLine->GetAttributeBool(CONSTLIT("noStars"))) dwPaintFlags |= CSystem::VWP_NO_STAR_FIELD; // Output file CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output")); if (!sFilespec.IsBlank()) sFilespec = pathStripExtension(sFilespec); // Output image CG32bitImage Output; Output.Create(cxWidth, cyHeight); // Update context SSystemUpdateCtx Ctx; Ctx.bForceEventFiring = true; Ctx.bForcePainted = true; RECT rcViewport; rcViewport.left = 0; rcViewport.top = 0; rcViewport.right = cxWidth; rcViewport.bottom = cyHeight; // Loop over all systems until we find what we're looking for int iLoops = 20; int iNodeIndex = 0; int iSnapshotIndex = 0; CTopologyNode *pNode = Universe.GetTopologyNode(iNodeIndex); while (true) { // Create the system CSystem *pSystem; if (error = Universe.CreateStarSystem(pNode, &pSystem)) { printf("ERROR: Unable to create star system.\n"); return; } // If this is the node we want, then search CSpaceObject *pTarget; if (sNode.IsBlank() || strEquals(sNode, pNode->GetID())) { printf("Searching %s...\n", pNode->GetSystemName().GetASCIIZPointer()); // Set the POV CSpaceObject *pPOV = pSystem->GetObject(0); Universe.SetPOV(pPOV); pSystem->SetPOVLRS(pPOV); // Prepare system Universe.UpdateExtended(); Universe.GarbageCollectLibraryBitmaps(); // Update for a while for (i = 0; i < iInitialUpdateTime; i++) { Universe.Update(Ctx); Universe.PaintPOV(Output, rcViewport, 0); } // Compose the criteria CSpaceObject::Criteria Criteria; CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria); // Get the list of all objects in the system that match the criteria CSpaceObject::SCriteriaMatchCtx Ctx(Criteria); TArray<CSpaceObject *> Results; for (i = 0; i < pSystem->GetObjectCount(); i++) { CSpaceObject *pObj = pSystem->GetObject(i); if (pObj && pObj->MatchesCriteria(Ctx, Criteria)) Results.Insert(pObj); } // Pick the appropriate object from the list if (Results.GetCount() == 0) pTarget = NULL; else if (Criteria.bNearestOnly || Criteria.bFarthestOnly) pTarget = Ctx.pBestObj; else pTarget = Results[mathRandom(0, Results.GetCount() - 1)]; } else pTarget = NULL; // If we found the target, then output if (pTarget) { Universe.SetPOV(pTarget); // Wait a bit // // NOTE: After we update, pTarget could be invalid (i.e., destroyed) // so we can't use it again. CString sTargetName = pTarget->GetNounPhrase(0); for (i = 0; i < iUpdateTime; i++) { if ((i % 100) == 99) printf("."); Universe.Update(Ctx); Universe.PaintPOV(Output, rcViewport, 0); } if (iUpdateTime >= 99) printf("\n"); // Paint if (bObjOnly) { SViewportPaintCtx Ctx; Ctx.pObj = Universe.GetPOV(); Ctx.XForm = ViewportTransform(Universe.GetPOV()->GetPos(), g_KlicksPerPixel, cxWidth / 2, cyHeight / 2); Ctx.XFormRel = Ctx.XForm; Ctx.fNoRecon = true; Ctx.fNoDockedShips = true; Ctx.fNoSelection = true; Ctx.fNoStarfield = true; CSpaceObject *pPOV = pSystem->GetObject(0); CSpaceObject::Criteria Criteria; CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria); // Paint all objects that match the criteria CSpaceObject::SCriteriaMatchCtx CriteriaCtx(Criteria); for (i = 0; i < pSystem->GetObjectCount(); i++) { CSpaceObject *pObj = pSystem->GetObject(i); if (pObj && pObj->MatchesCriteria(CriteriaCtx, Criteria)) { Ctx.pObj = pObj; int xObj; int yObj; Ctx.XForm.Transform(pObj->GetPos(), &xObj, &yObj); pObj->Paint(Output, xObj, yObj, Ctx); } } } else { Universe.PaintPOV(Output, rcViewport, 0); } // Write to file if (!sFilespec.IsBlank()) { CString sBmpFilespec; if (iTotalCount > 100) sBmpFilespec = pathAddExtensionIfNecessary(strPatternSubst(CONSTLIT("%s%03d"), sFilespec, iSnapshotIndex + 1), CONSTLIT(".bmp")); else if (iTotalCount > 1) sBmpFilespec = pathAddExtensionIfNecessary(strPatternSubst(CONSTLIT("%s%02d"), sFilespec, iSnapshotIndex + 1), CONSTLIT(".bmp")); else sBmpFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp")); CFileWriteStream OutputFile(sBmpFilespec); if (OutputFile.Create() != NOERROR) { printf("ERROR: Unable to create '%s'\n", sBmpFilespec.GetASCIIZPointer()); return; } Output.WriteToWindowsBMP(&OutputFile); OutputFile.Close(); printf("Found %s: Saved to %s\n", sTargetName.GetASCIIZPointer(), sBmpFilespec.GetASCIIZPointer()); } // Otherwise, clipboard else { if (error = Output.CopyToClipboard()) { printf("ERROR: Unable to copy image to clipboard.\n"); return; } printf("Found %s: Copied to clipboard.\n", sTargetName.GetASCIIZPointer()); } // Reset maximum loops iLoops = 20; // Done iSnapshotIndex++; if (iSnapshotIndex >= iTotalCount) break; } // Done with old system Universe.DestroySystem(pSystem); // Loop to the next node do { iNodeIndex = ((iNodeIndex + 1) % Universe.GetTopologyNodeCount()); pNode = Universe.GetTopologyNode(iNodeIndex); } while (pNode == NULL || pNode->IsEndGame()); // If we're back to the first node again, restart if (iNodeIndex == 0) { if (--iLoops > 0) { // Reinitialize Universe.Reinit(); CString sError; if (Universe.InitGame(0, &sError) != NOERROR) { printf("ERROR: %s\n", sError.GetASCIIZPointer()); return; } iNodeIndex = 0; pNode = Universe.GetTopologyNode(iNodeIndex); } else { printf("ERROR: Specified target could not be found.\n"); return; } } } }
void GenerateShipImageChart (CUniverse &Universe, CXMLElement *pCmdLine) { int i; enum OrderTypes { orderSmallest = 1, orderLargest = 2, orderName = 3, }; // Options bool bTextBoxesOnly = pCmdLine->GetAttributeBool(CONSTLIT("textBoxesOnly")); // Figure out what order we want CString sOrder = pCmdLine->GetAttribute(CONSTLIT("sort")); int iOrder; if (strEquals(sOrder, CONSTLIT("smallest"))) iOrder = orderSmallest; else if (strEquals(sOrder, CONSTLIT("largest"))) iOrder = orderLargest; else iOrder = orderName; // Image size int cxDesiredWidth; if (pCmdLine->FindAttributeInteger(CONSTLIT("width"), &cxDesiredWidth)) cxDesiredWidth = Max(512, cxDesiredWidth); else cxDesiredWidth = 1280; // Spacing int cxSpacing = pCmdLine->GetAttributeInteger(CONSTLIT("xSpacing")); int cxExtraMargin = pCmdLine->GetAttributeInteger(CONSTLIT("xMargin")); // Rotation int iRotation = pCmdLine->GetAttributeInteger(CONSTLIT("rotation")); // Font for text CString sTypeface; int iSize; bool bBold; bool bItalic; if (!CG16bitFont::ParseFontDesc(pCmdLine->GetAttribute(CONSTLIT("font")), &sTypeface, &iSize, &bBold, &bItalic)) { sTypeface = CONSTLIT("Arial"); iSize = 10; bBold = false; bItalic = false; } CG16bitFont NameFont; NameFont.Create(sTypeface, -PointsToPixels(iSize), bBold, bItalic); WORD wNameColor = CG16bitImage::RGBValue(255, 255, 255); // Output file CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output")); if (!sFilespec.IsBlank()) sFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp")); // Generate a table of ships CSymbolTable Table(FALSE, TRUE); for (i = 0; i < Universe.GetShipClassCount(); i++) { CShipClass *pClass = Universe.GetShipClass(i); // Skip player ship classes if (pClass->GetPlayerSettings()) continue; // Skip non-generic classes if (!pClass->HasAttribute(CONSTLIT("genericClass"))) continue; // Compute the sort key char szBuffer[1024]; switch (iOrder) { case orderLargest: wsprintf(szBuffer, "%04d%s%x", 2048 - RectWidth(pClass->GetImage().GetImageRect()), pClass->GetName().GetASCIIZPointer(), pClass); break; case orderSmallest: wsprintf(szBuffer, "%04d%s%x", RectWidth(pClass->GetImage().GetImageRect()), pClass->GetName().GetASCIIZPointer(), pClass); break; default: wsprintf(szBuffer, "%s%x", pClass->GetName().GetASCIIZPointer(), pClass); break; } // Add to list Table.AddEntry(CString(szBuffer), (CObject *)pClass); } // Allocate a map that tracks where to paint each ship CPaintMap Map(Table.GetCount()); // Arrange the ships SArrangeDesc Desc; Desc.cxDesiredWidth = Max(512, cxDesiredWidth - (2 * (cxSpacing + cxExtraMargin))); Desc.cxSpacing = cxSpacing; Desc.cxExtraMargin = cxExtraMargin; Desc.pHeader = &NameFont; ArrangeByRow(Table, Desc, Map); //ArrangeByCell(Table, cxDesiredWidth, Map); // Create a large image CG16bitImage Output; int cxWidth = Max(cxDesiredWidth, Map.GetWidth()); int cyHeight = Map.GetHeight(); Output.CreateBlank(cxWidth, cyHeight, false); printf("Creating %dx%d image.\n", cxWidth, cyHeight); // Paint the images for (i = 0; i < Table.GetCount(); i++) { CShipClass *pClass = (CShipClass *)Table.GetValue(i); int x = Map.GetX(i); int y = Map.GetY(i); if (x != -1) { if (!bTextBoxesOnly) pClass->GetImage().PaintImageUL(Output, x, y, 0, Angle2Direction(iRotation)); // Paint name int xText = Map.GetTextX(i); int yText = Map.GetTextY(i); if (xText != -1) { if (bTextBoxesOnly) Output.Fill(xText, yText, Map.GetTextWidth(i), Map.GetTextHeight(i), 0xffff); if (!bTextBoxesOnly) { Output.FillColumn(x + (Map.GetWidth(i) / 2), y + Map.GetHeight(i), yText - (y + Map.GetHeight(i)), wNameColor); NameFont.DrawText(Output, xText, yText, wNameColor, 255, pClass->GetNounPhrase(0)); } } } } // Write to file or clipboard OutputImage(Output, sFilespec); }
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 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"); }
EResults RunEncounter (CUniverse &Universe, CSimViewer &Viewer, CStationType *pDefenderType, CShipClass *pAttackerClass, CSovereign *pAttackerSovereign) { int iTimeOut = DEFAULT_TIME_OUT; // Make sure the universe is clean CString sError; if (Universe.InitGame(0, &sError) != NOERROR) { printf("ERROR: %s", sError.GetASCIIZPointer()); return resultError; } // Create an empty system CSystem *pSystem; if (Universe.CreateEmptyStarSystem(&pSystem) != NOERROR) { printf("ERROR: Unable to create empty star system.\n"); return resultError; } // Create a station in the center of the system CSpaceObject *pStation; if (pSystem->CreateStation(pDefenderType, NULL, CVector(), &pStation) != NOERROR) { printf("ERROR: Unable to create station.\n"); return resultError; } // Set the POV Universe.SetPOV(pStation); pSystem->SetPOVLRS(pStation); // Prepare system Universe.UpdateExtended(); Universe.GarbageCollectLibraryBitmaps(); Universe.StartGame(true); // Now create an attacker some distance away CVector vPos = PolarToVector(mathRandom(0, 359), INITIAL_DISTANCE); CShip *pAttacker; if (pSystem->CreateShip(pAttackerClass->GetUNID(), NULL, NULL, pAttackerSovereign, vPos, CVector(), 0, NULL, NULL, &pAttacker) != NOERROR) { printf("ERROR: Unable to create attacking ship.\n"); return resultError; } // Set the attacker to attack the station IShipController *pController = pAttacker->GetController(); if (pController == NULL) { printf("ERROR: No controller for ship.\n"); return resultError; } pController->AddOrder(IShipController::orderAttackStation, pStation, IShipController::SData()); // Watch the attacker Universe.SetPOV(pAttacker); pSystem->SetPOVLRS(pAttacker); // Update context SSystemUpdateCtx Ctx; Ctx.bForceEventFiring = true; Ctx.bForcePainted = true; // Now keep updating until either the station is destroyed, the ship is destroyed, or we time-out int iTime = 0; int iDestroyedTime = (Viewer.IsEmpty() ? 0 : DESTROY_TIME); bool bDestroyed = false; EResults iResult = resultTimeout; while (iTime < iTimeOut && (!bDestroyed || iDestroyedTime > 0)) { iTime++; Universe.Update(Ctx); if (!Viewer.IsEmpty()) Viewer.PaintViewport(Universe); if (bDestroyed) iDestroyedTime--; else if (pStation->IsDestroyed() || pStation->IsAbandoned()) { bDestroyed = true; iResult = resultDefenderDestroyed; } else if (pAttacker->IsDestroyed()) { bDestroyed = true; iResult = resultAttackerDestroyed; } } // Done return iResult; }
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 GenerateTopology (CUniverse &Universe, CXMLElement *pCmdLine) { int i, j, k; int iCount = pCmdLine->GetAttributeIntegerBounded(COUNT_SWITCH, 1, -1, 1); STopologyStats Stats; for (k = 0; k < iCount; k++) { if (iCount > 1) printf("sample %d", k+1); TSortMap<CString, SNodeInfo> NodeData; TSortMap<CString, int> AttribCount; // Initialize the topology CString sError; Universe.GetFirstTopologyNode(); // Loop over all nodes for (i = 0; i < Universe.GetTopologyNodeCount(); i++) { CTopologyNode *pNode = Universe.GetTopologyNode(i); SNodeInfo *pNewNode = NodeData.Insert(pNode->GetID()); pNewNode->sID = pNode->GetID(); pNewNode->sName = pNode->GetSystemName(); pNewNode->dwSystemUNID = pNode->GetSystemDescUNID(); pNewNode->sAttribs = pNode->GetAttributes(); // Add the attributes in this node to the list of // attributes for this try. TArray<CString> Attribs; ParseAttributes(pNewNode->sAttribs, &Attribs); for (j = 0; j < Attribs.GetCount(); j++) { int *pCount = AttribCount.GetAt(Attribs[j]); if (pCount == NULL) { pCount = AttribCount.Insert(Attribs[j]); *pCount = 0; } *pCount = (*pCount) + 1; } } // Compute topology stats // Add the node count for this try Stats.NodeCount.Insert(NodeData.GetCount()); // Loop over all attributes that we know about. If one doesn't // exist in this try, then we set its min to 0 if (k > 0) { for (i = 0; i < Stats.Attribs.GetCount(); i++) { if (AttribCount.GetAt(Stats.Attribs.GetKey(i)) == NULL) Stats.Attribs[i].SetMin(0); } } // Loop over all attributes in this try and add them to the stats SStat *pAttribStat; for (i = 0; i < AttribCount.GetCount(); i++) { // If we have some attributes that no other try had, then // that means that the minimum value is 0. if (pAttribStat = Stats.Attribs.GetAt(AttribCount.GetKey(i))) pAttribStat->Insert(AttribCount[i]); else { pAttribStat = Stats.Attribs.Insert(AttribCount.GetKey(i)); pAttribStat->Insert(AttribCount[i]); if (k > 0) pAttribStat->SetMin(0); } } // Output all the nodes if (iCount == 1) { printf("Node\tSystemType\tName\tStargates\tAttributes\n"); for (i = 0; i < NodeData.GetCount(); i++) { SNodeInfo *pNode = &NodeData.GetValue(i); printf("%s\t%08x\t%s\t%d\t%s\n", pNode->sID.GetASCIIZPointer(), pNode->dwSystemUNID, pNode->sName.GetASCIIZPointer(), pNode->Stargates.GetCount(), pNode->sAttribs.GetASCIIZPointer()); } } else { Universe.Reinit(); printf("\n"); } } // Output stats if (iCount > 0) { printf("\n"); printf("STATS\n\n"); Stats.NodeCount.Print(CONSTLIT("Nodes"), iCount, Stats.NodeCount.GetAverage(iCount)); printf("\n"); printf("ATTRIBS\n\n"); for (i = 0; i < Stats.Attribs.GetCount(); i++) Stats.Attribs[i].Print(Stats.Attribs.GetKey(i), iCount, Stats.NodeCount.GetAverage(iCount)); printf("\n"); } }
void GenerateArmorTable (CUniverse &Universe, CXMLElement *pCmdLine) { int i; printf("ARMOR TABLE\n\n"); printf("Level\tArmor\tCost\tWeight\tHP\tLasr\tImpc\tPart\tBlst\tIon\tThrm\tPosi\tPlsm\tAnti\tNano\tGrav\tSing\tDacd\tDstl\tDlgt\tDfir\n"); for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pItem = Universe.GetItemType(i); CArmorClass *pArmor = pItem->GetArmorClass(); if (pArmor == NULL) continue; CItem Item(pItem, 1); CString sName = pItem->GetName(NULL); int iHP = pArmor->GetMaxHP(CItemCtx(&Item)); printf("%d\t%s\t%d\t%d\t%d\t", pItem->GetLevel(), sName.GetASCIIZPointer(), Item.GetValue(true), Item.GetMassKg(), iHP); // For each damage type, compute the adjusted hit points of the armor int iDamage; for (iDamage = damageLaser; iDamage < damageCount; iDamage++) { printf("%d", pArmor->GetDamageAdj(CItemCtx(Item), (DamageTypes)iDamage)); if (iDamage != damageCount - 1) printf("\t"); } printf("\n"); } printf("ARMOR TABLE DAMAGE ADJUSTMENTS\n\n"); printf("Level\tArmor\tHP\tLasr\tImpc\tPart\tBlst\tIon\tThrm\tPosi\tPlsm\tAnti\tNano\tGrav\tSing\tDacd\tDstl\tDlgt\tDfir\n"); for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pItem = Universe.GetItemType(i); CArmorClass *pArmor = pItem->GetArmorClass(); if (pArmor == NULL) continue; CString sName = pItem->GetName(NULL); CItem Item(pItem, 1); int iHP = pArmor->GetMaxHP(CItemCtx(&Item)); printf("%d\t%s\t%d\t", pItem->GetLevel(), sName.GetASCIIZPointer(), iHP); // For each damage type, compute the adjusted hit points of the armor int iDamage; for (iDamage = damageLaser; iDamage < damageCount; iDamage++) { int iAdj = pArmor->GetDamageAdj(CItemCtx(Item), (DamageTypes)iDamage); if (iAdj == 0) printf("----"); else printf("%d", iHP * 100 / iAdj); if (iDamage != damageCount - 1) printf("\t"); } printf("\n"); } }
void GenerateShieldStats (CUniverse &Universe, CXMLElement *pCmdLine) { int i; CString sUNID = pCmdLine->GetAttribute(CONSTLIT("unid")); DWORD dwUNID = strToInt(sUNID, 0, NULL); CItemType *pItem = Universe.FindItemType(dwUNID); if (pItem == NULL) { CItemCriteria Crit; CItem::InitCriteriaAll(&Crit); CItem Item = CItem::CreateItemByName(sUNID, Crit); pItem = Item.GetType(); if (pItem == NULL) { printf("ERROR: Unknown item '%s'\n", sUNID.GetASCIIZPointer()); return; } } if (pItem->GetCategory() != itemcatShields) { printf("ERROR: Item '%s' is not a shield generator\n", pItem->GetNounPhrase().GetASCIIZPointer()); return; } bool bVerbose = pCmdLine->GetAttributeBool(CONSTLIT("verbose")); bool bEval = pCmdLine->GetAttributeBool(CONSTLIT("eval")); // Get the stats for the shield Metric rHP = (Metric)pItem->GetDataFieldInteger(FIELD_HP); Metric rHPRegenPerTick = pItem->GetDataFieldInteger(FIELD_REGEN) / 1000.0; int iDamageAdj[damageCount]; CString sDamageAdj = pItem->GetDataField(CONSTLIT("damageAdj")); char *pPos = sDamageAdj.GetASCIIZPointer(); int iCount = 0; while (iCount < damageCount) { iDamageAdj[iCount] = strParseInt(pPos, 0, &pPos, NULL); if (*pPos != '\0') pPos++; iCount++; } // Print header printf("%s\n\n", pItem->GetNounPhrase().GetASCIIZPointer()); // Loop over all weapons and sort them by level and then name CSymbolTable List(FALSE, TRUE); for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pWeapon = Universe.GetItemType(i); if (pWeapon->GetCategory() != itemcatWeapon) continue; CString sLevel = (pWeapon->GetLevel() < 10 ? strPatternSubst(CONSTLIT("0%d"), pWeapon->GetLevel()) : strFromInt(pWeapon->GetLevel(), FALSE)); CString sSortName = strPatternSubst(CONSTLIT("%s%s"), sLevel, pWeapon->GetNounPhrase()); List.AddEntry(sSortName, (CObject *)pWeapon); } // Loop over sorted list and output data for (i = 0; i < List.GetCount(); i++) { CItemType *pWeapon = (CItemType *)List.GetValue(i); // Get the data for the weapon int iFireDelay = pWeapon->GetDataFieldInteger(CONSTLIT("fireDelay")); Metric rAverageDamage = pWeapon->GetDataFieldInteger(CONSTLIT("averageDamage")) / 1000.0; int iDamageType = pWeapon->GetDataFieldInteger(CONSTLIT("damageType")); if (iDamageType < 0 || iDamageType >= damageCount) iDamageType = 0; // Adjust damage for type rAverageDamage = rAverageDamage * (iDamageAdj[iDamageType] / 100.0); if (rAverageDamage < 1.0) rAverageDamage = 0.0; // Calculate how many shots it would take to pierce through the shields char szBuffer[256]; Metric rShotsToDeplete; Metric rRegenPerShot = rHPRegenPerTick * (Metric)iFireDelay; if (rRegenPerShot >= rAverageDamage) { rShotsToDeplete = 1000000.0; lstrcpy(szBuffer, "ineffective"); } else { Metric rDrainPerShot = rAverageDamage - rRegenPerShot; rShotsToDeplete = rHP / rDrainPerShot; sprintf(szBuffer, "%.2f", rShotsToDeplete); } // See if this weapon is overpowered or underpowered char szEval[256]; if (bEval) { lstrcpy(szEval, "\t"); if (pWeapon->GetLevel() < pItem->GetLevel()) { if (rShotsToDeplete <= 10.0) lstrcpy(szEval, "\tOVERpowered"); } else { if (rShotsToDeplete > 20.0) lstrcpy(szEval, "\tUNDERpowered"); } } else lstrcpy(szEval, ""); // Print table if (bVerbose) { printf("%s\t%s\t%s\t(%d ticks; %.2f damage; %.2f regen/shot)%s\n", RomanNumeral(pWeapon->GetLevel()), pWeapon->GetNounPhrase().GetASCIIZPointer(), szBuffer, iFireDelay, rAverageDamage, rRegenPerShot, szEval); } else { printf("%s\t%s\t%s%s\n", RomanNumeral(pWeapon->GetLevel()), pWeapon->GetNounPhrase().GetASCIIZPointer(), szBuffer, szEval); } } }
void GenerateSystemLabelCount (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i, j; CString sError; enum STypes { typeSystemLabels, typeNodeAttributes, typeNodeDebug, }; // Figure out what kind of output we want STypes iType; if (pCmdLine->GetAttributeBool(CONSTLIT("nodes"))) iType = typeNodeAttributes; else if (pCmdLine->GetAttributeBool(CONSTLIT("nodeDebug"))) iType = typeNodeDebug; else iType = typeSystemLabels; // Samples int iSystemSample = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1); // Options bool bPermutations = pCmdLine->GetAttributeBool(CONSTLIT("permutations")); // Generate systems for multiple games CSystemCreateStats Stats; Stats.AddPermuteAttrib(CONSTLIT("asteroids")); Stats.AddPermuteAttrib(CONSTLIT("planetary")); Stats.AddPermuteAttrib(CONSTLIT("void")); Stats.AddPermuteAttrib(CONSTLIT("innerSystem")); Stats.AddPermuteAttrib(CONSTLIT("lifeZone")); Stats.AddPermuteAttrib(CONSTLIT("outerSystem")); Stats.AddPermuteAttrib(CONSTLIT("envAir")); Stats.AddPermuteAttrib(CONSTLIT("envEarth")); Stats.AddPermuteAttrib(CONSTLIT("envFire")); Stats.AddPermuteAttrib(CONSTLIT("envWater")); bPermutations = true; for (i = 0; i < iSystemSample; i++) { printf("pass %d...\n", i+1); // Initialize the universe if (error = Universe.InitGame(0, &sError)) { printf("ERROR: %s", sError.GetASCIIZPointer()); return; } // Loop over all topology nodes for (j = 0; j < Universe.GetTopologyNodeCount(); j++) { CTopologyNode *pNode = Universe.GetTopologyNode(j); if (pNode->IsEndGame()) continue; // Different stats depending on type switch (iType) { case typeSystemLabels: { // Create the system and generate stats CSystem *pSystem; if (error = Universe.CreateStarSystem(pNode, &pSystem, NULL, &Stats)) { printf("ERROR: Unable to create star system.\n"); return; } // Done Universe.DestroySystem(pSystem); break; } case typeNodeAttributes: { CString sAttribs = pNode->GetAttributes(); if (!sAttribs.IsBlank()) Stats.AddLabel(sAttribs); else Stats.AddLabel(CONSTLIT("[no attributes]")); break; } case typeNodeDebug: { CString sAttribs = pNode->GetAttributes(); printf("%s: %s\n", pNode->GetID().GetASCIIZPointer(), pNode->GetAttributes().GetASCIIZPointer()); break; } } } } // Titles int iTotalLabels100 = Stats.GetTotalLabelCount() * 100 / iSystemSample; int iTotalLabels = iTotalLabels100 / 100; int iTotalLabelsDecimal = iTotalLabels100 % 100; switch (iType) { case typeSystemLabels: printf("LABEL STATISTICS\n\n"); printf("Average no. of labels per universe: %d.%02d\n\n", iTotalLabels, iTotalLabelsDecimal); break; case typeNodeAttributes: printf("NODE ATTRIBUTES\n\n"); printf("Average no. of nodes per universe: %d.%02d\n\n", iTotalLabels, iTotalLabelsDecimal); break; } // Nodes if (iType != typeNodeDebug) { for (i = 0; i < Stats.GetLabelAttributesCount(); i++) { CString sAttribs; int iCount; Stats.GetLabelAttributes(i, &sAttribs, &iCount); if (bPermutations || strFind(sAttribs, CONSTLIT(",")) == -1) { int iCount100 = iCount * 100 / iSystemSample; int iPercent100 = iCount * 10000 / Stats.GetTotalLabelCount(); printf("%s: %d.%02d (%d.%02d%%)\n", sAttribs.GetASCIIZPointer(), iCount100 / 100, iCount100 % 100, iPercent100 / 100, iPercent100 % 100); } } } }
void TestUpdate (CUniverse &Universe, CXMLElement *pCmdLine) { int i; int iTrial; TArray<DWORD> Trials; DWORD dwLastAverage; // How many tests int iCount = pCmdLine->GetAttributeInteger(CONSTLIT("count")); if (iCount == 0) iCount = 1; // How long do we update int iUpdateCount = pCmdLine->GetAttributeInteger(CONSTLIT("updateCount")); if (iUpdateCount == 0) iUpdateCount = DEFAULT_UPDATE; // Create the fist system for (iTrial = 0; iTrial < iCount; iTrial++) { TArray<SSample> Timings; printf("Trial: %d\n", iTrial + 1); // Initialize the universe CString sError; if (Universe.InitGame(0, &sError) != NOERROR) { printf("ERROR: %s", sError.GetASCIIZPointer()); return; } // Create the first system CTopologyNode *pNode = Universe.GetFirstTopologyNode(); if (pNode == NULL) { printf("ERROR: Cannot find first node.\n"); return; } CSystem *pSystem; if (Universe.CreateStarSystem(pNode, &pSystem) != NOERROR) { printf("ERROR: Unable to create star system.\n"); return; } // Set the POV CSpaceObject *pPOV = pSystem->GetObject(0); Universe.SetPOV(pPOV); pSystem->SetPOVLRS(pPOV); // Prepare system Universe.UpdateExtended(); Universe.GarbageCollectLibraryBitmaps(); Universe.StartGame(true); // Update context SSystemUpdateCtx Ctx; Ctx.bForceEventFiring = true; Ctx.bForcePainted = true; // Update for a while DWORD dwStart = ::GetTickCount(); for (i = 0; i < iUpdateCount; i++) { Universe.Update(Ctx); if (i > 0 && (i % SAMPLE_SIZE) == 0) { DWORD dwEnd = ::GetTickCount(); DWORD dwTime = dwEnd - dwStart; SSample *pSample = Timings.Insert(); pSample->dwTime = dwTime; pSample->iObjCount = GetValidObjCount(pSystem); CString sTime = strFormatMilliseconds(dwTime); CString sObjTime = strFormatMicroseconds(1000 * dwTime / pSample->iObjCount); printf("Objs: %d Total time: %s Per obj: %s\n", pSample->iObjCount, sTime.GetASCIIZPointer(), sObjTime.GetASCIIZPointer()); dwStart = ::GetTickCount(); } } // Compute trial average DWORD dwTotal = 0; DWORD dwAverage = 0; for (i = 0; i < Timings.GetCount(); i++) dwTotal += Timings[i].dwTime; if (Timings.GetCount() > 0) { dwAverage = dwTotal / Timings.GetCount(); CString sTime = strFormatMilliseconds(dwAverage); printf("Trial average: %s\n", sTime.GetASCIIZPointer()); } Trials.Insert(dwAverage); // Compute total average dwTotal = 0; for (i = 0; i < Trials.GetCount(); i++) dwTotal += Trials[i]; dwLastAverage = dwTotal / Trials.GetCount(); CString sTime = strFormatMilliseconds(dwLastAverage); printf("\n"); printf("Running average: %s\n", sTime.GetASCIIZPointer()); printf("\n"); } // Final tally CString sTime = strFormatMilliseconds(dwLastAverage); CString sTime2 = strFormatMicroseconds(1000 * dwLastAverage / SAMPLE_SIZE); printf("Total updates: %d\n", iUpdateCount * iCount); printf("Average time for %d updates: %s\n", SAMPLE_SIZE, sTime.GetASCIIZPointer()); printf("Average time per update: %s\n", sTime2.GetASCIIZPointer()); }
void GenerateStationPlaceSim (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i, j, k; CSovereign *pPlayer = Universe.FindSovereign(g_PlayerSovereignUNID); int iSystemSample = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1); bool bLogo = !pCmdLine->GetAttributeBool(NO_LOGO_SWITCH); // Generate systems for multiple games CSymbolTable AllSystems(TRUE, TRUE); for (i = 0; i < iSystemSample; i++) { if (bLogo) printf("pass %d...\n", i+1); CTopologyNode *pNode = Universe.GetFirstTopologyNode(); while (true) { // Create the system CSystem *pSystem; if (error = Universe.CreateStarSystem(pNode, &pSystem)) { printf("ERROR: Unable to create star system.\n"); return; } // Find this system in the table. SPSimSystemInfo *pSystemEntry; if (error = AllSystems.Lookup(pNode->GetSystemName(), (CObject **)&pSystemEntry)) { pSystemEntry = new SPSimSystemInfo; pSystemEntry->sName = pNode->GetSystemName(); pSystemEntry->iLevel = pNode->GetLevel(); pSystemEntry->dwSystemType = pNode->GetSystemTypeUNID(); pSystemEntry->iCount = 1; for (j = 0; j < DIST_BUCKET_COUNT; j++) pSystemEntry->iEnemies[j] = 0; AllSystems.AddEntry(pSystemEntry->sName, pSystemEntry); } else pSystemEntry->iCount++; // For all active stations in the system, count the number of enemy stations // within certain distance buckets for (j = 0; j < pSystem->GetObjectCount(); j++) { CSpaceObject *pObj = pSystem->GetObject(j); // Find any objects that are lootable by the player if (pObj && pObj->GetCategory() == CSpaceObject::catStation && pObj->CanAttack()) { // Count to see how many enemy stations are in range for (k = 0; k < pSystem->GetObjectCount(); k++) { CSpaceObject *pEnemy = pSystem->GetObject(k); if (pEnemy && pEnemy->GetCategory() == CSpaceObject::catStation && pEnemy->CanAttack() && (pEnemy->IsEnemy(pObj) || pObj->IsEnemy(pEnemy))) { Metric rDist = pObj->GetDistance(pEnemy); int iDist = DistToBucketIndex(rDist); if (iDist != -1) { ASSERT(iDist < DIST_BUCKET_COUNT && iDist >= 0); pSystemEntry->iEnemies[iDist]++; int iLSDist = (int)((rDist / LIGHT_SECOND) + 0.5); if (iLSDist < 30) { printf("%s: %s (%x) and %s (%x) within %d ls\n", pSystem->GetName().GetASCIIZPointer(), pObj->GetNounPhrase().GetASCIIZPointer(), pObj->GetID(), pEnemy->GetNounPhrase().GetASCIIZPointer(), pEnemy->GetID(), iLSDist); } } } } } } // Get the next node CString sEntryPoint; pNode = pSystem->GetStargateDestination(CONSTLIT("Outbound"), &sEntryPoint); if (pNode == NULL || pNode->IsEndGame()) break; // Done with old system Universe.DestroySystem(pSystem); } Universe.Reinit(); } if (bLogo) printf("FINAL SYSTEM STATISTICS\n\n"); // Output total value stats printf("Level\tSystem\t<10 ls\t<25 ls\t<50ls\t<100 ls\n"); int iTotals[DIST_BUCKET_COUNT]; for (i = 0; i < DIST_BUCKET_COUNT; i++) iTotals[i] = 0; for (i = 0; i < AllSystems.GetCount(); i++) { SPSimSystemInfo *pSystemEntry = (SPSimSystemInfo *)AllSystems.GetValue(i); printf("%d\t%s", pSystemEntry->iLevel, pSystemEntry->sName.GetASCIIZPointer()); for (j = 0; j < DIST_BUCKET_COUNT; j++) { printf("\t%.2f", (double)pSystemEntry->iEnemies[j] / (double)pSystemEntry->iCount); iTotals[j] += pSystemEntry->iEnemies[j]; } printf("\n"); } // Totals printf("\n"); printf("Within 10 ls: %.2f\n", iTotals[0] / (double)iSystemSample); printf("Within 25 ls: %.2f\n", iTotals[1] / (double)iSystemSample); printf("Within 50 ls: %.2f\n", iTotals[2] / (double)iSystemSample); printf("Within 100 ls: %.2f\n", iTotals[3] / (double)iSystemSample); printf("\n"); }
void GenerateTypeDependencies (CUniverse &Universe, CXMLElement *pCmdLine) { int i, j; bool bRecursive = pCmdLine->GetAttributeBool(CONSTLIT("recursive")); bool bReverse = pCmdLine->GetAttributeBool(CONSTLIT("reverse")); // Create a reverse index of all type dependencies TSortMap<DWORD, TArray<DWORD> > ReverseIndex; // Types and what they use if (!bReverse) { printf("TYPES AND WHAT THEY USE\n"); printf("-----------------------\n\n"); } for (i = 0; i < Universe.GetDesignTypeCount(); i++) { CDesignType *pType = Universe.GetDesignType(i); if (!bReverse) printf("%s\n", (char *)GetTypeDesc(pType)); // Get the list of UNIDs that this type uses TSortMap<DWORD, bool> TypesUsed; if (bRecursive) AddTypesUsedRecursive(Universe, pType->GetUNID(), &TypesUsed); else pType->AddTypesUsed(&TypesUsed); // Output the list for (j = 0; j < TypesUsed.GetCount(); j++) { CDesignType *pRequired = Universe.FindDesignType(TypesUsed.GetKey(j)); if (pRequired == NULL) continue; if (!bReverse) printf("\t%s\n", (char *)GetTypeDesc(pRequired)); // Add to reverse index TArray<DWORD> *pList = ReverseIndex.SetAt(pRequired->GetUNID()); pList->Insert(pType->GetUNID()); } } // Types and what depends on them if (bReverse) { printf("\nTYPES AND WHAT USES THEM\n"); printf( "------------------------\n\n"); for (i = 0; i < ReverseIndex.GetCount(); i++) { CDesignType *pType = Universe.FindDesignType(ReverseIndex.GetKey(i)); if (pType == NULL) continue; printf("%s\n", (char *)GetTypeDesc(pType)); TArray<DWORD> &List = ReverseIndex.GetValue(i); for (j = 0; j < List.GetCount(); j++) { CDesignType *pRequiredBy = Universe.FindDesignType(List[j]); if (pRequiredBy) printf("\t%s\n", (char *)GetTypeDesc(pRequiredBy)); } } } }
void GenerateShipTable (CUniverse &Universe, CXMLElement *pCmdLine, CIDTable &EntityTable) { int i, j; // Some options bool bAllClasses = (pCmdLine->GetAttributeBool(CONSTLIT("allClasses")) || pCmdLine->GetAttributeBool(CONSTLIT("all"))); // Get the criteria from the command line. Always append 's' because we // want ship classes. CString sCriteria = strPatternSubst(CONSTLIT("%s s"), pCmdLine->GetAttribute(CONSTLIT("criteria"))); CDesignTypeCriteria Criteria; if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR) { printf("ERROR: Unable to parse criteria.\n"); return; } // Generate a list of columns to display TArray<CString> Cols; Cols.Insert(FIELD_LEVEL); Cols.Insert(FIELD_NAME); for (i = 0; i < pCmdLine->GetAttributeCount(); i++) { CString sAttrib = pCmdLine->GetAttributeName(i); if (strEquals(sAttrib, FIELD_BALANCE)) { Cols.Insert(CONSTLIT("balanceType")); Cols.Insert(CONSTLIT("combatStrength")); Cols.Insert(CONSTLIT("damage")); Cols.Insert(CONSTLIT("defenseStrength")); } else if (!IsMainCommandParam(sAttrib) && !strEquals(sAttrib, CONSTLIT("shiptable"))) { CString sValue = pCmdLine->GetAttribute(i); if (!strEquals(sValue, CONSTLIT("true"))) Cols.Insert(strPatternSubst(CONSTLIT("%s:%s"), sAttrib, sValue)); else Cols.Insert(sAttrib); } } // Output the header for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); printf(Cols[j].GetASCIIZPointer()); } printf("\n"); // Generate a table CSymbolTable Table(FALSE, TRUE); // Loop over all items that match and add them to // a sorted table. for (i = 0; i < Universe.GetShipClassCount(); i++) { CShipClass *pClass = Universe.GetShipClass(i); // Only include generic classes unless otherwise specified if (!bAllClasses && !pClass->HasLiteralAttribute(CONSTLIT("genericClass"))) continue; if (!pClass->MatchesCriteria(Criteria)) continue; // Figure out the sort order char szBuffer[1024]; wsprintf(szBuffer, "%04d%s%d", pClass->GetLevel(), pClass->GetNounPhrase(0).GetASCIIZPointer(), pClass->GetUNID()); Table.AddEntry(CString(szBuffer), (CObject *)pClass); } // Output table for (i = 0; i < Table.GetCount(); i++) { CShipClass *pClass = (CShipClass *)Table.GetValue(i); // Output each row for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); const CString &sField = Cols[j]; CString sValue; if (strEquals(sField, FIELD_ENTITY)) { CString *pValue; if (EntityTable.Lookup(pClass->GetUNID(), (CObject **)&pValue) == NOERROR) sValue = *pValue; else sValue = CONSTLIT("?"); } else sValue = pClass->GetDataField(sField); if (strEquals(sField, FIELD_MANEUVER) || strEquals(sField, FIELD_THRUST_TO_WEIGHT)) printf("%.1f", strToInt(sValue, 0, NULL) / 1000.0); else if (strEquals(sField, FIELD_SCORE_CALC)) printf("%d", pClass->CalcScore()); else printf(sValue.GetASCIIZPointer()); } printf("\n"); } printf("\n"); }
void GenerateSnapshot (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i; // Get some parameters int iInitialUpdateTime = 10; int iUpdateTime = pCmdLine->GetAttributeInteger(CONSTLIT("wait")); // Criteria CString sNode = pCmdLine->GetAttribute(CONSTLIT("node")); CString sCriteria = pCmdLine->GetAttribute(CONSTLIT("criteria")); // Output int cxWidth; int cyHeight; if (pCmdLine->FindAttributeInteger(CONSTLIT("size"), &cxWidth)) { cyHeight = cxWidth; } else { cxWidth = 1024; cyHeight = 1024; } // Paint flags DWORD dwPaintFlags = 0; if (pCmdLine->GetAttributeBool(CONSTLIT("noStars"))) dwPaintFlags |= CSystem::VWP_NO_STAR_FIELD; // Output file CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output")); if (!sFilespec.IsBlank()) sFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp")); // Update context SSystemUpdateCtx Ctx; Ctx.bForceEventFiring = true; Ctx.bForcePainted = true; // Loop over all systems until we find what we're looking for int iLoops = 20; int iNodeIndex = 0; CTopologyNode *pNode = Universe.GetTopologyNode(iNodeIndex); while (true) { // Create the system CSystem *pSystem; if (error = Universe.CreateStarSystem(pNode, &pSystem)) { printf("ERROR: Unable to create star system.\n"); return; } // If this is the node we want, then search CSpaceObject *pTarget; if (sNode.IsBlank() || strEquals(sNode, pNode->GetID())) { printf("Searching %s...\n", pNode->GetSystemName().GetASCIIZPointer()); // Set the POV CSpaceObject *pPOV = pSystem->GetObject(0); Universe.SetPOV(pPOV); pSystem->SetPOVLRS(pPOV); // Prepare system Universe.UpdateExtended(); Universe.GarbageCollectLibraryBitmaps(); // Update for a while for (i = 0; i < iInitialUpdateTime; i++) Universe.Update(Ctx); // Compose the criteria CSpaceObject::Criteria Criteria; CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria); // Get the list of all objects in the system that match the criteria CSpaceObject::SCriteriaMatchCtx Ctx(Criteria); TArray<CSpaceObject *> Results; for (i = 0; i < pSystem->GetObjectCount(); i++) { CSpaceObject *pObj = pSystem->GetObject(i); if (pObj && pObj->MatchesCriteria(Ctx, Criteria)) Results.Insert(pObj); } // Pick the appropriate object from the list if (Results.GetCount() == 0) pTarget = NULL; else if (Criteria.bNearestOnly || Criteria.bFarthestOnly) pTarget = Ctx.pBestObj; else pTarget = Results[mathRandom(0, Results.GetCount() - 1)]; } else pTarget = NULL; // If we found the target, then output if (pTarget) { // If we found the target, take a snapshot printf("Found %s.\n", pTarget->GetNounPhrase(0).GetASCIIZPointer()); // Wait a bit for (i = 0; i < iUpdateTime; i++) { if ((i % 100) == 99) printf("."); Universe.Update(Ctx); } if (iUpdateTime >= 99) printf("\n"); // Paint CG16bitImage Output; Output.CreateBlank(cxWidth, cyHeight, false); RECT rcViewport; rcViewport.left = 0; rcViewport.top = 0; rcViewport.right = cxWidth; rcViewport.bottom = cyHeight; pSystem->PaintViewport(Output, rcViewport, pTarget, dwPaintFlags); // Write to file if (!sFilespec.IsBlank()) { CFileWriteStream OutputFile(sFilespec); if (OutputFile.Create() != NOERROR) { printf("ERROR: Unable to create '%s'\n", sFilespec.GetASCIIZPointer()); return; } Output.WriteToWindowsBMP(&OutputFile); OutputFile.Close(); printf("%s\n", sFilespec.GetASCIIZPointer()); } // Otherwise, clipboard else { if (error = Output.CopyToClipboard()) { printf("ERROR: Unable to copy image to clipboard.\n"); return; } printf("Image copied to clipboard.\n"); } // Done break; } // Done with old system Universe.DestroySystem(pSystem); // Loop to the next node do { iNodeIndex = ((iNodeIndex + 1) % Universe.GetTopologyNodeCount()); pNode = Universe.GetTopologyNode(iNodeIndex); } while (pNode == NULL || pNode->IsEndGame()); // If we're back to the first node again, restart if (iNodeIndex == 0) { if (--iLoops > 0) { Universe.Reinit(); iNodeIndex = 0; pNode = Universe.GetTopologyNode(iNodeIndex); } else { printf("ERROR: Specified target could not be found.\n"); return; } } } }
void GenerateSimTables (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i, j; int iSystemSample = pCmdLine->GetAttributeInteger(CONSTLIT("count")); if (iSystemSample == 0) iSystemSample = DEFAULT_SYSTEM_SAMPLE; // Generate systems for multiple games CSymbolTable AllSystems(TRUE, TRUE); for (i = 0; i < iSystemSample; i++) { printf("sample %d...\n", i+1); CTopologyNode *pNode = Universe.GetFirstTopologyNode(); while (true) { // Create the system CSystem *pSystem; if (error = Universe.CreateStarSystem(pNode, &pSystem)) { printf("ERROR: Unable to create star system.\n"); return; } // Find this system in the table. SystemInfo *pSystemEntry; if (error = AllSystems.Lookup(pNode->GetSystemName(), (CObject **)&pSystemEntry)) { pSystemEntry = new SystemInfo; pSystemEntry->sName = pNode->GetSystemName(); pSystemEntry->iLevel = pNode->GetLevel(); pSystemEntry->dwSystemType = pNode->GetSystemDescUNID(); pSystemEntry->iCount = 1; AllSystems.AddEntry(pSystemEntry->sName, pSystemEntry); } else pSystemEntry->iCount++; // Add the encounters to the appropriate tables for (j = 0; j < pSystem->GetObjectCount(); j++) { CSpaceObject *pObj = pSystem->GetObject(j); if (pObj) { // Add this encounter to the table CStationType *pType; if (pType = pObj->GetEncounterInfo()) { CString sKey = strFromInt(pType->GetUNID(), false); // See if we have this type in the table StationInfo *pEntry; if (error = pSystemEntry->Stations.Lookup(sKey, (CObject **)&pEntry)) { pEntry = new StationInfo; pEntry->pType = pType; pEntry->iSystemCount = 0; pEntry->iTotalCount = 1; pSystemEntry->Stations.AddEntry(sKey, pEntry); } else pEntry->iTotalCount++; } // Enumerate the items in this object CItemListManipulator ItemList(pObj->GetItemList()); ItemList.ResetCursor(); while (ItemList.MoveCursorForward()) { const CItem &Item(ItemList.GetItemAtCursor()); if (!Item.IsInstalled() && !Item.IsDamaged()) { CString sKey = strFromInt(Item.GetType()->GetUNID(), false); // Find the item type in the table ItemInfo *pEntry; if (error = pSystemEntry->Items.Lookup(sKey, (CObject **)&pEntry)) { pEntry = new ItemInfo; pEntry->pType = Item.GetType(); pEntry->iTotalCount = Item.GetCount(); pSystemEntry->Items.AddEntry(sKey, pEntry); } else pEntry->iTotalCount += Item.GetCount(); } } } } // Get the next node CString sEntryPoint; pNode = pSystem->GetStargateDestination(CONSTLIT("Outbound"), &sEntryPoint); if (pNode == NULL || pNode->IsEndGame()) break; // Done with old system Universe.DestroySystem(pSystem); } Universe.Reinit(); } // Output if (error = OutputItemTable(AllSystems, iSystemSample)) return; if (error = OutputEncounterTable(AllSystems, iSystemSample)) return; // Create a table with the sum of all items for the game printf("Total count statistic computed.\n"); }
void GenerateRandomItemTables (CUniverse &Universe, CXMLElement *pCmdLine) { int i; printf("RANDOM ITEM TABLES\n\n"); // Create a sorted list of item types CSymbolTable SortedList(FALSE, TRUE); for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pType = Universe.GetItemType(i); SortedList.AddEntry(pType->GetSortName(), (CObject *)pType); } // Create the tables for (int iLevel = 1; iLevel <= MAX_ITEM_LEVEL; iLevel += 2) { for (TableTypes iTable = tableTypesFirst; iTable <= tableTypesCount; iTable = (enum TableTypes)((int)iTable + 1)) { int iCount = 0; ItemEntry Table[100]; // Fill the table with entries for each // item at this level for (i = 0; i < SortedList.GetCount(); i++) { CItemType *pType = (CItemType *)SortedList.GetValue(i); int iScore; if (iCount < 100 && ItemInTable(pType, iTable, iLevel, &iScore)) { Table[iCount].pType = pType; Table[iCount].iScore = iScore; iCount++; } } // Compute total score int iTotalScore = 0; for (i = 0; i < iCount; i++) iTotalScore += Table[i].iScore; // Compute chance for (i = 0; i < iCount; i++) { Table[i].iChance = (Table[i].iScore * 100) / iTotalScore; Table[i].iRemainder = (Table[i].iScore * 100) % iTotalScore; } // Compute remainder int iTotalChance = 0; for (i = 0; i < iCount; i++) iTotalChance += Table[i].iChance; while (iTotalChance < 100) { int iBestRemainder = 0; int iBestEntry = -1; for (i = 0; i < iCount; i++) if (Table[i].iRemainder > iBestRemainder) { iBestRemainder = Table[i].iRemainder; iBestEntry = i; } Table[iBestEntry].iChance++; Table[iBestEntry].iRemainder = 0; iTotalChance++; } // Title if (iCount > 0) { switch (iTable) { case tableArmorAndWeapons: printf("LEVEL %d: ARMOR AND WEAPONS\n\n", iLevel); break; case tableMiscItems: printf("LEVEL %d: MISCELLANEOUS ITEMS\n\n", iLevel); break; case tableUsefulItems: printf("LEVEL %d: USEFUL ITEMS\n\n", iLevel); break; } // Print table for (i = 0; i < iCount; i++) if (Table[i].iChance > 0) { //DWORD dwFlags; printf("%d\t%s\n", Table[i].iChance, //Table[i].pType->GetName(&dwFlags, true).GetASCIIZPointer()); Table[i].pType->GetSortName().GetASCIIZPointer()); } printf("\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 GenerateTypeTable (CUniverse &Universe, CXMLElement *pCmdLine) { int i, j; // Get the criteria from the command line. CString sCriteria = pCmdLine->GetAttribute(CRITERIA_ATTRIB); // Parse it CDesignTypeCriteria Criteria; if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR) { printf("ERROR: Unable to parse criteria.\n"); return; } // Generate a table of all matching types TSortMap<CString, CDesignType *> Table; // Loop over all items for this level and add them to // a sorted table. for (i = 0; i < Universe.GetDesignTypeCount(); i++) { CDesignType *pType = Universe.GetDesignType(i); int iLevel = pType->GetLevel(); if (!pType->MatchesCriteria(Criteria)) continue; // Get the name 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%08x", iLevel, sName.GetASCIIZPointer(), pType->GetUNID()); Table.Insert(CString(szBuffer), pType); } // Generate a list of columns to display TArray<CString> Cols; Cols.Insert(FIELD_LEVEL); Cols.Insert(FIELD_NAME); for (i = 0; i < pCmdLine->GetAttributeCount(); i++) { CString sAttrib = pCmdLine->GetAttributeName(i); if (!IsMainCommandParam(sAttrib) && !strEquals(sAttrib, CONSTLIT("typetable"))) { 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 (LoadDesignTypeStats(Universe.GetDesignCollection().GetAdventureUNID(), &TotalCount) != NOERROR) { printf("ERROR: Unable to load type count table.\n"); 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 CCodeChainCtx CCCtx; for (i = 0; i < Table.GetCount(); i++) { CDesignType *pType = Table[i]; for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); const CString &sField = Cols[j]; // Format and output 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 { ICCItem *pResult = pType->GetProperty(CCCtx, sField); CString sValue = pResult->Print(&g_pUniverse->GetCC(), PRFLAG_NO_QUOTES | PRFLAG_ENCODE_FOR_DISPLAY); pResult->Discard(&g_pUniverse->GetCC()); printf(sValue.GetASCIIZPointer()); } } printf("\n"); } printf("\n"); } else printf("No entries match criteria.\n"); }
void GenerateTopologyMap (CUniverse &Universe, CXMLElement *pCmdLine) { int i, j; STopologyMapCtx Ctx; // Initialize the output COutputChart Output; Output.SetStyleFont(STYLE_NAME, pCmdLine->GetAttribute(CONSTLIT("font"))); Output.SetStyleColor(STYLE_NAME, CG32bitPixel(0xFF, 0xFF, 0xFF)); Output.SetOutputFilespec(pCmdLine->GetAttribute(CONSTLIT("output"))); // Get the topology node CTopologyNode *pFirstNode = Universe.GetFirstTopologyNode(); if (pFirstNode == NULL) { printf("ERROR: Unable to find topology node.\n"); return; } // Get the system map for the node Ctx.pMap = pFirstNode->GetDisplayPos(); if (Ctx.pMap == NULL) { printf("ERROR: No system map for node %s.\n", pFirstNode->GetID().GetASCIIZPointer()); return; } // Create a background image CG32bitImage *pImage = Ctx.pMap->CreateBackgroundImage(); // Create the output Output.SetContentSize((pImage ? pImage->GetWidth() : 1024), (pImage ? pImage->GetHeight() : 1024)); CG32bitImage &Dest = Output.GetOutputImage(); // Blt if (pImage) Dest.Blt(0, 0, pImage->GetWidth(), pImage->GetHeight(), *pImage, 0, 0); // Done with background image delete pImage; pImage = NULL; // Compute the size of the map (in pixels) Ctx.cxMap = Dest.GetWidth(); Ctx.cyMap = Dest.GetHeight(); Ctx.xCenter = Ctx.cxMap / 2; Ctx.yCenter = Ctx.cyMap / 2; // Loop over all nodes and clear marks on the ones that we need to draw for (i = 0; i < Universe.GetTopologyNodeCount(); i++) { CTopologyNode *pNode = Universe.GetTopologyNode(i); int xPos, yPos; pNode->SetMarked(pNode->GetDisplayPos(&xPos, &yPos) != Ctx.pMap || pNode->IsEndGame()); } // Paint the nodes for (i = 0; i < Universe.GetTopologyNodeCount(); i++) { CTopologyNode *pNode = Universe.GetTopologyNode(i); if (!pNode->IsMarked()) { int xPos, yPos; pNode->GetDisplayPos(&xPos, &yPos); // Convert to view coordinates int x = Ctx.xCenter + xPos; int y = Ctx.yCenter - yPos; // Draw gate connections for (j = 0; j < pNode->GetStargateCount(); j++) { CTopologyNode *pDestNode = pNode->GetStargateDest(j); if (pDestNode && !pDestNode->IsMarked()) { int xPos, yPos; pDestNode->GetDisplayPos(&xPos, &yPos); int xDest = Ctx.xCenter + xPos; int yDest = Ctx.yCenter - yPos; Dest.DrawLine(x, y, xDest, yDest, STARGATE_LINE_WIDTH, STARGATE_LINE_COLOR); } } // Draw star system DrawNode(Ctx, Output, pNode, x, y); pNode->SetMarked(); } } // Done Output.Output(); }
void GenerateTypeIslands (CUniverse &Universe, CXMLElement *pCmdLine) { int i, j; bool bExcludeImages = true; printf("TYPE ISLANDS\n"); printf("------------\n\n"); // Make a list of default types #if 0 g_DefaultTypes.SetAt(0x00001001, true); // independent sovereign g_DefaultTypes.SetAt(0x00001002, true); // Commonwealth sovereign g_DefaultTypes.SetAt(0x00001003, true); // independent sovereign g_DefaultTypes.SetAt(0x00001007, true); // ares sovereign g_DefaultTypes.SetAt(0x0000100c, true); // sung slavers sovereign g_DefaultTypes.SetAt(0x0000100f, true); // auton sovereign g_DefaultTypes.SetAt(0x00001011, true); // corporate hierarchy g_DefaultTypes.SetAt(0x00004027, true); // container of frozen supplies g_DefaultTypes.SetAt(0x0000402c, true); // pteracnium ore g_DefaultTypes.SetAt(0x000040ae, true); // helium3 reactor assembly g_DefaultTypes.SetAt(0x000040af, true); // pteracnium fuel g_DefaultTypes.SetAt(0x000040ca, true); // lancer cannon g_DefaultTypes.SetAt(0x000040e2, true); // worldship armor g_DefaultTypes.SetAt(0x00004100, true); // xenotite ore g_DefaultTypes.SetAt(0x00004109, true); // SN2500 reactor g_DefaultTypes.SetAt(0x00004167, true); // tetramite ore g_DefaultTypes.SetAt(0x00005004, true); // wreck ejecta g_DefaultTypes.SetAt(0x0000500c, true); // blast explosion 2 g_DefaultTypes.SetAt(0x0000500d, true); // blast explosion 3 g_DefaultTypes.SetAt(0x0000500e, true); // blast explosion 4 g_DefaultTypes.SetAt(0x0000500f, true); // thermo explosion 1 g_DefaultTypes.SetAt(0x00005011, true); // thermo explosion 3 g_DefaultTypes.SetAt(0x00005012, true); // thermo explosion 4 g_DefaultTypes.SetAt(0x00009004, true); // shield effect g_DefaultTypes.SetAt(0x00009007, true); // explosion effect g_DefaultTypes.SetAt(0x0000900a, true); // fire effect g_DefaultTypes.SetAt(0x0000A003, true); // dsAbandonedStation g_DefaultTypes.SetAt(0x0000a017, true); // dock screen? g_DefaultTypes.SetAt(0x001a200c, true); // wreck of the CSC Europa g_DefaultTypes.SetAt(0x001a200e, true); // sandstorm wreck g_DefaultTypes.SetAt(0x001c1002, true); // ares sect in Heretic g_DefaultTypes.SetAt(0x08020102, true); // huari empire sovereign g_DefaultTypes.SetAt(0x08040140, true); // gaian processor station #endif // Create a reverse index of all type dependencies ReverseIndexMap ReverseIndex; for (i = 0; i < Universe.GetDesignTypeCount(); i++) { CDesignType *pType = Universe.GetDesignType(i); // Get the list of UNIDs that this type uses TSortMap<DWORD, bool> TypesUsed; pType->AddTypesUsed(&TypesUsed); for (j = 0; j < TypesUsed.GetCount(); j++) { CDesignType *pRequired = Universe.FindDesignType(TypesUsed.GetKey(j)); if (pRequired == NULL) continue; // Add to reverse index TArray<DWORD> *pList = ReverseIndex.SetAt(pRequired->GetUNID()); pList->Insert(pType->GetUNID()); } } // We create a list of islands. In each island, all the types refer to // each other and don't refer to types on any other island. TArray<IslandMap> AllIslands; // Loop over all types and add them to an island. for (i = 0; i < Universe.GetDesignTypeCount(); i++) { CDesignType *pType = Universe.GetDesignType(i); // Exclude images if (bExcludeImages && pType->GetType() == designImage) continue; if (pType->GetType() == designShipTable) continue; // Exclude default types if (g_DefaultTypes.Find(pType->GetUNID())) continue; // If this type is already on one of the islands, then we skip it. #if 0 bool bFound = false; for (j = 0; j < AllIslands.GetCount(); j++) if (AllIslands[j].Find(pType->GetUNID())) { bFound = true; break; } if (bFound) continue; #endif // Since this type is not on any island, we add start a new island and // add all related types to it. IslandMap *pIsland = AllIslands.Insert(); AddTypeToIsland(Universe, ReverseIndex, pIsland, pType); // Print printf("ISLAND %s\n", (char *)GetTypeDesc(pType)); for (j = 0; j < pIsland->GetCount(); j++) { CDesignType *pType = Universe.FindDesignType(pIsland->GetKey(j)); if (pType == NULL) continue; printf("%s\n", (char *)GetTypeDesc(pType)); } printf("\n"); } }
void GenerateEncounterCount (CUniverse &Universe, CXMLElement *pCmdLine) { int i, j, k, l; // Options int iSystemSample = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1); bool bLogo = !pCmdLine->GetAttributeBool(CONSTLIT("noLogo")); bool bAll = pCmdLine->GetAttributeBool(CONSTLIT("all")); // 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("encountercount"))) { 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 TSortMap<CString, SNodeDesc> NodeTable; 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) != NOERROR) { printf("ERROR: Unable to create star system.\n"); return; } // Create a sort string for this system CString sSort = strPatternSubst(CONSTLIT("%02d-%s"), pSystem->GetLevel(), pNode->GetID()); // Get the table bool bNew; SNodeDesc *pResult = NodeTable.SetAt(sSort, &bNew); if (bNew) { pResult->iLevel = pNode->GetLevel(); pResult->sNodeID = pNode->GetID(); } // Accumulate data AddSystemData(pSystem, bAll, pResult); // Done with old system Universe.DestroySystem(pSystem); } Universe.Reinit(); } // Header printf("Level\tNode\tSystemType\tCategory\tSovereign\tEncounter\tCount"); for (i = 0; i < Cols.GetCount(); i++) printf("\t%s", Cols[i].GetASCIIZPointer()); printf("\n"); // Output all rows for (i = 0; i < NodeTable.GetCount(); i++) { for (j = 0; j < NodeTable[i].Table.GetCount(); j++) { CCountTable &Encounters = NodeTable[i].Table[j]; for (k = 0; k < Encounters.GetCount(); k++) { int iCount = Encounters[k] / iSystemSample; int iCountFrac = 1000 * (Encounters[k] % iSystemSample) / iSystemSample; CStationType *pEncounterType = Universe.FindStationType(Encounters.GetKey(k)); if (pEncounterType == NULL) continue; CSovereign *pSovereign = pEncounterType->GetControllingSovereign(); CString sSovereign = (pSovereign ? pSovereign->GetTypeName() : CONSTLIT("(Unknown)")); printf("%d\t%s\t0x%08x\t%s\t%s\t%s\t%d.%03d", NodeTable[i].iLevel, NodeTable[i].sNodeID.GetASCIIZPointer(), NodeTable[i].Table.GetKey(j), pEncounterType->GetDataField(CONSTLIT("category")).GetASCIIZPointer(), sSovereign.GetASCIIZPointer(), pEncounterType->GetName().GetASCIIZPointer(), iCount, iCountFrac); for (l = 0; l < Cols.GetCount(); l++) { CString sValue = pEncounterType->GetDataField(Cols[l]); printf("\t%s", sValue.GetASCIIZPointer()); } printf("\n"); } } } }
void GenerateStationFrequencyTable (CUniverse &Universe, CXMLElement *pCmdLine) { int i, j; printf("STATION FREQUENCY TABLE\n\n"); // Figure out which columns to show TArray<CString> Cols; Cols.Insert(CONSTLIT("Level")); Cols.Insert(CONSTLIT("Freq")); Cols.Insert(CONSTLIT("Name")); Cols.Insert(CONSTLIT("Type")); Cols.Insert(CONSTLIT("Environment")); // Print the header for (i = 0; i < Cols.GetCount(); i++) { if (i != 0) printf("\t"); printf("%s", (LPSTR)Cols[i]); } printf("\n"); // For all levels, 1-25 int iLevel; for (iLevel = 1; iLevel <= MAX_ITEM_LEVEL; iLevel++) { CSymbolTable Sort(FALSE, TRUE); // Find all stations for this level and add them to // a sorting table for (i = 0; i < Universe.GetStationTypeCount(); i++) { CStationType *pType = Universe.GetStationType(i); if (pType->GetFrequencyByLevel(iLevel) > 0) { char szBuffer[256]; wsprintf(szBuffer, "%02d %s", ftCommon - pType->GetFrequencyByLevel(iLevel), pType->GetName().GetASCIIZPointer()); Sort.AddEntry(CString(szBuffer), (CObject *)pType); } } // Print out the stations for this level if (Sort.GetCount() > 0) { for (i = 0; i < Sort.GetCount(); i++) { CStationType *pType = (CStationType *)Sort.GetValue(i); for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); if (strEquals(Cols[j], CONSTLIT("Level"))) printf("%d", iLevel); else if (strEquals(Cols[j], CONSTLIT("Freq"))) printf((LPSTR)FrequencyChar(pType->GetFrequencyByLevel(iLevel))); else if (strEquals(Cols[j], CONSTLIT("Name"))) printf((LPSTR)pType->GetName()); else if (strEquals(Cols[j], CONSTLIT("Type"))) { if (pType->HasAttribute(CONSTLIT("enemy"))) printf("Enemy"); else if (pType->HasAttribute(CONSTLIT("debris"))) printf("Debris"); else printf("Friend"); } else if (strEquals(Cols[j], CONSTLIT("Environment"))) { bool bElements = false; if (pType->HasAttribute(CONSTLIT("envAir"))) { if (bElements) printf(", "); printf("envAir"); bElements = true; } if (pType->HasAttribute(CONSTLIT("envEarth"))) { if (bElements) printf(", "); printf("envEarth"); bElements = true; } if (pType->HasAttribute(CONSTLIT("envFire"))) { if (bElements) printf(", "); printf("envFire"); bElements = true; } if (pType->HasAttribute(CONSTLIT("envWater"))) { if (bElements) printf(", "); printf("envWater"); bElements = true; } if (!bElements) printf("None"); } } printf("\n"); } } } }
void DoTradeSim (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i, j; CSovereign *pPlayer = Universe.FindSovereign(g_PlayerSovereignUNID); int iSystemSample = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1); bool bLogo = !pCmdLine->GetAttributeBool(NO_LOGO_SWITCH); // For each station type we keep track of the items that it sells and the // various prices that each instances charges. SStationData AllStations; // For each item type we keep track of the stations that sell and/or // buy it. SItemData AllItems; // Generate systems for multiple games for (i = 0; i < iSystemSample; i++) { if (bLogo) printf("pass %d...\n", i+1); CTopologyNode *pNode = Universe.GetFirstTopologyNode(); while (true) { // Create the system CSystem *pSystem; if (error = Universe.CreateStarSystem(pNode, &pSystem)) { printf("ERROR: Unable to create star system.\n"); return; } // For all active stations in the system, get their trading information for (j = 0; j < pSystem->GetObjectCount(); j++) { CSpaceObject *pObj = pSystem->GetObject(j); if (pObj && pObj->GetCategory() == CSpaceObject::catStation) CompileTradeData(pObj, &AllStations, &AllItems); } // Get the next node CString sEntryPoint; pNode = pSystem->GetStargateDestination(CONSTLIT("Outbound"), &sEntryPoint); if (pNode == NULL || pNode->IsEndGame()) break; // Done with old system Universe.DestroySystem(pSystem); } Universe.Reinit(); } if (bLogo) printf("FINAL STATISTICS\n\n"); // Loop over each item and output the best trading strategy printf("Item\tSeller\tSell Price\tBuyer\tBuy Price\tProfit\n"); for (i = 0; i < AllItems.GetCount(); i++) { ComputeAverages(&AllItems[i]); OutputTradingStrategy(AllItems[i]); } }
void GenerateImageChart (CUniverse &Universe, CXMLElement *pCmdLine) { int i; enum OrderTypes { orderSmallest = 1, orderLargest = 2, orderName = 3, orderLevel = 4, orderSovereign = 5, orderManufacturer = 6, }; // Item criteria bool bHasItemCriteria; CString sCriteria; CItemCriteria ItemCriteria; if (bHasItemCriteria = pCmdLine->FindAttribute(CONSTLIT("itemCriteria"), &sCriteria)) CItem::ParseCriteria(sCriteria, &ItemCriteria); else CItem::InitCriteriaAll(&ItemCriteria); // Get the criteria from the command line. CDesignTypeCriteria Criteria; if (pCmdLine->FindAttribute(CONSTLIT("criteria"), &sCriteria)) { if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR) { printf("ERROR: Unable to parse criteria.\n"); return; } } else if (bHasItemCriteria) { if (CDesignTypeCriteria::ParseCriteria(CONSTLIT("i"), &Criteria) != NOERROR) { printf("ERROR: Unable to parse criteria.\n"); return; } } else { printf("ERROR: Expected criteria.\n"); return; } bool bAll = pCmdLine->GetAttributeBool(CONSTLIT("all")); // Options bool bTextBoxesOnly = pCmdLine->GetAttributeBool(CONSTLIT("textBoxesOnly")); bool bFieldUNID = pCmdLine->GetAttributeBool(CONSTLIT("unid")); // Figure out what order we want CString sOrder = pCmdLine->GetAttribute(CONSTLIT("sort")); int iOrder; if (strEquals(sOrder, CONSTLIT("smallest"))) iOrder = orderSmallest; else if (strEquals(sOrder, CONSTLIT("largest"))) iOrder = orderLargest; else if (strEquals(sOrder, CONSTLIT("level"))) iOrder = orderLevel; else if (strEquals(sOrder, CONSTLIT("sovereign"))) iOrder = orderSovereign; else if (strEquals(sOrder, CONSTLIT("manufacturer"))) iOrder = orderManufacturer; else iOrder = orderName; bool b3DGrid = pCmdLine->GetAttributeBool(CONSTLIT("3DGrid")); bool bDockingPorts = pCmdLine->GetAttributeBool(CONSTLIT("portPos")); bool bDevicePos = pCmdLine->GetAttributeBool(CONSTLIT("devicePos")); // Image size int cxDesiredWidth; if (pCmdLine->FindAttributeInteger(CONSTLIT("width"), &cxDesiredWidth)) cxDesiredWidth = Max(512, cxDesiredWidth); else cxDesiredWidth = 1280; // Spacing int cxSpacing = pCmdLine->GetAttributeInteger(CONSTLIT("xSpacing")); int cxExtraMargin = pCmdLine->GetAttributeInteger(CONSTLIT("xMargin")); int cxImageMargin = 2 * pCmdLine->GetAttributeInteger(CONSTLIT("xImageMargin")); // Font for text CString sTypeface; int iSize; bool bBold; bool bItalic; if (!CG16bitFont::ParseFontDesc(pCmdLine->GetAttribute(CONSTLIT("font")), &sTypeface, &iSize, &bBold, &bItalic)) { sTypeface = CONSTLIT("Arial"); iSize = 10; bBold = false; bItalic = false; } CG16bitFont NameFont; NameFont.Create(sTypeface, -PointsToPixels(iSize), bBold, bItalic); CG32bitPixel rgbNameColor = CG32bitPixel(255, 255, 255); // Rotation int iRotation = pCmdLine->GetAttributeInteger(CONSTLIT("rotation")); // Output file CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output")); if (!sFilespec.IsBlank()) sFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp")); // Generate a sorted table of types TSortMap<CString, SEntryDesc> Table; for (i = 0; i < Universe.GetDesignTypeCount(); i++) { CDesignType *pType = Universe.GetDesignType(i); SEntryDesc NewEntry; // Make sure we match the criteria if (!pType->MatchesCriteria(Criteria)) continue; // Figure stuff stuff out based on the specific design type switch (pType->GetType()) { case designItemType: { CItemType *pItemType = CItemType::AsType(pType); CItem Item(pItemType, 1); // Skip if not in item criteria if (!Item.MatchesCriteria(ItemCriteria)) continue; // Skip virtual classes if (pItemType->IsVirtual()) continue; // Initialize the entry NewEntry.pType = pType; NewEntry.sName = pItemType->GetNounPhrase(0); NewEntry.pImage = &pItemType->GetImage(); NewEntry.iSize = RectWidth(NewEntry.pImage->GetImageRect()); break; } case designShipClass: { CShipClass *pClass = CShipClass::AsType(pType); // Skip non-generic classess if (!bAll && !pClass->HasLiteralAttribute(CONSTLIT("genericClass"))) continue; // Initialize the entry NewEntry.pType = pType; NewEntry.sName = pClass->GetNounPhrase(0); NewEntry.iSize = RectWidth(pClass->GetImage().GetImageRect()); NewEntry.pImage = &pClass->GetImage(); NewEntry.iRotation = pClass->Angle2Direction(iRotation); NewEntry.sSovereignName = (pClass->GetDefaultSovereign() ? pClass->GetDefaultSovereign()->GetTypeNounPhrase() : NULL_STR); break; } case designStationType: { CStationType *pStationType = CStationType::AsType(pType); // Skip generic classes if (!bAll && !pStationType->HasLiteralAttribute(CONSTLIT("generic"))) continue; NewEntry.pType = pType; NewEntry.sName = pStationType->GetNounPhrase(0); NewEntry.iSize = pStationType->GetSize(); NewEntry.sSovereignName = (pStationType->GetSovereign() ? pStationType->GetSovereign()->GetTypeNounPhrase() : NULL_STR); InitStationTypeImage(NewEntry, pStationType); break; } default: // Don't know how to handle this type continue; break; } // Adjust name if (bFieldUNID) NewEntry.sName = strPatternSubst(CONSTLIT("%s (%x)"), NewEntry.sName, NewEntry.pType->GetUNID()); // Compute the sort key char szBuffer[1024]; switch (iOrder) { case orderLargest: wsprintf(szBuffer, "%09d%s%x", 1000000 - NewEntry.iSize, NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); break; case orderLevel: wsprintf(szBuffer, "%09d%s%x", pType->GetLevel(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); break; case orderSmallest: wsprintf(szBuffer, "%09d%s%x", NewEntry.iSize, NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); break; case orderSovereign: wsprintf(szBuffer, "%s|%s|%x", NewEntry.sSovereignName.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); NewEntry.sCategorize = NewEntry.sSovereignName; break; case orderManufacturer: { CString sManufacturer = NewEntry.pType->GetPropertyString(CONSTLIT("manufacturer")); wsprintf(szBuffer, "%s|%s|%x", sManufacturer.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); NewEntry.sCategorize = sManufacturer; break; } default: wsprintf(szBuffer, "%s%x", NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); break; } // Add to list Table.Insert(CString(szBuffer), NewEntry); } // Allocate an arranger that tracks where to paint each world. CImageArranger Arranger; // Settings for the overall arrangement CImageArranger::SArrangeDesc Desc; Desc.cxDesiredWidth = Max(512, cxDesiredWidth - (2 * (cxSpacing + cxExtraMargin))); Desc.cxSpacing = cxSpacing; Desc.cxExtraMargin = cxExtraMargin; Desc.pHeader = &NameFont; // Generate a table of cells for the arranger TArray<CCompositeImageSelector> Selectors; Selectors.InsertEmpty(Table.GetCount()); CString sLastCategory; TArray<CImageArranger::SCellDesc> Cells; for (i = 0; i < Table.GetCount(); i++) { SEntryDesc &Entry = Table[i]; CImageArranger::SCellDesc *pNewCell = Cells.Insert(); pNewCell->cxWidth = (Entry.pImage ? RectWidth(Entry.pImage->GetImageRect()) : 0) + cxImageMargin; pNewCell->cyHeight = (Entry.pImage ? RectHeight(Entry.pImage->GetImageRect()) : 0) + cxImageMargin; pNewCell->sText = Entry.sName; if (!strEquals(sLastCategory, Entry.sCategorize)) { sLastCategory = Entry.sCategorize; pNewCell->bStartNewRow = true; } } // Arrange Arranger.ArrangeByRow(Desc, Cells); // Create a large image CG32bitImage Output; int cxWidth = Max(cxDesiredWidth, Arranger.GetWidth()); int cyHeight = Arranger.GetHeight(); Output.Create(cxWidth, cyHeight); printf("Creating %dx%d image.\n", cxWidth, cyHeight); // Paint the images for (i = 0; i < Table.GetCount(); i++) { SEntryDesc &Entry = Table[i]; int x = Arranger.GetX(i); int y = Arranger.GetY(i); // Paint if (x != -1) { int xCenter = x + (Arranger.GetWidth(i) / 2); int yCenter = y + (Arranger.GetHeight(i) / 2); int xOffset; int yOffset; Entry.pImage->GetImageOffset(0, Entry.iRotation, &xOffset, &yOffset); int cxImage = RectWidth(Entry.pImage->GetImageRect()); int cyImage = RectHeight(Entry.pImage->GetImageRect()); // Paint image if (!bTextBoxesOnly && Entry.pImage) { Entry.pImage->PaintImageUL(Output, x + (Arranger.GetWidth(i) - cxImage) / 2, y + (Arranger.GetHeight(i) - cyImage) / 2, 0, Entry.iRotation); } // Paint type specific stuff switch (Entry.pType->GetType()) { case designStationType: { CStationType *pStationType = CStationType::AsType(Entry.pType); int xStationCenter = xCenter - xOffset; int yStationCenter = yCenter - yOffset; if (bDockingPorts) pStationType->PaintDockPortPositions(Output, xStationCenter, yStationCenter); if (bDevicePos) pStationType->PaintDevicePositions(Output, xStationCenter, yStationCenter); // If we have docking or device positions, mark the center of the station if (bDockingPorts || bDevicePos) { const int LINE_HALF_LENGTH = 24; const CG32bitPixel RGB_CENTER_CROSS(255, 255, 0); Output.DrawLine(xStationCenter - LINE_HALF_LENGTH, yStationCenter, xStationCenter + LINE_HALF_LENGTH, yStationCenter, 1, RGB_CENTER_CROSS); Output.DrawLine(xStationCenter, yStationCenter - LINE_HALF_LENGTH, xStationCenter, yStationCenter + LINE_HALF_LENGTH, 1, RGB_CENTER_CROSS); } break; } } // Paint the 3D grid, if necessary if (b3DGrid) { int iScale = Entry.pImage->GetImageViewportSize(); Metric rMaxRadius = g_KlicksPerPixel * cxImage * 0.5; const Metric rGridSize = LIGHT_SECOND; Metric rRadius; for (rRadius = rGridSize; rRadius <= rMaxRadius; rRadius += rGridSize) { int iRadius = (int)((rRadius / g_KlicksPerPixel) + 0.5); const int iGridAngle = 8; int iPrevAngle = 0; int iAngle; for (iAngle = iGridAngle; iAngle <= 360; iAngle += iGridAngle) { int xFrom, yFrom; C3DConversion::CalcCoord(iScale, iPrevAngle, iRadius, 0, &xFrom, &yFrom); int xTo, yTo; C3DConversion::CalcCoord(iScale, iAngle, iRadius, 0, &xTo, &yTo); Output.DrawLine(xFrom + xCenter, yFrom + yCenter, xTo + xCenter, yTo + yCenter, 1, CG32bitPixel(255, 255, 0)); iPrevAngle = iAngle; } } } // Paint name int xText = Arranger.GetTextX(i); int yText = Arranger.GetTextY(i); if (xText != -1) { if (bTextBoxesOnly) Output.Fill(xText, yText, Arranger.GetTextWidth(i), Arranger.GetTextHeight(i), 0xffff); if (!bTextBoxesOnly) { Output.FillColumn(xCenter, y + Arranger.GetHeight(i), yText - (y + Arranger.GetHeight(i)), rgbNameColor); NameFont.DrawText(Output, xText, yText, rgbNameColor, Entry.sName); } } } } // Write to file or clipboard OutputImage(Output, sFilespec); }