array.remove() not working on every loop iteration

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

Hey guys and gals. I’m having trouble with a loop. In this loop I take an element from an array and I want to remove it from the array afterwards, but it seems that in some iterations of the loop this doesn’t happen. Any Ideas?

The function is invoked from the ready function of another node:

func _ready():
globalNode = get_node("/root/global")
rng.randomize()
#instancia player node
add_child(playerNode)
playerNode.add_to_group("Players")
#instancia bots
add_bot(howManyBots)

#despues que todos los elementos se instanciaron, se llama a la funcion de color
globalNode.color_giver()

The function per se:

var colors = [Color(0, 1, 1, 1), Color(1, 0.5, 0.31, 1), Color(0.86, 0.08, 0.24, 1),
		Color(1, 0.55, 0, 1), Color(1, 0.08, 0.58, 1), Color(0.49, 0.99, 0, 1), 
		Color(1, 0, 1, 1), Color(1, 0.87, 0.68, 1), Color(0.93, 0.51, 0.93, 1),
		Color(0.53, 0.81, 0.92, 1),Color(1, 0, 0, 1), Color(0.29, 0, 0.51, 1)]

var selectedColors = []
	
func color_giver():
	randomize()
	#tomamos un array de nodos del grupo players
	var groupNodes = get_tree().get_nodes_in_group("Players")
	#una seleccion de tantos colores como jugadores hay
	selectedColors = slice_array(colors, 0, groupNodes.size()-1)
	#Duplicamos el array
	var tempColors = selectedColors.duplicate()
	#Loopeamos el array, asignandole un color random a cada nodo
	for n in range(groupNodes.size()):
		var node = groupNodes[n]
		var randomNum = randi()%tempColors.size()-1
		var color = tempColors[randomNum]
		#borramos el color del array duplicado
		tempColors.remove(randomNum)
		print(tempColors)
		#llamamos a la funcion del nodo que setea el color en el sprite
		node.selfColor = color
		node.modulate_sprite()

Output:

[0,1,1,1, 1,0.5,0.31,1, 0.86,0.08,0.24,1, 1,0.55,0,1, 1,0.08,0.58,1, 0.49,0.99,0,1]
[0,1,1,1, 1,0.5,0.31,1, 1,0.55,0,1, 1,0.08,0.58,1, 0.49,0.99,0,1]
[0,1,1,1, 1,0.5,0.31,1, 1,0.55,0,1, 0.49,0.99,0,1]
[0,1,1,1, 1,0.5,0.31,1, 1,0.55,0,1, 0.49,0.99,0,1]
[0,1,1,1, 1,0.5,0.31,1, 0.49,0.99,0,1]
[1,0.5,0.31,1, 0.49,0.99,0,1]


 
:bust_in_silhouette: Reply From: jgodfrey

I think you have an operator precedence issue here:

var randomNum = randi()%tempColors.size()-1

Since % has a higher priority than -, that’s basically doing this:

randi()%tempColors.size()

… then, once it has that value, it’s subtracting 1 from it.

So, when the initial value is 0, you end up with a final value of -1, which isn’t a valid array index.

To fix it, add some parenthesis to indicate the expected processing order. So…

var randomNum = randi() % (tempColors.size()-1)

If you print the value of the selected random number (before fixing the problem using the above), you’ll find the times it fails to remove an element from the array is when the index has been calculated to be -1.

Also, note that Array.remove(index) is documented as:

If the index does not exist in the array, nothing happens.

Now it gives me an error “Division by zero in operator %” ???

chantunRey | 2020-10-19 17:01

:bust_in_silhouette: Reply From: chantunRey

remove() Was already taking the current lenght of the array. So by substracting 1 it gave an error.