I'm trying to make a World Function Collapse algorithm, arrays from previous loops don't save?

Godot Version

4.2.2.stable.mono

Question

so i got this around 400 line long code, and I’m pretty new at coding, and I don’t know how do i debug this. I have no clue what actually works. I know that it’s generating cells, but, it seems to generate the cells at around the same spots?

Basically, i have a 5x5 grid. In the grid, around 80% of the cells will get collapsed, and then will just keep reiterating on those cells, keep setting new cells on those cells that already exist. So, I just have a random mess of random models, instead of it actually working.

What it’s supposed to do, is remove all collapsed cells, and only set_cell_item on cells that haven’t been collapsed yet.
image

Also, in the entire code, all the variables in the variable wall_types are Objects. They all link to different nodes with a couple different variable, that are all structure like this, but with different values:


class_name Doorway_1

extends Node

# 0=WALL+EMPTY+DOORWAY, 1=WALL, 2=DOORWAY+TIGHT,

var neighbour_lists: Dictionary = {
	"xnegative": 0,
	"zpositive": 0,
	"xpositive": 0,
	"znegative": 2
}

var ID_ORIENTATION: Dictionary = {
	"orientation": 0,
	"cellID": 5
}

Below is the code, it’s long, and there are many parts that can definitely be optimized, but I’m so tired, I have to get this done in around 2 hours, and I have no clue what to do.

.

.

.


extends GridMap

var next_cells: Array = []
var chunk = 5
var draw_amount: int = 0
#this on is for sorting in the .srot_custom
var previous_options_count: int = 0
var all_cell_chords_array = []
var deleter: int = 5
#these 2 below are for sorting adjacent cells to the "ME" cell
@onready var yeahthisaplayer = $"../yeahthisaplayer"

# Wall types
var wall_0_1 = Wall_0_1.new()
var wall_1_1 = Wall_1_1.new()
var wall_2_1 = Wall_2_1.new()
var wall_3_1 = Wall_3_1.new()
var corner_1 = Corner_1.new()
var doorway_1 = Doorway_1.new()
var tight_1 = Tight_1.new()

# Wall types list (to get the index later)
var wall_types = [
	wall_0_1,
	wall_1_1,
	wall_2_1,
	wall_3_1,
	corner_1,
	doorway_1,
	tight_1
]




func _process(delta):
	#if Input.is_action_just_released("click"):
	var all_cell_chords = prepare_chunk(yeahthisaplayer.position)
	draw(all_cell_chords, yeahthisaplayer.position)
func _ready():
	pass
	#var all_cell_chords = prepare_chunk(yeahthisaplayer.position)
	#draw(all_cell_chords, yeahthisaplayer.position)
	#Preparing chunk of cells
func prepare_chunk(local_position):
	var all_cell_chords_dict = {}  # Store cells by global_chords key 
	var cell_coordinates = local_to_map(local_position)  # Convert local position to map coordinates
	cell_coordinates.y = -1
	
	for x in range(chunk):
		for y in range(chunk):
			# Adjust coordinates for chunk center, to align with the player position
			var global_x = cell_coordinates.x - chunk / 2 + x
			var global_y = cell_coordinates.z - chunk / 2 + y
			var global_chords = Vector3i(global_x, -1, global_y)
			# Check if the cell already exists, and add to the dictionary
			if not all_cell_chords_dict.has(global_chords):
				all_cell_chords_dict[global_chords] = {
					"Collapsed": false,
					"Options": [wall_0_1, wall_1_1, wall_2_1, wall_3_1, corner_1, doorway_1, tight_1]
				}
	#			all_cell_chords_array.append({
	#				global_chords: {
	#					"Collapsed": false,
	#					"Options": [wall_0_1, wall_1_1, wall_2_1, wall_3_1, corner_1, doorway_1, tight_1]
	#				}
	#			})
	
	return all_cell_chords_dict

func checkValid(ME_options, adjacent_cell_options):
	var BETTET_adjacent_cell_options: Array = []
	var sorted_adjacent_cell_options: Array = []
	
	if adjacent_cell_options is Array:
		#sometimes x is an array. sometimes its 1 option
		#remember, x is the options, the nodes, sometimes it's 1 option.
		for x in adjacent_cell_options:
			if x is Array:
				for i in x:
					BETTET_adjacent_cell_options.append(i.neighbour_lists["xnegative"])
					BETTET_adjacent_cell_options.append(i.neighbour_lists["zpositive"])
					BETTET_adjacent_cell_options.append(i.neighbour_lists["xpositive"])
					BETTET_adjacent_cell_options.append(i.neighbour_lists["znegative"])
				for item in BETTET_adjacent_cell_options:
					if not sorted_adjacent_cell_options.has(item):
						sorted_adjacent_cell_options.append(item)
			#BY THIS POINT, THE ARRAY(adjacent_cell_options) WHICH WAS 0-7 OBJECTS(the cell nodes), IS NOW SORTED AS
			#WHAT THE CELL OPTIONS ARE. SO, adjacent_cell_options BECOMES AN ARRAY OF WHAT DIFFERENT OBJECTS CAN BE ATTACHED
			#TO THE adjacent_cell_options CELL
			#THE CODE BELOW REMOVES THE OPTIONS IN me_cell_options THAT AREN'T IN sorted_adjacent_cell_options.
			#RESULTS IN MAKING me_cell_options AN ARRAY OF CELLS THAT ARE POSSIBLE ACCORDING TO THE OPTIONS IN THE ADJACENT CELL.
				for i in range(ME_options.size() - 1, -1, -1):
					#if me cell options not in sortec adjacent options, remove it from me cell.
					if not ME_options[i] in sorted_adjacent_cell_options:
						ME_options.remove_at(i)
			if not x is Array:
				BETTET_adjacent_cell_options.append(x.neighbour_lists["xnegative"])
				BETTET_adjacent_cell_options.append(x.neighbour_lists["zpositive"])
				BETTET_adjacent_cell_options.append(x.neighbour_lists["xpositive"])
				BETTET_adjacent_cell_options.append(x.neighbour_lists["znegative"])
				#Only appends unique items
				for item in BETTET_adjacent_cell_options:
					if not sorted_adjacent_cell_options.has(item):
						sorted_adjacent_cell_options.append(item)
		#BY THIS POINT, THE OBJECT(adjacent_cell_options) IS NOW SORTED AS
		#WHAT THE CELL OPTIONS ARE. SO, adjacent_cell_options BECOMES AN ARRAY OF WHAT DIFFERENT OBJECTS CAN BE ATTACHED
		#TO THE adjacent_cell_options CELL
		#THE CODE BELOW REMOVES THE OPTIONS IN me_cell_options THAT AREN'T IN sorted_adjacent_cell_options.
		#RESULTS IN MAKING me_cell_options AN ARRAY OF CELLS THAT ARE POSSIBLE ACCORDING TO THE OPTIONS IN THE ADJACENT CELL.
		for x in range(ME_options.size() - 1, -1, -1):
			if not ME_options[x] in sorted_adjacent_cell_options:
				ME_options.remove_at(x)
				#die
	#Returns the ME_options, which is an aray of numbers, the numbers indicating the attachment points.
	return ME_options

# Drawing the chunk and setting items
func draw(all_cell_chords_both, local_position):
	draw_amount += 1
	var all_cell_chords: Dictionary = all_cell_chords_both
	var cell_coordinates = local_to_map(local_position)  # Convert local position to map coordinates
	cell_coordinates.y = -1
	if all_cell_chords_array.size() < 1:
		if draw_amount >= (chunk * chunk) - 1:
			return
	if all_cell_chords_array.is_empty():
		if draw_amount < (chunk * chunk) - 1:
			for key in all_cell_chords.keys():
				all_cell_chords_array.append([key, all_cell_chords[key]])
	#for x in all_cell_chords_array.size():
	#	print("KEYWORD: ")
	#	print("index: ", x, "  Global_Chords: ", all_cell_chords_array[x][0], "  collapsed: ", all_cell_chords_array[x][1]["Collapsed"], "  options size: ", all_cell_chords_array[x][1]["Options"].size())
	var all_cell_chords_array_1 = all_cell_chords_array
	#pick cell with least entropy
	if all_cell_chords_array_1.size() > 0:
		all_cell_chords_array_1.sort_custom(sort_by_entropy)
	var all_cell_chords_array_2 = all_cell_chords_array_1.filter(remove_by_entropy)
	
	#if array has more than 1 option, choose 1 random one
	if all_cell_chords_array_2.size() > 1:
		var random_index = randi_range(0, all_cell_chords_array_2.size() - 1)
		# Get the corresponding value from the dictionary using the random key
		var random_cell = all_cell_chords_array_2[random_index]
		var pick_index = randi_range(0, random_cell[1]["Options"].size() - 1)
		var random_option = random_cell[1]["Options"][pick_index]
		random_cell[1]["Options"] = random_option
		all_cell_chords_array_2 = [random_cell]
	if all_cell_chords_array_2.size() == 1:
		all_cell_chords_array_2[0][1]["Collapsed"] = true
		if all_cell_chords_array_2[0][1]["Options"] is Array:
			var pick_index = randi_range(0, all_cell_chords_array_2[0][1]["Options"].size() - 1)
			var random_option = all_cell_chords_array_2[0][1]["Options"][pick_index]
			all_cell_chords_array_2[0][1]["Options"] = random_option
		var indexnumber: int = -1
		var found = false
		for sub_array in all_cell_chords_array:
			indexnumber += 1
			if all_cell_chords_array_2[0][0] == sub_array[0]: #check for matching chords
				found = true 
				sub_array[1]["Collapsed"] = true # Set "Collapsed" to true in the matching sub-array
				all_cell_chords_array[indexnumber][1]["Collapsed"] = true
				all_cell_chords_array[indexnumber][1]["Options"] = all_cell_chords_array_2[0][1]["Options"]
				break
	
	#BY THIS POINT THERE SHOULD BE ONLY 1 OPTION
	for x in range(chunk):
		for y in range(chunk):
			# Adjust coordinates for chunk center, to align with the player position
			var index: int = 0 
			index = x + y
			if index < all_cell_chords_array_2.size():
				var cell = all_cell_chords_array_2[index]
				if cell[1]["Collapsed"] == true:
					#item_index = wall_0_1
					var item_index = cell[1]["Options"];
					#item_index = wall_0_1
					#wall.
					set_cell_item(cell[0], item_index.ID_ORIENTATION["cellID"], item_index.ID_ORIENTATION["orientation"])
			else:
				pass
	next_cells = []
	var indexnumera: int = 0
	for x in range(chunk):
		for y in range(chunk): 
			indexnumera += 1
			if indexnumera >= all_cell_chords_array.size() - 1:
				indexnumera = all_cell_chords_array.size() - 1
			#If its already collapsed, i just set the indexnumera which was in the og array into the next cells array as the
			#exact same shit
			if all_cell_chords_array.size() < 1:
				return
			if all_cell_chords_array[indexnumera][1]["Collapsed"] == true:
				next_cells.resize(all_cell_chords_array.size())
				all_cell_chords_array.remove_at(indexnumera)
			else:
				#This whole "else" operator is for if the cell we get, the "ME" cell is NOT collapsed; has many options
				#THESE OPTIONS ARE FOR "ME" CELL
				var me_cell_options: Array = [0, 1, 2, 3]
				
				
				
				
				
				
				
				
				
				
				
				var ME_ALL_UP: Array = []
				var ME_ALL_RIGHT: Array = []
				var ME_ALL_DOWN: Array = []
				var ME_ALL_LEFT: Array = []
				
				var mesamocell = all_cell_chords_array[indexnumera]
				var ME_OPTIONS2: Array = []
				
				#LOOKING UP LOOKING UP LOOKING UP LOOKING UP LOOKING UP LOOKING UP LOOKING UP LOOKING UP
				if x > 0:
					var arrayindex: int = 0
					#this is a bad idea, but im just setting "up" as the cell im at rn, not the above one
					var up = mesamocell
					var findthissoon: Vector3i = mesamocell[0]
					findthissoon.x -= 1
					
					
					
					for sub_array in all_cell_chords_array:
						arrayindex +=1
						#findthissoon is the global chords were looking for
						if sub_array[0] == findthissoon:
							if arrayindex >= all_cell_chords_array.size():
								arrayindex = all_cell_chords_array.size() - 1
							all_cell_chords_array[arrayindex] = sub_array
							up = all_cell_chords_array[arrayindex]
							break
					#up = the tile above me
					#first i check if it not collapsed
					if up[1]["Collapsed"] == false:
						#makes an array of the options that the above tile has
						var up_valid_adjacent: Array = []
						for option in up[1]["Options"]:
							up_valid_adjacent.append(option)
							#CHECK IF THE "UP" TILE CAN CONNECT WITH THE "ME" TILE
							ME_OPTIONS2.append(up_valid_adjacent)
							#here i check if collapsed
					if up[1]["Collapsed"] == true:
						var option = up[1]["Options"]
						ME_OPTIONS2.append(option)
						ME_ALL_UP = checkValid(me_cell_options, ME_OPTIONS2)
				#LOOKING RIGHT LOOKING RIGHT LOOKING RIGHT LOOKING RIGHT LOOKING RIGHT LOOKING RIGHT LOOKING RIGHT LOOKING RIGHT 
				if y < chunk - 1:
					var arrayindex: int = 0
					#this is a bad idea, but im just setting "right" as the cell im at rn, not the one to the right
					var right = mesamocell
					var findthissoon: Vector3i = mesamocell[0]
					findthissoon.y += 1
					
					
					
					for sub_array in all_cell_chords_array:
						arrayindex +=1
						#findthissoon is the global chords were looking for
						if sub_array[0] == findthissoon:
							if arrayindex > all_cell_chords_array.size():
								arrayindex = all_cell_chords_array.size() - 1
							all_cell_chords_array[arrayindex] = sub_array
							right = all_cell_chords_array[arrayindex]
							break
					#first i check if it not collapsed
					if right[1]["Collapsed"] == false:
						#makes an array of the options that the right tile has
						var up_valid_adjacent: Array = []
						for option in right[1]["Options"]:
							up_valid_adjacent.append(option)
							#CHECK IF THE "UP" TILE CAN CONNECT WITH THE "ME" TILE
							ME_OPTIONS2.append(up_valid_adjacent)
							#here i check if collapsed
					if right[1]["Collapsed"] == true:
						var option = right[1]["Options"]
						ME_OPTIONS2.append(option)
						ME_ALL_RIGHT = checkValid(me_cell_options, ME_OPTIONS2)
				#LOOKING DOWN LOOKING DOWN LOOKING DOWN LOOKING DOWN LOOKING DOWN LOOKING DOWN LOOKING DOWN LOOKING DOWN 
				if x < chunk - 1:
					var arrayindex: int = 0
					#this is a bad idea, but im just setting "up" as the cell im at rn, not the above one
					var down = mesamocell
					var findthissoon: Vector3i = mesamocell[0]
					findthissoon.x += 1
					
					
					
					for sub_array in all_cell_chords_array:
						arrayindex +=1
						#findthissoon is the global chords were looking for
						if sub_array[0] == findthissoon:
							if arrayindex > all_cell_chords_array.size() -  1:
								arrayindex = all_cell_chords_array.size() - 1
							all_cell_chords_array[arrayindex] = sub_array
							down = all_cell_chords_array[arrayindex]
							break
					#up = the tile above me
					#first i check if it not collapsed
					if down[1]["Collapsed"] == false:
						#makes an array of the options that the above tile has
						var up_valid_adjacent: Array = []
						for option in down[1]["Options"]:
							up_valid_adjacent.append(option)
							#CHECK IF THE "UP" TILE CAN CONNECT WITH THE "ME" TILE
							ME_OPTIONS2.append(up_valid_adjacent)
							#here i check if collapsed
					if down[1]["Collapsed"] == true:
						var option = down[1]["Options"]
						ME_OPTIONS2.append(option)
						ME_ALL_DOWN = checkValid(me_cell_options, ME_OPTIONS2)
				#LOOKING LEFT LOOKING LEFT LOOKING LEFT LOOKING LEFT LOOKING LEFT LOOKING LEFT LOOKING LEFT LOOKING LEFT 
				if y > 0:
					var arrayindex: int = 0
					#this is a bad idea, but im just setting "right" as the cell im at rn, not the one to the right
					var left = mesamocell
					var findthissoon: Vector3i = mesamocell[0]
					findthissoon.y -= 1
					
					
					
					for sub_array in all_cell_chords_array:
						arrayindex +=1
						#findthissoon is the global chords were looking for
						if sub_array[0] == findthissoon:
							if arrayindex > all_cell_chords_array.size():
								arrayindex = all_cell_chords_array.size() - 1
							all_cell_chords_array[arrayindex] = sub_array
							left = all_cell_chords_array[arrayindex]
							break
					#first i check if it not collapsed
					if left[1]["Collapsed"] == false:
						#makes an array of the options that the right tile has
						var up_valid_adjacent: Array = []
						for option in left[1]["Options"]:
							up_valid_adjacent.append(option)
							#CHECK IF THE "UP" TILE CAN CONNECT WITH THE "ME" TILE
							ME_OPTIONS2.append(up_valid_adjacent)
							#here i check if collapsed
					if left[1]["Collapsed"] == true:
						var option = left[1]["Options"]
						ME_OPTIONS2.append(option)
						ME_ALL_LEFT = checkValid(me_cell_options, ME_OPTIONS2)
					
				#ALL CHECKING HAS BEEN DONE BY THIS POINT
				next_cells.resize(all_cell_chords_array.size())
				var ME_OPTIONS_ALL: Array = []
				var ME_OPTIONS: Array = []
				ME_OPTIONS_ALL.append(ME_ALL_LEFT)
				ME_OPTIONS_ALL.append(ME_ALL_RIGHT)
				ME_OPTIONS_ALL.append(ME_ALL_UP)
				ME_OPTIONS_ALL.append(ME_ALL_DOWN)
				for item in ME_OPTIONS_ALL:
					if not ME_OPTIONS.has(item):
						ME_OPTIONS.append(item)
				#AT THIS POINT, "ME_OPTIONS" IS THE OPTIONS THE "ME" CELL CAN BE.
				#I have to check what walls share the same numbers as in the "ME_OPTIONS" in the "neighbour_lists"
				next_cells[indexnumera] = mesamocell
				#wall = wall class
				for wall in wall_types:
					var wallvaluearray: Array = []
					wallvaluearray = wall.neighbour_lists.values()
					#walllvaluearray = all values in wall class, EG: [1,2,3,1]
					for value in wallvaluearray:
						#value = 1 value from the wall class, an intr
						var wallarray: Array = []
						#checks if "ME_OPTIONS" has value
						if ME_OPTIONS.has(value):
							next_cells[indexnumera][1]["Options"].append(wall)
							print("waltuh: ",next_cells[indexnumera][1]["Options"])
						else:
							pass
	next_cells.resize(chunk * chunk)
	for i in range(all_cell_chords_array.size() - 1, -1, -1):
		if next_cells[i] != null:
			all_cell_chords_array[i] = next_cells[i]
		if all_cell_chords_array[i][1]["Collapsed"] == true:
			print("Removed collapsed cell")
			all_cell_chords_array.remove_at(i)






















													#SORTING SHIT	
func sort_by_entropy(a, b):
	var a_options = a[1]["Options"]
	var b_options = b[1]["Options"]
	if a_options.size() < b_options.size():
		return true
	return false
	#THE PREVIOUS OPTIONS COUNT > OPTIONS COUNT ISBROKEY
func remove_by_entropy(cell):
	# Get the number of options for the cell
	var options_count = cell[1]["Options"].size()
	if previous_options_count == 0:
		print("Previous options count: ", previous_options_count)
		previous_options_count = options_count
		print("NEW Previous options count: ", previous_options_count)
		print("options_count: ", options_count)
		return true
	if previous_options_count < options_count:
		previous_options_count = options_count
		print("OPTIONS_COUNT WAS SMALLER THAN PREVIOUS")
		deleter = 0
		return false
	if deleter == 0:
		return false
	else:
		previous_options_count = options_count
		return true
	
	# Start on a random cell in the chunk
	# Solve via rules made in the classes
	#

Make your code look better by wrapping it in triple back-ticks ```code```
You can also use the “Preformatted Text” button:

image

1 Like

Thanks, it’s actually readable now!

aight so i messed around with the code for hours, and managed to fix it. Somehow, almost everything was broken, without me even realizing. Basically had to rewrite the code.