273 lines
6.4 KiB
Python
273 lines
6.4 KiB
Python
import random
|
|
|
|
def is_good(walls, size, x, y) -> bool:
|
|
return 0 <= x < size and 0 <= y < size and ((x == 0 or walls[x - 1][y]) + (y == 0 or walls[x][y - 1]) + (x == size - 1 or walls[x + 1][y]) + (y == size - 1 or walls[x][y + 1]) >= 3)
|
|
|
|
def move_str2coord(move, x, y) -> tuple[int, int]:
|
|
if move == "left":
|
|
return x - 1, y
|
|
elif move == "up":
|
|
return x, y - 1
|
|
elif move == "right":
|
|
return x + 1, y
|
|
elif move == "down":
|
|
return x, y + 1
|
|
else:
|
|
raise ValueError()
|
|
|
|
def invert_move(move):
|
|
if move == "left":
|
|
return "right"
|
|
elif move == "up":
|
|
return "down"
|
|
elif move == "right":
|
|
return "left"
|
|
elif move == "down":
|
|
return "up"
|
|
else:
|
|
raise ValueError()
|
|
|
|
def generate_box_test() -> dict:
|
|
size = random.randint(5, 15)
|
|
tiles = []
|
|
winning_moves = []
|
|
|
|
walls = [[True] * size for _ in range(size)]
|
|
x, y = random.randrange(size), random.randrange(size)
|
|
starting_position = x, y
|
|
walls[x][y] = False
|
|
tiles.append({"kind": "player", "pos": {"x": x, "y": y}, "data": None})
|
|
while True:
|
|
moves = []
|
|
for move in ("left", "up", "right", "down"):
|
|
coords = move_str2coord(move, x, y)
|
|
if coords != starting_position and is_good(walls, size, *coords):
|
|
moves.append(move)
|
|
if len(moves) == 0:
|
|
break
|
|
move = random.choice(moves)
|
|
moves.remove(move)
|
|
x1, y1 = move_str2coord(move, x, y)
|
|
if len(moves) >= 1 and True:
|
|
other_move = random.choice(moves)
|
|
x2, y2 = move_str2coord(other_move, x, y)
|
|
x3, y3 = move_str2coord(other_move, x2, y2)
|
|
if is_good(walls, size, x3, y3):
|
|
walls[x2][y2] = False
|
|
walls[x3][y3] = False
|
|
tiles.append({"kind": "door", "pos": {"x": x1, "y": y1}, "data": {"button_position": {"x": x3, "y": y3}}})
|
|
tiles.append({"kind": "box", "pos": {"x": x2, "y": y2}, "data": None})
|
|
winning_moves.extend((other_move, invert_move(other_move)))
|
|
x, y = x1, y1
|
|
walls[x][y] = False
|
|
winning_moves.append(move)
|
|
|
|
tiles.append({"kind": "exit", "pos": {"x": x, "y": y}, "data": None})
|
|
|
|
for x in range(size):
|
|
for y in range(size):
|
|
if walls[x][y]:
|
|
tiles.append({"kind": "wall", "pos": {"x": x, "y": y}, "data": None})
|
|
|
|
# debug_level_print(size, tiles, winning_moves)
|
|
|
|
return {"size": size, "tiles": tiles}, winning_moves
|
|
|
|
|
|
def generate_easy():
|
|
size = random.randint(10, 20)
|
|
tiles = []
|
|
winning_moves = []
|
|
|
|
x1, y1 = random.randrange(size), random.randrange(size)
|
|
tiles.append({"kind": "player", "pos": {"x": x1, "y": y1}, "data": None})
|
|
while True:
|
|
x2, y2 = random.randrange(size), random.randrange(size)
|
|
if x1 != x2 or y1 != y2:
|
|
break
|
|
tiles.append({"kind": "exit", "pos": {"x": x2, "y": y2}, "data": None})
|
|
|
|
x, y = x1, y1
|
|
while x < x2:
|
|
winning_moves.append("right")
|
|
x += 1
|
|
while x > x2:
|
|
winning_moves.append("left")
|
|
x -= 1
|
|
while y < y2:
|
|
winning_moves.append("down")
|
|
y += 1
|
|
while y > y2:
|
|
winning_moves.append("up")
|
|
y -= 1
|
|
|
|
# debug_level_print(size, tiles, winning_moves)
|
|
|
|
return {"size": size, "tiles": tiles}, winning_moves
|
|
|
|
def generate_unbeatable():
|
|
size = 6
|
|
tiles = []
|
|
|
|
tiles = [
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 1,
|
|
"y": 0
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 1,
|
|
"y": 1
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 1,
|
|
"y": 2
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 1,
|
|
"y": 3
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 1,
|
|
"y": 4
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 1,
|
|
"y": 5
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 2,
|
|
"y": 3
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 3,
|
|
"y": 3
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 4,
|
|
"y": 3
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 5,
|
|
"y": 3
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 4,
|
|
"y": 0
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "wall",
|
|
"pos": {
|
|
"x": 4,
|
|
"y": 1
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "door",
|
|
"pos": {
|
|
"x": 5,
|
|
"y": 1
|
|
},
|
|
"data": {
|
|
"button_position": {
|
|
"x": 2,
|
|
"y": 0
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"kind": "box",
|
|
"pos": {
|
|
"x": 2,
|
|
"y": 1
|
|
},
|
|
"data": None
|
|
},
|
|
{
|
|
"kind": "exit",
|
|
"pos": {
|
|
"x": 5,
|
|
"y": 0
|
|
},
|
|
"data": None
|
|
}
|
|
]
|
|
|
|
x, y = random.randint(2, 5), random.randint(4, 5)
|
|
tiles.append({"kind": "player", "pos": {"x": x, "y": y}, "data": None})
|
|
x, y = 0, random.randrange(6)
|
|
tiles.append({"kind": "box", "pos": {"x": x, "y": y}, "data": None})
|
|
|
|
# debug_level_print(size, tiles)
|
|
|
|
return {"size": size, "tiles": tiles}
|
|
|
|
def debug_level_print(size, tiles, winning_moves = None):
|
|
if winning_moves:
|
|
print(winning_moves)
|
|
|
|
for y in range(size):
|
|
for x in range(size):
|
|
s = ""
|
|
for tile in tiles:
|
|
if tile["pos"]["x"] == x and tile["pos"]["y"] == y:
|
|
if tile["kind"] == "exit":
|
|
s = "00"
|
|
elif tile["kind"] == "player":
|
|
s = "<>"
|
|
elif tile["kind"] == "door":
|
|
s = "##"
|
|
elif tile["kind"] == "box":
|
|
s = "[]"
|
|
elif tile["kind"] == "wall":
|
|
s = s or "::"
|
|
elif tile["kind"] == "door" and tile["data"]["button_position"]["x"] == x and tile["data"]["button_position"]["y"] == y:
|
|
s = "xx"
|
|
s = s or " "
|
|
print(s, end="")
|
|
print()
|