komplexeres wfc, funktioniert jetzt immer
This commit is contained in:
@@ -7,7 +7,7 @@ from src.net import NetGame
|
|||||||
|
|
||||||
|
|
||||||
def test_run(i: int) -> float:
|
def test_run(i: int) -> float:
|
||||||
game = NetGame(5, 5, i)
|
game = NetGame(11, 11, i)
|
||||||
solver = WFCSolver(game)
|
solver = WFCSolver(game)
|
||||||
a = time.perf_counter()
|
a = time.perf_counter()
|
||||||
for _ in solver.solve():
|
for _ in solver.solve():
|
||||||
|
|||||||
@@ -1,9 +1,21 @@
|
|||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
|
from copy import deepcopy
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
from src.netTypes import Direction, PieceType
|
from src.netTypes import Direction, PieceType
|
||||||
from src.net import NetGame
|
from src.net import NetGame
|
||||||
|
|
||||||
|
type RollbackType = list[
|
||||||
|
tuple[
|
||||||
|
list[tuple[int, int]],
|
||||||
|
list[list[Direction]],
|
||||||
|
set[Direction],
|
||||||
|
int,
|
||||||
|
int,
|
||||||
|
list[list[PieceConnectionState]],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ConnectionState(Enum):
|
class ConnectionState(Enum):
|
||||||
DISCONNECTED = auto()
|
DISCONNECTED = auto()
|
||||||
@@ -73,9 +85,16 @@ class WFCSolver:
|
|||||||
|
|
||||||
def get_possible_corner_directions(self, x: int, y: int) -> set[Direction]:
|
def get_possible_corner_directions(self, x: int, y: int) -> set[Direction]:
|
||||||
cstates = self.connection_states[x][y]
|
cstates = self.connection_states[x][y]
|
||||||
connected = cstates.connected_or_unknown()
|
connected = cstates.directions_with_state(ConnectionState.CONNECTED)
|
||||||
possible = connected.copy()
|
if connected:
|
||||||
possible.update(map(lambda d: Direction((d - 1) % 4), connected))
|
possible = {Direction.UP, Direction.DOWN, Direction.LEFT, Direction.RIGHT}
|
||||||
|
for direction in connected:
|
||||||
|
possible.intersection_update(
|
||||||
|
{direction, Direction((direction - 1) % 4)}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
possible = cstates.directions_with_state(ConnectionState.UNKNOWN)
|
||||||
|
possible.update(map(lambda d: Direction((d - 1) % 4), possible.copy()))
|
||||||
disconnected = cstates.directions_with_state(ConnectionState.DISCONNECTED)
|
disconnected = cstates.directions_with_state(ConnectionState.DISCONNECTED)
|
||||||
possible.difference_update(disconnected)
|
possible.difference_update(disconnected)
|
||||||
possible.difference_update(map(lambda d: Direction((d - 1) % 4), disconnected))
|
possible.difference_update(map(lambda d: Direction((d - 1) % 4), disconnected))
|
||||||
@@ -117,20 +136,44 @@ class WFCSolver:
|
|||||||
)
|
)
|
||||||
return possible
|
return possible
|
||||||
|
|
||||||
|
def get_field_rotations(self) -> list[list[Direction]]:
|
||||||
|
return [[p.direction for p in col] for col in self.game.get_field()]
|
||||||
|
|
||||||
|
def set_field_rotations(self, rotations: list[list[Direction]]):
|
||||||
|
for x, col in enumerate(rotations):
|
||||||
|
for y, d in enumerate(col):
|
||||||
|
self.game.set_direction(x, y, d)
|
||||||
|
|
||||||
def solve(self) -> Generator[None]:
|
def solve(self) -> Generator[None]:
|
||||||
unfixed = list(
|
unfixed = list(
|
||||||
((i, j) for i in range(self.game.width) for j in range(self.game.height))
|
((i, j) for i in range(self.game.width) for j in range(self.game.height))
|
||||||
)
|
)
|
||||||
|
rollback: RollbackType = []
|
||||||
while not self.game.solved():
|
while not self.game.solved():
|
||||||
yield
|
yield
|
||||||
(x, y) = min(unfixed, key=lambda t: len(self.get_possible_directions(*t)))
|
if len(unfixed) == 0:
|
||||||
if len(self.get_possible_directions(x, y)) == 0:
|
unfixed, rotations, dirs, x, y, self.connection_states = rollback.pop()
|
||||||
raise NotImplementedError(
|
self.set_field_rotations(rotations)
|
||||||
"Irgendwo eine falsche Richtung gewählt, muss diese Logik noch schreiben"
|
else:
|
||||||
|
(x, y) = min(
|
||||||
|
unfixed, key=lambda t: len(self.get_possible_directions(*t))
|
||||||
|
)
|
||||||
|
dirs = self.get_possible_directions(x, y)
|
||||||
|
if len(dirs) == 0:
|
||||||
|
unfixed, rotations, dirs, x, y, self.connection_states = rollback.pop()
|
||||||
|
self.set_field_rotations(rotations)
|
||||||
|
direction = dirs.pop()
|
||||||
|
if len(dirs) > 0:
|
||||||
|
rollback.append(
|
||||||
|
(
|
||||||
|
unfixed.copy(),
|
||||||
|
self.get_field_rotations(),
|
||||||
|
dirs,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
deepcopy(self.connection_states),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
if len(self.get_possible_directions(x, y)) > 1:
|
|
||||||
print("AAAAAAAA")
|
|
||||||
direction = self.get_possible_directions(x, y).pop()
|
|
||||||
self.game.set_direction(x, y, direction)
|
self.game.set_direction(x, y, direction)
|
||||||
self.game.lock(x, y)
|
self.game.lock(x, y)
|
||||||
unfixed.remove((x, y))
|
unfixed.remove((x, y))
|
||||||
|
|||||||
@@ -20,10 +20,11 @@ class Grid:
|
|||||||
raise ValueError("Feldgrösse nicht erlaubt")
|
raise ValueError("Feldgrösse nicht erlaubt")
|
||||||
with open(f"descriptions/{width}x{height}.txt") as f:
|
with open(f"descriptions/{width}x{height}.txt") as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
if specific:
|
if specific is not None:
|
||||||
selected = lines[specific].strip()
|
selected = lines[specific].strip()
|
||||||
else:
|
else:
|
||||||
selected = choice(lines).strip()
|
selected = choice(lines).strip()
|
||||||
|
print(f"Seed: {lines.index(selected + "\n")}")
|
||||||
self.pieces = parse_description(selected)
|
self.pieces = parse_description(selected)
|
||||||
|
|
||||||
def neighbors(self, x: int, y: int) -> list[Coordinate]:
|
def neighbors(self, x: int, y: int) -> list[Coordinate]:
|
||||||
|
|||||||
Reference in New Issue
Block a user