i have a problem using oop in gdscript

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

I have a problem, I am trying to do an AI that can play flappy bird. so I created a class named “Brain” in which all the AI related operations take place (except for collecting information). it works so every time I spawn a bird its brain has random weights.
that is the code for the random weights when initiated:
func _init(inp, out): # initiate the class (inp = input layer length, out = output layer length) self.weights = [] for i in range(inp * out): var rand = RandomNumberGenerator.new() rand.randomize() var r = rand.randf_range(-1,1) self.weights.append(r)
this code works, after that I try to take the best bird’s weights (I know the NEAT algorithm is not like this but I will change it once I solve that issue) and put them into the new generation, mutate them and the let them run again
here is the code:

for i in range(pop_size): # create new players
	b = bird.instance()
	$Players.add_child(b)
	fittest.brain.clone(b) # put fittest's brain into b

for n in dead_birds:
	n.brain.mutate()

for some reason when I use mutate it mutates all birds every time instead of one bird at a time so that all birds have the same weights (because from gen 2 they all have the same weights as the best in the generation before them)
how can I solve this so that it will change only to the spacific instance of a bird and not the entire birds

here is more of the code I wrote:
Brain class:

class Brain:
var weights


func _init(inp, out): # initiate the class (inp = input layer length, out = output layer length)
	self.weights = []
	for i in range(inp * out):
		var rand = RandomNumberGenerator.new()
		rand.randomize()
		var r = rand.randf_range(-1,1)
		self.weights.append(r)

func show_weights():
	print(weights)

func feed_forward(inp): # feeding the date and getting an action
	var output = 0
	for i in range(len(inp)): # creating a summ of all inputs and weight to get an action
		output += inp[i] * self.weights[i]
		
	if output > 0: return 1
	
	if output <= 0: return -1

func mutate(): # twiking the weights 
	
	for i in range(len(self.weights)):
		var rand = RandomNumberGenerator.new()
		rand.randomize()
		var c = rand.randf_range(0, 10)
		if c < 0.2: # 2% of totally changing the weights 
			rand.randomize()
			self.weights[i] = rand.randf_range(-1, 1)
		else: # adding a slight change to the weights
			rand.randomize()
			self.weights[i] += rand.randf_range(-0.1,0.1)

func clone(bird):
	bird.brain.weights = self.weights

_ready() func of each bird:

func _ready():
position = Vector2(130, 235)
var script = preload("res://Brain.gd")
brain = script.Brain.new(6,1)

again the first generation does have different weights but each generation after they all have the same because for some reason my mutate func changes the weights to all birds and not the spacific instance i need it to.

thanks to who ever tries to help (sorry that my english isnt perfect)

I think duplicate so all not point to same array?

bird.brain.weights = self.weights.duplicate()

rakkarage | 2020-09-26 20:19