% Read a file with the puzzle and return the initial state of the game read_board(Filename, Board) :- open(Filename, read, Stream), read_lines(Stream, Lines), maplist(atom_chars, Board, Lines). read_lines(Stream, []) :- at_end_of_stream(Stream). read_lines(Stream, [Line|Lines]) :- \+ at_end_of_stream(Stream), read_line(Stream, Line), read_lines(Stream, Lines). read_line(Stream, Line) :- read_line_to_codes(Stream, Codes), maplist(char_code, Line, Codes). % Solve the Sokoban puzzle using DFS sokoban(Board, Moves, Solution) :- solved(Board), Solution = Board, Moves = []. sokoban(Board, Moves, Solution) :- move(Board, Dir, NewBoard), \+ member(NewBoard, Moves), sokoban(NewBoard, [NewBoard|Moves], Solution1), Solution = [Dir|Solution1]. % Check if the board is solved (all boxes are on targets) solved(Board) :- findall(Box, (member(Box, Board), member($, Box)), Boxes), findall(Target, (member(Target, Board), member(., Target)), Targets), subset(Boxes, Targets). % Find the position of the player on the board player(Board, row(Row), col(Col)) :- nth0(Row, Board, RowList), nth0(Col, RowList, '1'). % Find the cell at the given row and column cell(Board, row(Row), col(Col), Cell) :- nth0(Row, Board, RowList), nth0(Col, RowList, Cell). % Move the player in the given direction % If the player pushes a box, move the box as well move(Board, Dir, NewBoard) :- player(Board, row(Row), col(Col)), cell(Board, row(NewRow), col(NewCol), Cell), direction(Dir, dRow, dCol), NewRow is Row + dRow, NewCol is Col + dCol, ( Cell = ' ' ; Cell = '.', replace(Board, Row, Col, ' ', Board1), replace(Board1, NewRow, NewCol, '1', NewBoard) ; Cell = '$' ; Cell = '*', cell(Board, row(NewRow2), col(NewCol2), Cell2), NewRow2 is NewRow + dRow, NewCol2 is NewCol + dCol, (Cell2 = ' ' ; Cell2 = '.'), replace(Board, Row, Col, ' ', Board1), replace(Board1, NewRow, NewCol, '1', Board2), replace(Board2, NewRow2, NewCol2, '$', NewBoard) ). % Replace an element at the given row and column replace(List, Row, Col, NewElem, NewList) :- nth0(Row, List, RowList), nth0(Col, RowList, _, RestRow), nth0(Col, NewRow, NewElem, RestRow), nth0(Row, NewList, NewRow, RestList). % Define the directions direction(up, -1, 0). direction(down, 1, 0). direction(left, 0, -1). direction(right, 0, 1). % Example usage solve_sokoban(Filename, Solution) :- read_board(Filename, Board), sokoban(Board, [Board], Solution).