From 6e4a35b0c2710d12ea85ed6283d0515448b96bf7 Mon Sep 17 00:00:00 2001
From: Ryan Reed <git@ryanreed.net>
Date: Fri, 11 Aug 2023 15:13:20 -0400
Subject: [PATCH] Fixing processing which was not properly following Conway's
 rules

---
 world.gd | 54 ++++++++++++++++++++++++++++++++----------------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/world.gd b/world.gd
index 7d7981d..3a86102 100644
--- a/world.gd
+++ b/world.gd
@@ -17,9 +17,9 @@ enum CellStates {
 @onready var world_seed_label: Label = $CanvasLayer/Debug/VBoxContainer/WorldSeed
 
 @export var world_seed: int
-@export var cell_size: Vector2 = Vector2(64, 64)
+@export var cell_size: Vector2 = Vector2(16, 16)
 @export var cell_texture: Texture2D
-@export var world_size: Vector2 = Vector2(8, 8)
+@export var world_size: Vector2 = Vector2(32, 32)
 
 var cell_instance
 var generation: int = 1
@@ -37,29 +37,26 @@ func _ready() -> void:
 	generate_world()
 
 
-## Check a cell against the Conway rules
-func check_cell_rules(pos: Vector2) -> void:
+## Check a cell against the Conway rules and return True if cell shoudl be alive
+func cell_is_alive(pos: Vector2) -> bool:
 	var neighbors := count_living_neighbors(pos)
 	var currently_alive = world[pos.x][pos.y] is RID
 
 	# Rule 1 - Any live cell with fewer than two live neighbours dies (underpopulation)
 	if currently_alive and neighbors < 2:
-		kill_cell(pos)
-		return
+		return false
 	# Rule 2 - Any live cell with two or three live neighbours lives
 	elif currently_alive and (neighbors == 2 or neighbors == 3):
-		total_living += 1
-		return
+		return true
 	# Rule 3 - Any live cell with more than three live neighbours dies (overpopulation)
-	elif currently_alive and neighbors > 3:
-		kill_cell(pos)
-		return
+		return false
 	# Rule 4 - Any dead cell with epos.xactly three live neighbours becomes a live cell (reproduction)
 	elif not currently_alive and neighbors == 3:
-		total_living += 1
-		world[pos.x][pos.y] = create_cell(pos)
-		return
+		return true
 
+	return false
+
+## Count all neighbors surrounding a cell
 func count_living_neighbors(pos: Vector2) -> int:
 	var count := 0
 
@@ -75,18 +72,31 @@ func count_living_neighbors(pos: Vector2) -> int:
 				count += 1
 	return count
 
+## Loop through the world and create or kill cells depending on rules
 func process_generation() -> void:
 	generation += 1
 	total_living = 0
 
+	var new_world: Array= []
 	for x in range(world_size.x):
+		new_world.append([])
+		new_world[x].resize(world_size.x)
 		for y in range(world_size.y):
-			check_cell_rules(Vector2(x, y))
+			var pos = Vector2(x, y)
+			if cell_is_alive(pos):
+				total_living += 1
+				new_world[x][y] = create_cell(pos)
+			else:
+				new_world[x][y] = kill_cell(pos)
 
+	world = new_world
 
 
 ## Create the cell using the rendering server
 func create_cell(pos: Vector2) -> RID:
+	var world_size = world.size()
+	if world[pos.x][pos.y] is RID: return world[pos.x][pos.y]
+
 	var rs = RenderingServer
 
 	cell_instance = rs.canvas_item_create()
@@ -101,23 +111,23 @@ func create_cell(pos: Vector2) -> RID:
 
 	return cell_instance
 
-func kill_cell(pos: Vector2) -> void:
-	if not world[pos.x][pos.y] is RID: return
-
-	RenderingServer.free_rid(world[pos.x][pos.y])
-	world[pos.x][pos.y] = CellStates.DEAD
+func kill_cell(pos: Vector2) -> CellStates:
+	if world[pos.x][pos.y] is RID:
+		RenderingServer.free_rid(world[pos.x][pos.y])
+	return CellStates.DEAD
 
 
 ## Generate the world with the initial cells
 func generate_world() -> void:
 	for x in range(world_size.x):
 		world.append([])
+		world[x].resize(world_size.x)
 		for y in range(world_size.y):
 			if randi_range(0, 1):
 				total_living += 1
-				world[x].append(create_cell(Vector2(x, y)))
+				world[x][y] = create_cell(Vector2(x, y))
 			else:
-				world[x].append(CellStates.DEAD)
+				world[x][y] = CellStates.DEAD
 
 
 func _on_generation_timer_timeout() -> void: