TARGET_TOTAL = { :common => 200, :rare => 140, :epic => 100, :legendary => 30 } CARDS_BY_RARITY = { :common => 100, :rare => 70, :epic => 50, :legendary => 30 } RARITY_CHANCE = { :legendary => 0.005, :epic => 0.025, :rare => 0.1, :common => 1 } RARITY_PRIORITY_CHECK = [ :legendary, :epic, :rare, :common ] DISENCHANTED_ARCANE_DUST = { :common => 2, :rare => 10, :epic => 100, :legendary => 400 } CRAFT_ARCANE_DUST = { :legendary => 1600, :epic => 400, :rare => 100, :common => 10 } CRAFT_RARITY_PRIORITY = [ :legendary, :epic, :rare, :common ] CARDS_PER_PACK = 5 class Card attr_accessor :rarity, :number def initialize(rarity, number) @rarity = rarity @number = number end end class PackGenerator def initialize @collection = { :common => [], :rare => [], :epic => [], :legendary => [] } @arcane_dust = 0 @packs_open = 0 @disenchanted = 0 end def check_packs_needed while !is_collection_complete? add_collection(random_pack) @packs_open += 1 #puts info end return @packs_open end def add_collection(pack) pack.each do |card| unless is_card_number_already_in_collection?(card.rarity, card.number) @collection[card.rarity] << card else disenchant_card(card) end end end def disenchant_card(card) @arcane_dust += DISENCHANTED_ARCANE_DUST[card.rarity] @disenchanted += 1 CRAFT_RARITY_PRIORITY.each do |rarity| if @collection[rarity].size != TARGET_TOTAL[rarity] craft_card(rarity) if CRAFT_ARCANE_DUST[rarity] <= @arcane_dust break end end end def craft_card(rarity) (1..CARDS_BY_RARITY[rarity]).each do |i| unless is_card_number_already_in_collection?(rarity, i) @arcane_dust -= CRAFT_ARCANE_DUST[rarity] @collection[rarity] << Card.new(rarity, i) return end end end def is_card_number_already_in_collection?(rarity, i) target_total = rarity == :legendary ? 1 : 2 return @collection[rarity].select { |card| card.number == i }.size == target_total end def random_pack @last_pack = [] (1..5).each do |i| @last_pack << random_rarity_card((i == 5 && !@last_pack.any? { |card| card.rarity != :common })) #@last_pack << random_rarity_card(i == 1) end return @last_pack end def random_rarity_card(force_rare) r = rand # get rarity card = nil RARITY_PRIORITY_CHECK.each do |rarity| chance = force_rare && rarity == :rare ? 1 : RARITY_CHANCE[rarity] if r < chance card = Card.new(rarity, random_card_from_rarity(CARDS_BY_RARITY[rarity])) break end end return card end def random_card_from_rarity(max) return (rand * (max - 1) + 1).round end def is_collection_complete? @collection.each do |rarity, list| return false if list.size != TARGET_TOTAL[rarity] end return true end def info msg = "" msg << "#{@packs_open}\t" msg << "#{@last_pack.collect { |c| c.rarity }.inspect}\t" msg << "#{@collection[:common].size}\t" msg << "#{@collection[:rare].size}\t" msg << "#{@collection[:epic].size}\t" msg << "#{@collection[:legendary].size}\t" msg << "#{@disenchanted}\t" msg << "#{@arcane_dust}" return msg end end #STDOUT.reopen(File.open('generator.log', 'w+')) results = [] (1..500).each do |i| p = PackGenerator.new results << p.check_packs_needed puts "[#{i}] Packs needed: #{results[i-1]}." end puts "Average: #{results.inject{|sum,x| sum + x} / results.size}" puts "Max: #{results.max}" puts "Min: #{results.min}"