its... something?

This commit is contained in:
Mylloon 2023-03-01 02:28:50 +01:00
parent c856eabad0
commit 59cc1e1d04
Signed by: Anri
GPG key ID: A82D63DFF8D1317F

View file

@ -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).