Confusing variable reset

Godot Version

4.2.2

Question

I am trying to implement Conway’s Game of life. I’m specifically having an issue with this function:

func update_grid():
	for i in grid.keys():
		# TODO: find out why n resets to 0 if commented code is active
		var n = get_neighbors(i)
		if grid[i].visible:
			if (n < 2 or n > 3):
				print("dead, ", i, ", ", n)
				#grid[i].alive = false
			elif (n == 2 or n == 3):
				print ("alive, ", i, ", ", n)
				#grid[i].alive = true
		else:
			if (n == 3):
				print("alive, ", i, ", ", n)
				#grid[i].alive = true
	pass

As the TODO states, n resets to zero if the grid[i].alive flags are altered. I’m not certain as to why.

For context, here is the whole main.gd:

extends Node2D

@export var grid_size: Vector2i
@export var cell_size: int

var grid = {}
var generation = 0

func init_grid():
	var rng = RandomNumberGenerator.new()
	for x in grid_size.x:
		for y in grid_size.y:
			var cell = $Cell.duplicate()
			var pos = Vector2i(x, y) * cell_size
			add_child(cell)
			cell.position = pos
			cell.alive = rng.randi_range(false, true)
			cell.visible = false
			grid[pos] = cell
	pass

func _ready():
	$Cell.hide()
	init_grid()
	render_grid()
	pass

func _on_timer_timeout():
	generation += 1
	print("Generation: ", generation)
	
	update_grid()
	render_grid()
	pass

func get_neighbors(pos: Vector2i):
	var count = 0
	for x in range(-1, 1):
		for y in range(-1, 1):
			if (x == 0 and y == 0):
				continue
			pos += Vector2i(x, y) * cell_size
			if grid.has(pos):
				if grid[pos].alive == true:
					count += 1
	return count

func update_grid():
	for i in grid.keys():
		# TODO: find out why n resets to 0 if commented code is active
		var n = get_neighbors(i)
		if grid[i].visible:
			if (n < 2 or n > 3):
				print("dead, ", i, ", ", n)
				#grid[i].alive = false
			elif (n == 2 or n == 3):
				print ("alive, ", i, ", ", n)
				#grid[i].alive = true
		else:
			if (n == 3):
				print("alive, ", i, ", ", n)
				#grid[i].alive = true
	pass

func render_grid():
	for i in grid.keys():
		grid[i].visible = true if grid[i].alive else false
	pass

It references a single var created in cell.gd:

extends ColorRect

var alive: bool

try change it to

var cell = $Cell.duplicate(true)

image

It appears to not carry over the alive flag if .duplicate(true), and that has me trying to find out why.
Am I missing a signal?

the $Cell you are trying to duplicate, does it have alive property/variable in it? as in a script is attached to it

Yeah:

extends ColorRect

var alive: bool

Is there a keyword I’m missing that allows this var to be seen?
Or is it instantiated when the $Cell is duplicated?

wait nevermind what i do, the duplicate of a node is not the same as duplicate of an array or dictionary
so your default .duplicate() should be correct already

i think you will need to store pos else where first and reset to it before

pos += Vector2i(x, y) * cell_size

so it looks like this:

func get_neighbors(pos: Vector2i):
	var count = 0
	var temp_pos=pos
	for x in range(-1, 1):
		for y in range(-1, 1):
			if (x == 0 and y == 0):
				continue
			temp_pos=pos
			temp_pos+= Vector2i(x, y) * cell_size
			if grid.has(temp_pos):
				if grid[temp_pos].alive == true:
					count += 1
	return count