diff --git a/TP1/Prolog/main.pl b/TP1/Prolog/main.pl index 8551b20..0bbd1ea 100644 --- a/TP1/Prolog/main.pl +++ b/TP1/Prolog/main.pl @@ -1 +1,84 @@ -% :) +% 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).