Guest User

Untitled

a guest
Jun 17th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.58 KB | None | 0 0
  1. NUM_ROOMS = 8
  2. MONSTER_ROOM_RATIO = 3
  3. NUM_SELECT_TESTS = 30
  4. monster_info = {
  5. :Bandit => {:weight => 5.0, :group_size => 3},
  6. :Rat => {:weight => 3.5, :group_size => 6},
  7. :Death_Knight => {:weight => 1.0, :group_size => 1},
  8. }
  9.  
  10. # Given an array of weights, chooses an array element
  11. # pseudo-randomly based on those weights. Returns the
  12. # array index of that element.
  13. #
  14. # For example, given (1, 1.25, 3.6, 2)
  15. # The chance that the 2nd element will be chosen is
  16. # 3.6 times as large as the chance that the 0th element
  17. # will be chosen
  18. #
  19. def weighted_random(weights)
  20. #sum the weights, and store the sum at each iteration
  21. sum = 0
  22. sum_list = []
  23. weights.each do |n|
  24. sum += n
  25. sum_list.push(sum)
  26. end
  27.  
  28. #pick a random number less than the sum
  29. random_value = sum * rand()
  30.  
  31. #find the first sum less than our random value
  32. index = 0
  33. index += 1 while (sum_list[index] <= random_value)
  34.  
  35. return index
  36. end
  37.  
  38. def random_monster_type(monster_info)
  39. #build arrays of types and their corresponding weights
  40. types = []
  41. weights = []
  42. monster_info.each_pair do |type,info|
  43. types.push type
  44. weights.push info[:weight]
  45. end
  46.  
  47. #get a random, weighted index
  48. index = weighted_random(weights)
  49.  
  50. #return type for that random index
  51. return types[index]
  52. end
  53.  
  54. def min_monsters_to_spawn(num_rooms, monster_room_ratio)
  55. return num_rooms * monster_room_ratio
  56. end
  57.  
  58. #returns a hash of monster types => number spawned
  59. def spawn_level_monsters(num_rooms, monster_room_ratio, monster_info)
  60. #calculate the minimum number of monsters to spawn
  61. min_monsters = min_monsters_to_spawn(num_rooms, monster_room_ratio)
  62.  
  63. #monster type counts start at 0
  64. type_counts = {}
  65. monster_info.each_key {|type| type_counts[type] = 0}
  66.  
  67. #spawn 'em
  68. total = 0
  69. while total < min_monsters do
  70. #random type
  71. type = random_monster_type(monster_info)
  72. #random spawn count
  73. num = random_group_size_for_monster_type(type, monster_info)
  74. #keep track of the count for this type
  75. type_counts[type] += num
  76. #update the total monsters
  77. total += num
  78. end
  79.  
  80. return type_counts
  81. end
  82.  
  83. def random_group_size_for_monster_type(type, monster_info)
  84. group_size = monster_info[type][:group_size]
  85. return rand(group_size)+1
  86. end
  87.  
  88.  
  89. #####################
  90. # MONSTER SELECTS #
  91. #####################
  92. #occurrences hash
  93. occurrences = {}
  94. monster_info.each_key do |monster_type|
  95. occurrences[monster_type] = 0
  96. end
  97.  
  98. NUM_SELECT_TESTS.times do
  99. type = random_monster_type(monster_info)
  100. occurrences[type] += 1
  101. end
  102.  
  103. weights = []
  104. actual = []
  105. monster_info.each_pair do |type, info|
  106. weights.push info[:weight]
  107. actual.push occurrences[type]
  108. end
  109.  
  110. ####################
  111. # MONSTER SPAWNS #
  112. ####################
  113. total_selects = occurrences.values.inject {|sum, n| sum + n}
  114.  
  115.  
  116. monster_type_counts = spawn_level_monsters(NUM_ROOMS,
  117. MONSTER_ROOM_RATIO,
  118. monster_info)
  119.  
  120. total_spawns = 0
  121. monster_type_counts.each_pair {|type, count| total_spawns += count}
  122.  
  123.  
  124. min_spawns = min_monsters_to_spawn(NUM_ROOMS, MONSTER_ROOM_RATIO)
  125. puts "........................................................"
  126. puts ".. MONSTER INFO .."
  127. puts "........................................................"
  128. puts ".. MONSTERS WEIGHT GROUP SIZE .."
  129.  
  130. #monster info
  131. monster_info.each_pair do |type, info|
  132. str = ".. "
  133. str += type.to_s.ljust(20)
  134. str += "%2.2f" % info[:weight]
  135. str += " %d" % info[:group_size]
  136. str += " .."
  137. puts str
  138. end
  139.  
  140. puts "........................................................"
  141. puts ".. SELECTION TEST (n=#{NUM_SELECT_TESTS}) .."
  142. puts "........................................................"
  143. puts ".. %SELECTED \#SELECTED .."
  144.  
  145. #selection results
  146. i = 0
  147. monster_info.each_pair do |type, info|
  148. str = ".. "
  149. str += type.to_s.ljust(19)
  150. percent_str = "%2.2f\%" % (actual[i].to_f / total_selects * 100)
  151. str += percent_str.rjust(6)
  152. num_selected_str = "%d" % actual[i]
  153. str += " " + num_selected_str.rjust(2)
  154. str += " .."
  155. puts str
  156. i += 1
  157. end
  158.  
  159. puts ".. -- .."
  160. puts ".. TOTAL: #{total_selects} .."
  161. puts "........................................................"
  162. puts ".. SPAWN TEST .."
  163. puts "........................................................"
  164. puts ".. \#ROOMS: #{NUM_ROOMS} .."
  165. puts ".. MONSTERS/ROOM: #{MONSTER_ROOM_RATIO} .."
  166. puts ".. MIN. SPAWNS: #{min_spawns} .."
  167. puts ".. .."
  168.  
  169. #spawn results
  170. i = 0
  171. monster_info.each_pair do |type, info|
  172. str = ".. "
  173. str += type.to_s.ljust(19)
  174. percent_str = "%2.2f\%" % (monster_type_counts[type].to_f / total_spawns * 100)
  175. str += percent_str.rjust(6)
  176. num_selected_str = "%d" % monster_type_counts[type]
  177. str += " " + num_selected_str.rjust(2)
  178. str += " .."
  179. puts str
  180. i += 1
  181. end
  182.  
  183. puts ".. -- .."
  184. puts ".. TOTAL: #{total_spawns} (min+#{total_spawns-min_spawns}) .."
  185. puts "........................................................"
Add Comment
Please, Sign In to add comment