its... something?
This commit is contained in:
parent
c856eabad0
commit
59cc1e1d04
1 changed files with 84 additions and 1 deletions
|
@ -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).
|
||||
|
|
Reference in a new issue