random choice with weights

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Lfzinho

I have an array [a, b, c, d, e] and I want to choose one element from it, but I want “e” to have an actual chance of 0.5% of being choosed. How can I do that?

:bust_in_silhouette: Reply From: rakkarage

the tilemap uses a system like this to select random tiles when priority is selected

each tile has a int priority defaults to 1
so if you have 6 tiles and each has a 1 then each tile has 1 in 6 chance
if you want one to drop more often change its number to 2 and then it has a 2 in 7 chance etc

but the system only seems to work from editor

so i made a function that picks a random tile based on the priority so i can use it from code

the basics: sum all probabilities and roll and random number between 0 and total
then loop through items summing probabilities until you find selected item

tmi:
https://www.codeproject.com/Articles/420046/Loot-Tables-Random-Maps-and-Monsters-Part-I

func _setRandomTile(map: TileMap, x: int, y: int, id: int, flipX: bool = false, flipY: bool = false, rot90: bool = false) -> void:
	map.set_cell(x, y, id, flipX, flipY, rot90, _randomTile(id))

func _randomTile(id: int) -> Vector2:
	var p := Vector2.ZERO
	var s := _tileSet.tile_get_region(id).size / _tileSet.autotile_get_size(id)
	var total := 0
	for y in range(s.y):
		for x in range(s.x):
			total += _tileSet.autotile_get_subtile_priority(id, Vector2(x, y))
	var selected := randi() % total
	var current := 0
	for y in range(s.y):
		for x in range(s.x):
			p = Vector2(x, y)
			current += _tileSet.autotile_get_subtile_priority(id, p)
			if current > selected:
				return p
	return p
        if current **>** selected:

rakkarage | 2020-06-30 00:38