OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

My Python Sokoban Level Generator hangs indefinitely without display the level itself

  • Thread starter Thread starter notanerd
  • Start date Start date
N

notanerd

Guest
I have implemented a Sokoban level generator in Python using numpy, but when I run the code, it doesn't print anything or generate the expected Sokoban level. The generator is supposed to go through several steps:

  1. Placing Borders: Surrounding the level with walls (#)
  2. Placing Walls: Adding random walls within the level for complexity.
  3. Placing Player: Positioning the player (@) at a random spot.
  4. Placing Boxes and Goals: Adding boxes ($) and their respective goals (.) randomly.
  5. Checking Solvability: Ensuring the level is solvable by confirming all boxes can reach their respective goals.
  6. Generating and Returning the Level: Constructing and returning a 2D list representing the Sokoban level.

Code Implementation:​


Code:
import numpy as np

class LevelGenerator:
    def __init__(self, size, num_walls):
        self.size = size
        self.num_walls = num_walls
        self.level = np.full((size, size), ' ')
        self.generate_level()

    def place_borders(self):
        self.level[0, :] = '#'
        self.level[:, 0] = '#'
        self.level[-1, :] = '#'
        self.level[:, -1] = '#'

    def place_walls(self):
        for _ in range(self.num_walls):
            while True:
                x, y = np.random.randint(1, self.size-1, size=2)
                if self.level[x, y] == ' ':
                    self.level[x, y] = '#'
                    break

    def place_player(self):
        while True:
            x, y = np.random.randint(1, self.size-1, size=2)
            if self.level[x, y] == ' ':
                self.level[x, y] = '@'
                self.player_pos = (x, y)
                break

    def place_boxes_and_goals(self):
        num_boxes = (self.size - 2) // 2
        self.boxes = []
        self.goals = []
        for _ in range(num_boxes):
            while True:
                x, y = np.random.randint(1, self.size-1, size=2)
                if self.level[x, y] == ' ':
                    self.level[x, y] = '$'
                    self.boxes.append((x, y))
                    break
        for _ in range(num_boxes):
            while True:
                x, y = np.random.randint(1, self.size-1, size=2)
                if self.level[x, y] == ' ':
                    self.level[x, y] = '.'
                    self.goals.append((x, y))
                    break

    def is_solvable(self):
        return all(self.is_reachable(box) for box in self.boxes) and all(self.is_reachable(goal) for goal in self.goals)

    def is_reachable(self, target):
        x, y = target
        if self.level[x, y] in '#':
            return False

        visited = set()
        stack = [self.player_pos]
        
        while stack:
            cx, cy = stack.pop()
            if (cx, cy) == target:
                return True
            if (cx, cy) in visited:
                continue
            visited.add((cx, cy))

            for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                nx, ny = cx + dx, cy + dy
                if 0 <= nx < self.size and 0 <= ny < self.size and self.level[nx, ny] not in '#$' and (nx, ny) not in visited:
                    stack.append((nx, ny))

        return False

    def generate_level(self):
        while True:
            self.level.fill(' ')
            self.place_borders()
            self.place_walls()
            self.place_player()
            self.place_boxes_and_goals()
            if self.is_solvable():
                break

    def get_level(self):
        return self.level
# Example usage
print("Generating Sokoban level...")
size = 10
num_walls = 20
generator = LevelGenerator(size, num_walls)
level = generator.get_level()
print("\n".join("".join(row) for row in level))

Upon running the code, instead of getting a printed Sokoban level, the program seems to hang indefinitely without displaying anything. I expected the program to generate and print a Sokoban level based on the specified size (size = 10) and number of walls (num_walls = 20).

Could someone please assist in identifying what might be causing the code to not display or print the generated Sokoban level? Any insights or suggestions on how to fix this issue would be greatly appreciated.
<p>I have implemented a Sokoban level generator in Python using numpy, but when I run the code, it doesn't print anything or generate the expected Sokoban level. The generator is supposed to go through several steps:</p>
<ol>
<li>Placing Borders: Surrounding the level with walls (#)</li>
<li>Placing Walls: Adding random walls within the level for complexity.</li>
<li>Placing Player: Positioning the player (@) at a random spot.</li>
<li>Placing Boxes and Goals: Adding boxes ($) and their respective goals (.) randomly.</li>
<li>Checking Solvability: Ensuring the level is solvable by confirming all boxes can reach their respective goals.</li>
<li>Generating and Returning the Level: Constructing and returning a 2D list representing the Sokoban level.</li>
</ol>
<h1>Code Implementation:</h1>
<pre class="lang-py prettyprint-override"><code>import numpy as np

class LevelGenerator:
def __init__(self, size, num_walls):
self.size = size
self.num_walls = num_walls
self.level = np.full((size, size), ' ')
self.generate_level()

def place_borders(self):
self.level[0, :] = '#'
self.level[:, 0] = '#'
self.level[-1, :] = '#'
self.level[:, -1] = '#'

def place_walls(self):
for _ in range(self.num_walls):
while True:
x, y = np.random.randint(1, self.size-1, size=2)
if self.level[x, y] == ' ':
self.level[x, y] = '#'
break

def place_player(self):
while True:
x, y = np.random.randint(1, self.size-1, size=2)
if self.level[x, y] == ' ':
self.level[x, y] = '@'
self.player_pos = (x, y)
break

def place_boxes_and_goals(self):
num_boxes = (self.size - 2) // 2
self.boxes = []
self.goals = []
for _ in range(num_boxes):
while True:
x, y = np.random.randint(1, self.size-1, size=2)
if self.level[x, y] == ' ':
self.level[x, y] = '$'
self.boxes.append((x, y))
break
for _ in range(num_boxes):
while True:
x, y = np.random.randint(1, self.size-1, size=2)
if self.level[x, y] == ' ':
self.level[x, y] = '.'
self.goals.append((x, y))
break

def is_solvable(self):
return all(self.is_reachable(box) for box in self.boxes) and all(self.is_reachable(goal) for goal in self.goals)

def is_reachable(self, target):
x, y = target
if self.level[x, y] in '#':
return False

visited = set()
stack = [self.player_pos]

while stack:
cx, cy = stack.pop()
if (cx, cy) == target:
return True
if (cx, cy) in visited:
continue
visited.add((cx, cy))

for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = cx + dx, cy + dy
if 0 <= nx < self.size and 0 <= ny < self.size and self.level[nx, ny] not in '#$' and (nx, ny) not in visited:
stack.append((nx, ny))

return False

def generate_level(self):
while True:
self.level.fill(' ')
self.place_borders()
self.place_walls()
self.place_player()
self.place_boxes_and_goals()
if self.is_solvable():
break

def get_level(self):
return self.level
# Example usage
print("Generating Sokoban level...")
size = 10
num_walls = 20
generator = LevelGenerator(size, num_walls)
level = generator.get_level()
print("\n".join("".join(row) for row in level))
</code></pre>
<p>Upon running the code, instead of getting a printed Sokoban level, the program seems to hang indefinitely without displaying anything. I expected the program to generate and print a Sokoban level based on the specified size <code>(size = 10)</code> and number of walls <code>(num_walls = 20)</code>.</p>
<p>Could someone please assist in identifying what might be causing the code to not display or print the generated Sokoban level? Any insights or suggestions on how to fix this issue would be greatly appreciated.</p>
 
Top