Created
January 29, 2026 17:15
-
-
Save taylorthurlow/b31e9d348d4bd2431640178f72cdecc0 to your computer and use it in GitHub Desktop.
Calculate the average number of chests required to obtain N number of unique barrows pieces
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env ruby | |
| brothers = %i[ahrim karil dharok verac torag guthan] | |
| categories = %i[helm body legs weapon] | |
| @items = brothers | |
| .product(categories) | |
| .map { |(brother, category)| :"#{brother} #{category}" } | |
| .sort | |
| @brothers_killed = 6 | |
| puts "Brother kill count: #{@brothers_killed}" | |
| @probability_of_unique = 1 / (450 - (58 * @brothers_killed)).to_f | |
| @roll_fractional_base = (1 / @probability_of_unique).to_i | |
| puts "Probability of unique: 1 in #{@roll_fractional_base}" | |
| @roll_for_unique = ->(excluded_items) { | |
| if rand(1..@roll_fractional_base) == 1 | |
| (@items - excluded_items).sample | |
| end | |
| } | |
| def loot_chest | |
| chest_loot = [] | |
| (@brothers_killed + 1).times do | |
| if (roll_loot = @roll_for_unique.call(chest_loot)) | |
| chest_loot << roll_loot | |
| end | |
| end | |
| chest_loot | |
| end | |
| run_limit = 100_000 | |
| all_finished_at = {} | |
| total_runs = 0 | |
| num_uniques_to_stop = @items.count | |
| loop do # Multiple-sample run loop (experiment) | |
| kc = 0 | |
| current_items = [] | |
| finished_at = {} | |
| loop do # Single sample run loop (get all items at least once) | |
| current_items += loot_chest | |
| kc += 1 | |
| if (uniques_count = current_items.uniq.count) > 0 && !finished_at[uniques_count] | |
| finished_at[uniques_count] ||= [] | |
| finished_at[uniques_count] << kc | |
| end | |
| break if current_items.uniq.count == num_uniques_to_stop | |
| end | |
| total_runs += 1 | |
| all_finished_at.merge!(finished_at) do |key, old_value, new_value| | |
| old_value + new_value | |
| end | |
| if total_runs % 1000 == 0 | |
| puts "After #{total_runs} samples (min/max/avg):" | |
| all_finished_at.sort.each do |uniques_count, kc_array| | |
| puts " #{uniques_count} => #{kc_array.min}/#{kc_array.max}/#{kc_array.sum / kc_array.size}" | |
| end | |
| end | |
| break if total_runs == run_limit | |
| end |
Author
taylorthurlow
commented
Jan 29, 2026
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment