I'm trying to make my dungeon auto-generate randomly and such, which includes the floor. I have a few floor tiles I want to use, but I want one to appear more often than the others, I want my first one to have like a 70% or 80% chance to be the tile spawned and then my other ones to have like 5% or 10% chance to be the one that spawns. What way would I go about this other than adding a bunch of duplicates to my tilemap and using a normal random number generator?

Godot version 3.2.3
in Engine

Adding a bunch of tiles would be imo the most elegant solution but not for that disparate of percentages. Otherwise, you could create a tuple of `[tile_type, percent_chance]` and select one randomly. The only stipulations for this implementation is that the integer percent chances are in descending order as demonstrated AND that none of the chances are the same integer. This implementation assumes higher roll = better or more rare.

``````var tile_rarities = [[0, 80], [1, 10], [2, 5], [3,4]]
# list = [[tile_type, integer_percent_chance], [tile_type, integer_percent_chance],...]
func get_random_tile_type(list):
var total = 0
for pair in list:
total += pair

randomize()
var roll = randi() % int(total) + 1
# default value just in case
var chosen_tile = list

for pair in list:
if roll <= pair:
chosen_tile = pair
break
else:
roll -= pair

return chosen_tile
``````
by (3,707 points)

Hmm, I don't think I could fit all of that where I'm trying to put it. I mean, I was just trying to ass this into my auto-generated floor. Which is already in a function, and if I'm not mistaken, I can't throw a function within a function. I guess I'll do it the dumb way I said before, I could always use what you typed for loot drops or something.

You can call a function from within a function though...

``````extends TileMap

func generate_map():
var tile_rarities = [[0, 80], [1, 10], [2, 5], [3,4]]
for row in range(_max_rows):
for col in range(_max_cols):
var selected_tile_type = get_random_tile_type(tile_rarities)
self.set_cell(row, col, selected_tile_type)

func get_random_tile_type(list):
var total = 0
for pair in list:
total += pair

randomize()
var roll = randi() % int(total) + 1
# default value just in case
var chosen_tile = list

for pair in list:
if roll <= pair:
chosen_tile = pair
break
else:
roll -= pair

return chosen_tile
``````

That's in fact how you should write code, it makes it more modular, maintainable and readable.