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:
- Placing Borders: Surrounding the level with walls (#)
- Placing Walls: Adding random walls within the level for complexity.
- Placing Player: Positioning the player (@) at a random spot.
- Placing Boxes and Goals: Adding boxes ($) and their respective goals (.) randomly.
- Checking Solvability: Ensuring the level is solvable by confirming all boxes can reach their respective goals.
- Generating and Returning the Level: Constructing and returning a 2D list representing the Sokoban level.
Code Implementation:
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))
Issue Explanation:
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).
Request:
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.