CurrencyValue CLevelTableOfItemGenerators::GetAverageValue (int iLevel) // GetAverageValue // // Returns the average value. { int i; // Compute the table for this level. Metric rTotal = 0.0; int iTotalChance = 0; for (i = 0; i < m_Table.GetCount(); i++) { int iChance = GetFrequencyByLevel(m_Table[i].sLevelFrequency, iLevel); iTotalChance += iChance; } for (i = 0; i < m_Table.GetCount(); i++) { int iChance = GetFrequencyByLevel(m_Table[i].sLevelFrequency, iLevel); if (iChance > 0) rTotal += (m_Table[i].Count.GetAveValueFloat() * (Metric)m_Table[i].pEntry->GetAverageValue(iLevel) * (Metric)iChance / (Metric)iTotalChance); } return (CurrencyValue)(rTotal + 0.5); }
void CLevelTableOfItemGenerators::AddItems (SItemAddCtx &Ctx) // AddItems // // Adds items { int i, j; // Compute probabilities, if necessary if (m_iComputedLevel != Ctx.iLevel) { // Create a table of probabilities m_iTotalChance = 0; for (i = 0; i < m_Table.GetCount(); i++) { m_Table[i].iChance = GetFrequencyByLevel(m_Table[i].sLevelFrequency, Ctx.iLevel); m_iTotalChance += m_Table[i].iChance; } m_iComputedLevel = Ctx.iLevel; } // Generate if (m_iTotalChance) { int iRoll = mathRandom(1, m_iTotalChance); for (i = 0; i < m_Table.GetCount(); i++) { iRoll -= m_Table[i].iChance; if (iRoll <= 0) { int iCount = m_Table[i].Count.Roll(); for (j = 0; j < iCount; j++) m_Table[i].pEntry->AddItems(Ctx); break; } } } }
void CLevelTableOfDeviceGenerators::AddDevices (SDeviceGenerateCtx &Ctx) // AddDevices // // Adds devices { int i, j; // Compute probabilities if (Ctx.iLevel != m_iComputedLevel) { m_iTotalChance = 0; for (i = 0; i < m_Table.GetCount(); i++) { m_Table[i].iChance = GetFrequencyByLevel(m_Table[i].sLevelFrequency, Ctx.iLevel); m_iTotalChance += m_Table[i].iChance; } m_iComputedLevel = Ctx.iLevel; } // Generate if (m_iTotalChance) { int iCount = m_Count.Roll(); for (i = 0; i < iCount; i++) { int iRoll = mathRandom(1, m_iTotalChance); for (j = 0; j < m_Table.GetCount(); j++) { iRoll -= m_Table[j].iChance; if (iRoll <= 0) { m_Table[j].pDevice->AddDevices(Ctx); break; } } } } }
void CRandomItems::InitTable (void) // InitTable // // Initializes the m_Table array. // // We assume that m_Criteria, m_sLevelFrequency, m_iLevel, and m_iLevelCurve are properly initialized. { int i; // Start by allocating an array large enough to hold // all item types in the universe ItemEntryStruct *pTable = new ItemEntryStruct [g_pUniverse->GetItemTypeCount()]; int iTableSize = 0; // Figure out if we should use level curves or level frequency bool bUseLevelFrequency = !m_sLevelFrequency.IsBlank(); // Iterate over every item type and add it to the table if // it matches the given criteria for (i = 0; i < g_pUniverse->GetItemTypeCount(); i++) { CItemType *pType = g_pUniverse->GetItemType(i); CItem Item(pType, 1); // Skip if the item doesn't match the categories if (!Item.MatchesCriteria(m_Criteria)) continue; // Skip if this item is not found randomly if (pType->GetFrequency() == ftNotRandom) continue; // Adjust score based on level, either the level curve // or the level frequency string. int iScore; if (bUseLevelFrequency) { iScore = 1000 * GetFrequencyByLevel(m_sLevelFrequency, pType->GetLevel()) / ftCommon; } else { // Skip if the item is not within the level curve if ((pType->GetLevel() < m_iLevel - m_iLevelCurve) || (pType->GetLevel() > m_iLevel + m_iLevelCurve)) continue; // If we get this far then the item perfectly matches // and we need to add it to our table. First, however, we need // to calculate a score. // // The score is number that represents how common the item // is in the table. Later we normalize the score to be a probability int iLevelDelta = pType->GetLevel() - m_iLevel; switch (iLevelDelta) { case 0: iScore = 1000; break; case 1: case -1: iScore = 500; break; case 2: case -2: iScore = 200; break; default: iScore = 50; } } // Adjust score based on item frequency iScore = iScore * pType->GetFrequency() * 10 / (ftCommon * 10); // If we have a score of 0 then we skip this item if (iScore == 0) continue; // Add the item to the table pTable[iTableSize].pType = pType; pTable[iTableSize].iChance = iScore; iTableSize++; } // We must have items if (iTableSize == 0) { m_iCount = 0; m_Table = NULL; return; } // Add up the total score of all items int iTotalScore = 0; for (i = 0; i < iTableSize; i++) iTotalScore += pTable[i].iChance; // Compute the chance int iTotalChance = 0; for (i = 0; i < iTableSize; i++) { int iScore = pTable[i].iChance; pTable[i].iChance = (iScore * 1000) / iTotalScore; pTable[i].iRemainder = (iScore * 1000) % iTotalScore; iTotalChance += pTable[i].iChance; } // Distribute the remaining chance points while (iTotalChance < 1000) { // Look for the entry with the biggest remainder int iBestRemainder = 0; int iBestEntry = -1; for (i = 0; i < iTableSize; i++) if (pTable[i].iRemainder > iBestRemainder) { iBestRemainder = pTable[i].iRemainder; iBestEntry = i; } pTable[iBestEntry].iChance++; pTable[iBestEntry].iRemainder = 0; iTotalChance++; } // Count the number of entries that we've got m_iCount = 0; for (i = 0; i < iTableSize; i++) if (pTable[i].iChance > 0) m_iCount++; // Now loop over the entire table and add it to the // random entry generator m_Table = new SEntry [m_iCount]; int j = 0; for (i = 0; i < iTableSize; i++) if (pTable[i].iChance > 0) { m_Table[j].pType = pTable[i].pType; m_Table[j].iProbability = pTable[i].iChance; j++; } // Done delete [] pTable; }