Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- NUM_ROOMS = 8
- MONSTER_ROOM_RATIO = 3
- NUM_SELECT_TESTS = 30
- monster_info = {
- :Bandit => {:weight => 5.0, :group_size => 3},
- :Rat => {:weight => 3.5, :group_size => 6},
- :Death_Knight => {:weight => 1.0, :group_size => 1},
- }
- # Given an array of weights, chooses an array element
- # pseudo-randomly based on those weights. Returns the
- # array index of that element.
- #
- # For example, given (1, 1.25, 3.6, 2)
- # The chance that the 2nd element will be chosen is
- # 3.6 times as large as the chance that the 0th element
- # will be chosen
- #
- def weighted_random(weights)
- #sum the weights, and store the sum at each iteration
- sum = 0
- sum_list = []
- weights.each do |n|
- sum += n
- sum_list.push(sum)
- end
- #pick a random number less than the sum
- random_value = sum * rand()
- #find the first sum less than our random value
- index = 0
- index += 1 while (sum_list[index] <= random_value)
- return index
- end
- def random_monster_type(monster_info)
- #build arrays of types and their corresponding weights
- types = []
- weights = []
- monster_info.each_pair do |type,info|
- types.push type
- weights.push info[:weight]
- end
- #get a random, weighted index
- index = weighted_random(weights)
- #return type for that random index
- return types[index]
- end
- def min_monsters_to_spawn(num_rooms, monster_room_ratio)
- return num_rooms * monster_room_ratio
- end
- #returns a hash of monster types => number spawned
- def spawn_level_monsters(num_rooms, monster_room_ratio, monster_info)
- #calculate the minimum number of monsters to spawn
- min_monsters = min_monsters_to_spawn(num_rooms, monster_room_ratio)
- #monster type counts start at 0
- type_counts = {}
- monster_info.each_key {|type| type_counts[type] = 0}
- #spawn 'em
- total = 0
- while total < min_monsters do
- #random type
- type = random_monster_type(monster_info)
- #random spawn count
- num = random_group_size_for_monster_type(type, monster_info)
- #keep track of the count for this type
- type_counts[type] += num
- #update the total monsters
- total += num
- end
- return type_counts
- end
- def random_group_size_for_monster_type(type, monster_info)
- group_size = monster_info[type][:group_size]
- return rand(group_size)+1
- end
- #####################
- # MONSTER SELECTS #
- #####################
- #occurrences hash
- occurrences = {}
- monster_info.each_key do |monster_type|
- occurrences[monster_type] = 0
- end
- NUM_SELECT_TESTS.times do
- type = random_monster_type(monster_info)
- occurrences[type] += 1
- end
- weights = []
- actual = []
- monster_info.each_pair do |type, info|
- weights.push info[:weight]
- actual.push occurrences[type]
- end
- ####################
- # MONSTER SPAWNS #
- ####################
- total_selects = occurrences.values.inject {|sum, n| sum + n}
- monster_type_counts = spawn_level_monsters(NUM_ROOMS,
- MONSTER_ROOM_RATIO,
- monster_info)
- total_spawns = 0
- monster_type_counts.each_pair {|type, count| total_spawns += count}
- min_spawns = min_monsters_to_spawn(NUM_ROOMS, MONSTER_ROOM_RATIO)
- puts "........................................................"
- puts ".. MONSTER INFO .."
- puts "........................................................"
- puts ".. MONSTERS WEIGHT GROUP SIZE .."
- #monster info
- monster_info.each_pair do |type, info|
- str = ".. "
- str += type.to_s.ljust(20)
- str += "%2.2f" % info[:weight]
- str += " %d" % info[:group_size]
- str += " .."
- puts str
- end
- puts "........................................................"
- puts ".. SELECTION TEST (n=#{NUM_SELECT_TESTS}) .."
- puts "........................................................"
- puts ".. %SELECTED \#SELECTED .."
- #selection results
- i = 0
- monster_info.each_pair do |type, info|
- str = ".. "
- str += type.to_s.ljust(19)
- percent_str = "%2.2f\%" % (actual[i].to_f / total_selects * 100)
- str += percent_str.rjust(6)
- num_selected_str = "%d" % actual[i]
- str += " " + num_selected_str.rjust(2)
- str += " .."
- puts str
- i += 1
- end
- puts ".. -- .."
- puts ".. TOTAL: #{total_selects} .."
- puts "........................................................"
- puts ".. SPAWN TEST .."
- puts "........................................................"
- puts ".. \#ROOMS: #{NUM_ROOMS} .."
- puts ".. MONSTERS/ROOM: #{MONSTER_ROOM_RATIO} .."
- puts ".. MIN. SPAWNS: #{min_spawns} .."
- puts ".. .."
- #spawn results
- i = 0
- monster_info.each_pair do |type, info|
- str = ".. "
- str += type.to_s.ljust(19)
- percent_str = "%2.2f\%" % (monster_type_counts[type].to_f / total_spawns * 100)
- str += percent_str.rjust(6)
- num_selected_str = "%d" % monster_type_counts[type]
- str += " " + num_selected_str.rjust(2)
- str += " .."
- puts str
- i += 1
- end
- puts ".. -- .."
- puts ".. TOTAL: #{total_spawns} (min+#{total_spawns-min_spawns}) .."
- puts "........................................................"
Add Comment
Please, Sign In to add comment