Files

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()