public MobType PickRandomMobType(Random rng) { MobType result = null; float random_variable = (float)rng.NextDouble(); for (int entry_index = 0; entry_index < m_entries.Length; entry_index++) { MobSpawnTableEntry entry = m_entries[entry_index]; if (random_variable <= entry.cumulative_weight) { if (entry.mob_spawn_table != null) { result = entry.mob_spawn_table.PickRandomMobType(rng); } else { result = entry.mob_type; } break; } } return(result); }
public MobSpawnTable( Dictionary <int, MobSpawnTable> spawnTables, MobTypeSet mob_types, MobSpawnTables db_table, List <MobSpawnTableEntries> db_entries) { m_table_id = db_table.MobSpawnTableID; m_table_name = db_table.MobSpawnTableName; if (db_entries.Count > 0) { // Compute the total non normalized weight float weight_sum = (float)db_entries.Sum(e => e.Weight); // Sort the source list by weight and then store in the internal entry array m_entries = new MobSpawnTableEntry[db_entries.Count]; // Copy over the source entries into the table // Normalize the weights for (int entry_index = 0; entry_index < db_entries.Count; entry_index++) { MobSpawnTableEntries db_entry = db_entries[entry_index]; MobSpawnTableEntry entry = new MobSpawnTableEntry(); entry.cumulative_weight = (float)db_entry.Weight / weight_sum; if (db_entry.ReferenceIsMobType) { entry.mob_type = mob_types.GetMobTypeById(db_entry.ReferenceID); entry.mob_spawn_table = null; } else { entry.mob_type = null; entry.mob_spawn_table = spawnTables[db_entry.ReferenceID]; } m_entries[entry_index] = entry; } // Sort the weights. Largest weight first. // We do this so that when we search through the CDF // we're more likely to find the random entry we're looking for earlier in the array. m_entries.OrderByDescending(e => e.cumulative_weight); // Convert the probability density function (PDF) into a cumulative distribution function (CDF) float accumulator = 0f; for (int entry_index = 0; entry_index < m_entries.Length; entry_index++) { MobSpawnTableEntry entry = m_entries[entry_index]; float weight = entry.cumulative_weight; entry.cumulative_weight = Math.Min(accumulator + entry.cumulative_weight, 1.0f); accumulator = accumulator + weight; } } }
public MobSpawnTable( Dictionary<int, MobSpawnTable> spawnTables, MobTypeSet mob_types, MobSpawnTables db_table, List<MobSpawnTableEntries> db_entries) { m_table_id = db_table.MobSpawnTableID; m_table_name = db_table.MobSpawnTableName; if (db_entries.Count > 0) { // Compute the total non normalized weight float weight_sum = (float)db_entries.Sum(e => e.Weight); // Sort the source list by weight and then store in the internal entry array m_entries = new MobSpawnTableEntry[db_entries.Count]; // Copy over the source entries into the table // Normalize the weights for (int entry_index = 0; entry_index < db_entries.Count; entry_index++) { MobSpawnTableEntries db_entry = db_entries[entry_index]; MobSpawnTableEntry entry = new MobSpawnTableEntry(); entry.cumulative_weight = (float)db_entry.Weight / weight_sum; if (db_entry.ReferenceIsMobType) { entry.mob_type = mob_types.GetMobTypeById(db_entry.ReferenceID); entry.mob_spawn_table = null; } else { entry.mob_type = null; entry.mob_spawn_table = spawnTables[db_entry.ReferenceID]; } m_entries[entry_index] = entry; } // Sort the weights. Largest weight first. // We do this so that when we search through the CDF // we're more likely to find the random entry we're looking for earlier in the array. m_entries.OrderByDescending(e => e.cumulative_weight); // Convert the probability density function (PDF) into a cumulative distribution function (CDF) float accumulator = 0f; for (int entry_index = 0; entry_index < m_entries.Length; entry_index++) { MobSpawnTableEntry entry = m_entries[entry_index]; float weight = entry.cumulative_weight; entry.cumulative_weight = Math.Min(accumulator + entry.cumulative_weight, 1.0f); accumulator = accumulator + weight; } } }