0 votes

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)

in Engine by (12 points)

I think duplicate so all not point to same array?

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

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.