please help with converting python code to gdscript, thanks.

import os
import sys
import random


def make_wordsearch(nrows, ncols, wordlist, allow_backwards_words=True):
	grid = [['']*ncols for _ in range(nrows)]

	def fill_empty_cells(grid):
		for irow in range(nrows):
			for icol in range(ncols):
				if grid[irow][icol] == '':
					grid[irow][icol] = random.choice(alphabet)

	def is_word_fits(irow, icol, dx, dy, word):
		for j in range(len(word)):
			if grid[irow][icol] not in ('', word[j]):
				return False
			irow += dy
			icol += dx
		return True

	def place_word(word):
		dxdy_choices = [(0,1), (1,0), (1,1), (1,-1)]  # Left, down, and the diagonals.
		random.shuffle(dxdy_choices)
		for (dx, dy) in dxdy_choices:
			if allow_backwards_words and random.choice([True, False]):
				word = word[::-1]  # If backwards words are allowed, simply reverse word.
			# Work out the minimum and maximum column and row indexes, given the word length.
			n = len(word)
			colmin = 0
			colmax = ncols - n if dx else ncols - 1
			rowmin = 0 if dy >= 0 else n - 1
			rowmax = nrows - n if dy >= 0 else nrows - 1
			if colmax - colmin < 0 or rowmax - rowmin < 0:
				continue  # No possible place for the word in this orientation.
			# Build a list of candidate locations for the word.
			candidates = []
			for irow in range(rowmin, rowmax+1):
				for icol in range(colmin, colmax+1):
					if is_word_fits(irow, icol, dx, dy, word):
						candidates.append((irow, icol))
			# If we don't have any candidates, try the next orientation.
			if not candidates:
				continue
			# Pick a random candidate location and place the word in this orientation.
			loc = irow, icol = random.choice(candidates)
			for j in range(n):
				grid[irow][icol] = word[j]
				irow += dy
				icol += dx
			break  # We're done: no need to try any more orientations.
		else:
			return False  # If we're here, it's because we tried all orientations but couldn't find anywhere to place the word. Oh dear.
		return True
	# Iterate over the word list and try to place each word (without spaces).
	for word in wordlist:
		word = word.replace(' ', '')
		if not place_word(word):
			return None  # We failed to place word, so bail.

	fill_empty_cells(grid)
	return grid


def show_grid_text(grid):
	"""Output a text version of the filled grid wordsearch."""
	for irow in range(nrows):
		print(' '.join(grid[irow]))



if __name__ == "__main__":
	NATTEMPTS = 100
	alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	nrows, ncols = 7, 7
	wordlist = sorted(["uranus","venus","earth","mars","mercury","jupiter","neptune","saturn"], key=lambda w: len(w), reverse=True)

	for i in range(NATTEMPTS):
		grid = make_wordsearch(nrows, ncols, wordlist)

		if grid:
			print('fitted after {} attempt(s)'.format(i + 1))
			show_grid_text(grid)
			break
  • indicainkwell and Jesusemora replied to this.
  • chill guys, i already solved my problem once again.

    #!/usr/bin/env -S godot -s --no-window
    extends SceneTree
    
    
    const ALPHABET := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    const ATTEMPTS := 100
    
    var wordlist := ["URANUS", "VENUS", "EARTH", "MARS", "MERCURY", "JUPITER", "NEPTUNE", "SATURN"]
    var size := Vector2(7, 7)
    
    
    func wordsearch(size: Vector2, wordlist: Array) -> Array:
    	var grid := Utils.get_2D_list(size, "")
    
    	for word in wordlist:
    		if !place_word(grid, word, size):
    			return []
    
    	for y in size.y:
    		for x in size.x:
    			if grid[x][y].empty():
    				grid[x][y] = ALPHABET[randi() % ALPHABET.length()]
    
    	return grid
    
    
    func is_word_fits(grid: Array, cell: Vector2, direction: Vector2, word: String) -> bool:
    	for i in word.length():
    		if !grid[cell.x][cell.y] in ["", word[i]]:
    			return false
    		cell += direction
    	return true
    
    
    func place_word(grid: Array, word: String, size: Vector2) -> bool:
    	var directions := [Vector2(0, 1), Vector2(1, 0), Vector2(1, 1), Vector2(1, -1)]
    	directions.shuffle()
    
    	for direction in directions:
    		# reverse
    		if randf() > 0.5:
    			var revesed := ""
    			for j in range(word.length()-1, -1, -1):
    				revesed += word[j]
    			word = revesed
    		# dimensions
    		var length := word.length()
    		var colmin := 0
    		var colmax := size.x - length if direction.x != 0 else size.x - 1
    		var rowmin := 0 if direction.y >= 0 else length - 1
    		var rowmax := size.y - length if direction.y >= 0 else size.y - 1
    		if colmax - colmin < 0 or rowmax - rowmin < 0:
    			continue  # no place for this direction
    		# candidates
    		var candidates : PoolVector2Array
    		for y in range(rowmin, rowmax + 1):
    			for x in range(colmin, colmax + 1):
    				var cell := Vector2(x, y)
    				if is_word_fits(grid, cell, direction, word):
    					candidates.append(cell)
    		if candidates.empty():
    			continue  # try the next direction
    		# place candidate
    		var cand := candidates[randi() % candidates.size()]
    		for j in length:
    			grid[cand.x][cand.y] = word[j]
    			cand += direction
    		return true
    	return false
    
    
    func _init() -> void:
    	randomize()
    	wordlist.sort_custom(self, "_sort_by_len")
    
    	for i in ATTEMPTS:
    		var grid := wordsearch(size, wordlist)
    		if grid:
    			print("fitted after %d attempt(s)" % (i + 1))
    			for arr in grid:
    				print(arr)
    			break
    	quit()
    
    
    static func _sort_by_len(a: String, b: String) -> bool:
    	return a.length() > b.length()

    this script for making that kind game

    boruok it comes out as extremely disrespectful to expect someone to do your job while you don't even put in the effort to type more than one line of text, let alone code.

    if you were to try and convert this yourself, and have a problem with some part, then you could ask about that part and we would probably help.
    or if you don't know anything about code, at least tell us WHAT the code is supposed to do, what you need it for, or something.

    but this is a tedious work that requires expertise in many languages, which, granted, I have, and some others in the forum too. But the one thing no one wants to do is tedious, because it doesn't just take a long time to do, you don't get any gratification from doing it either.

    I'll take a look at it anyway, but just a look.

    this looks like the main function, it executes when running the script.

    
    if __name__ == "__main__":

    I started with python, but now I f***ng hate this stupid way of defining variables that python has, it's just so confusing.

    	NATTEMPTS = 100 #this is an INT
    	alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #this is a STRING
    	nrows, ncols = 7, 7#2 INTs
    	wordlist = sorted(["uranus","venus","earth","mars","mercury","jupiter","neptune","saturn"], key=lambda w: len(w), reverse=True)#this is a mess. there's a list of string, it is then sorted using a lambda function. I don't care enough to decipher what it does. len(w) gives size of w. read the python docs.

    in gdscript you only have arrays, you can sort arrays using the sorting methods or use a custom one. I won't explain.
    https://docs.godotengine.org/en/stable/classes/class_array.html#class-array-method-sort

    for i in range(NATTEMPTS):#same thing in gdscript
    	grid = make_wordsearch(nrows, ncols, wordlist)#this is a function
    	if grid:
    		print('fitted after {} attempt(s)'.format(i + 1))
    		show_grid_text(grid)#this is a function
    		break

    first function. too long, there's probably some built in gdscript function that does the same. but what is this supposed to do?

    def make_wordsearch(nrows, ncols, wordlist, allow_backwards_words=True):
    	grid = [['']*ncols for _ in range(nrows)]
    
    	def fill_empty_cells(grid):
    		for irow in range(nrows):
    			for icol in range(ncols):
    				if grid[irow][icol] == '':
    					grid[irow][icol] = random.choice(alphabet)
    
    	def is_word_fits(irow, icol, dx, dy, word):
    		for j in range(len(word)):
    			if grid[irow][icol] not in ('', word[j]):
    				return False
    			irow += dy
    			icol += dx
    		return True
    
    	def place_word(word):
    		dxdy_choices = [(0,1), (1,0), (1,1), (1,-1)]  # Left, down, and the diagonals.
    		random.shuffle(dxdy_choices)
    		for (dx, dy) in dxdy_choices:
    			if allow_backwards_words and random.choice([True, False]):
    				word = word[::-1]  # If backwards words are allowed, simply reverse word.
    			# Work out the minimum and maximum column and row indexes, given the word length.
    			n = len(word)
    			colmin = 0
    			colmax = ncols - n if dx else ncols - 1
    			rowmin = 0 if dy >= 0 else n - 1
    			rowmax = nrows - n if dy >= 0 else nrows - 1
    			if colmax - colmin < 0 or rowmax - rowmin < 0:
    				continue  # No possible place for the word in this orientation.
    			# Build a list of candidate locations for the word.
    			candidates = []
    			for irow in range(rowmin, rowmax+1):
    				for icol in range(colmin, colmax+1):
    					if is_word_fits(irow, icol, dx, dy, word):
    						candidates.append((irow, icol))
    			# If we don't have any candidates, try the next orientation.
    			if not candidates:
    				continue
    			# Pick a random candidate location and place the word in this orientation.
    			loc = irow, icol = random.choice(candidates)
    			for j in range(n):
    				grid[irow][icol] = word[j]
    				irow += dy
    				icol += dx
    			break  # We're done: no need to try any more orientations.
    		else:
    			return False  # If we're here, it's because we tried all orientations but couldn't find anywhere to place the word. Oh dear.
    		return True
    	# Iterate over the word list and try to place each word (without spaces).
    	for word in wordlist:
    		word = word.replace(' ', '')
    		if not place_word(word):
    			return None  # We failed to place word, so bail.
    
    	fill_empty_cells(grid)
    	return grid

    kuligs2 chat gpt can do that ezpz

    no it can't and this isn't helpful. but it's kinda deserved for the amount of effort put into the post to get such response.

    chill guys, i already solved my problem once again.

    #!/usr/bin/env -S godot -s --no-window
    extends SceneTree
    
    
    const ALPHABET := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    const ATTEMPTS := 100
    
    var wordlist := ["URANUS", "VENUS", "EARTH", "MARS", "MERCURY", "JUPITER", "NEPTUNE", "SATURN"]
    var size := Vector2(7, 7)
    
    
    func wordsearch(size: Vector2, wordlist: Array) -> Array:
    	var grid := Utils.get_2D_list(size, "")
    
    	for word in wordlist:
    		if !place_word(grid, word, size):
    			return []
    
    	for y in size.y:
    		for x in size.x:
    			if grid[x][y].empty():
    				grid[x][y] = ALPHABET[randi() % ALPHABET.length()]
    
    	return grid
    
    
    func is_word_fits(grid: Array, cell: Vector2, direction: Vector2, word: String) -> bool:
    	for i in word.length():
    		if !grid[cell.x][cell.y] in ["", word[i]]:
    			return false
    		cell += direction
    	return true
    
    
    func place_word(grid: Array, word: String, size: Vector2) -> bool:
    	var directions := [Vector2(0, 1), Vector2(1, 0), Vector2(1, 1), Vector2(1, -1)]
    	directions.shuffle()
    
    	for direction in directions:
    		# reverse
    		if randf() > 0.5:
    			var revesed := ""
    			for j in range(word.length()-1, -1, -1):
    				revesed += word[j]
    			word = revesed
    		# dimensions
    		var length := word.length()
    		var colmin := 0
    		var colmax := size.x - length if direction.x != 0 else size.x - 1
    		var rowmin := 0 if direction.y >= 0 else length - 1
    		var rowmax := size.y - length if direction.y >= 0 else size.y - 1
    		if colmax - colmin < 0 or rowmax - rowmin < 0:
    			continue  # no place for this direction
    		# candidates
    		var candidates : PoolVector2Array
    		for y in range(rowmin, rowmax + 1):
    			for x in range(colmin, colmax + 1):
    				var cell := Vector2(x, y)
    				if is_word_fits(grid, cell, direction, word):
    					candidates.append(cell)
    		if candidates.empty():
    			continue  # try the next direction
    		# place candidate
    		var cand := candidates[randi() % candidates.size()]
    		for j in length:
    			grid[cand.x][cand.y] = word[j]
    			cand += direction
    		return true
    	return false
    
    
    func _init() -> void:
    	randomize()
    	wordlist.sort_custom(self, "_sort_by_len")
    
    	for i in ATTEMPTS:
    		var grid := wordsearch(size, wordlist)
    		if grid:
    			print("fitted after %d attempt(s)" % (i + 1))
    			for arr in grid:
    				print(arr)
    			break
    	quit()
    
    
    static func _sort_by_len(a: String, b: String) -> bool:
    	return a.length() > b.length()

    this script for making that kind game

    • xyz replied to this.

      boruok extends SceneTree? This is some next level stuff, man 😮

        xyz
        it's for running script from terminal or vscode, for example you can define task.json file in vscode to help you for development. actually a very handy.

        {
        	// See https://go.microsoft.com/fwlink/?LinkId=733558
        	// for the documentation about the tasks.json format
        	"version": "2.0.0",
        	"tasks": [
        		{
        			"label": "run game",
        			"type": "shell",
        			"group": "build",
        			"command": "godot"
        		},
        		{
        			"label": "run sandbox",
        			"type": "shell",
        			"group": "build",
        			"command": "godot res://sandbox/sandbox.tscn"
        		},
        		{
        			"label": "run script",
        			"type": "shell",
        			"group": "build",
        			"command": "godot -s ${file} --no-window"
        		},
        		{
        			"label": "compile font",
        			"type": "shell",
        			"group": "build",
        			"command": "./scripts/editor/compile_font.gd",
        		},
        		{
        			"label": "erase userdata",
        			"type": "shell",
        			"group": "build",
        			"command": "./scripts/editor/erase_userdata.gd" ,
        		},
        
        	]
        }
        • xyz replied to this.

          boruok I was just saying that's it's strange how you're capable of running standalone shebanged gdscripts via comandline, yet ask for help with translating a short snippet of python code to... basically the python code 🙂

          2 months later

          This is the funniest post I've ever seen