from builders.maze_builder import MazeBuilder from core.cell import Cell from core.maze import Maze class TextFileMazeBuilder(MazeBuilder): def buildFromFile(self, filename): with open(filename, "r", encoding="utf-8") as source: raw_lines = [line.rstrip("\n") for line in source] if not raw_lines: raise ValueError("Maze file is empty") expected_width = len(raw_lines[0]) blueprint = [] start_cell = None exit_cell = None for y_index, raw in enumerate(raw_lines): if len(raw) != expected_width: raise ValueError( f"Broken maze shape at line {y_index + 1}" ) row_pack = [] for x_index, symbol in enumerate(raw): current = None if symbol == "#": current = Cell( x_index, y_index, isWall=True ) elif symbol == " ": current = Cell( x_index, y_index ) elif symbol == "S": if start_cell: raise ValueError( "Multiple start cells detected" ) current = Cell( x_index, y_index, isStart=True ) start_cell = current elif symbol == "E": if exit_cell: raise ValueError( "Multiple exit cells detected" ) current = Cell( x_index, y_index, isExit=True ) exit_cell = current else: raise ValueError( f"Unsupported symbol '{symbol}' " f"at ({x_index}, {y_index})" ) row_pack.append(current) blueprint.append(row_pack) if start_cell is None: raise ValueError( "Start cell S not found" ) if exit_cell is None: raise ValueError( "Exit cell E not found" ) return Maze( blueprint, start_cell=start_cell, exit_cell=exit_cell )