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.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.