You are on page 1of 6

Fabian loves puzzling.

One of his favourite puzzles is the well-known game


Sokoban (“warehouse keeper”). In this game, the player controls an em-
ployee in a warehouse, see Figure 1. This employee must push a number of
boxes to proper storage locations in the warehouse. Every storage location
can contain a single box. Boxes standing in a storage location are of a
darker color (i.e. one box of Figure 1 is already in a storage location).
An employee can only push away a box (i.e. in a forward direction),
and only as long as there are no other boxes or walls in its way.

0 1 2 3 4 5 6 7
0

Figure 1: An example of a Sokoban puzzle.

We can describe a Sokoban field using a sokoban/4 Prolog term. A


sokoban(Width, Height, CurrPos, Field) term indicates that on a map
of dimensions Width by Height, the current position of the player is CurrPos.
Field indicates the game elements on the map. Game elements are described

1
using wall((X1,Y1),(X2,Y2)), crate(Id,X,Y) and storage(X,Y) prolog
terms. These terms identify the coordinates of respectively walls, boxes and
storage locations, where (0,0) corresponds to the top left corner. In the case
of crate/3 and storage/2 terms, the X and Y directly indicate the object’s
coordinates, for wall/2 terms the coordinates of the end points are given.
Because walls always run strictly horizontal or strictly vertical, either the
X or the Y coordinate of both coordinates is the same. Furthermore you
may assume that the first coordinate of the two is always the left uppermost
coordinate. This way, Figure 2 can be described as:

0 1 2 3 4 5 6
0
1
2
3
4
5
6

Figure 2: Simple example.

sokoban (7 ,7 , (1 ,1) , [ wall ((0 ,0) ,(6 ,0) ) , wall ((6 ,0)
,(6 ,6) ) , wall ((0 ,6) ,(6 ,6) ) , wall ((0 ,0) ,(0 ,6) ) ,
wall ((3 ,0) ,(3 ,2) ) , wall ((3 ,4) ,(3 ,6) ) , crate
(1 ,3 ,3) , storage (1 ,3) ])

Fabian likes playing Sokoban games so much that he has written his
own solver. Now he asks us to check his solver for mistakes. Sadly, Fabian’s
solver only reports the order in which the boxes need to be pushed, not in
which direction or how far!

Exercise 1 Write a predicate reachable(Sokoban, (X,Y)) which suc-


ceeds if the player can reach the position (X,Y) on the board in its current

2
setup (as given by Sokoban). The player can only move horizontally and
vertically along free squares (i.e. not containing a box or a wall, storage
locations are fine as long as they do not contain a box), without pushing
any boxes. Of course, he is allowed not to move at all.

? - Sokoban = sokoban (7 ,7 , (1 ,1) , [ wall ((0 ,0) ,(6 ,0) ) ,


wall ((6 ,0) ,(6 ,6) ) , wall ((0 ,6) ,(6 ,6) ) , wall ((0 ,0)
,(0 ,6) ) , wall ((3 ,0) ,(3 ,2) ) , wall ((3 ,4) ,(3 ,6) ) ,
crate (1 ,3 ,3) , storage (1 ,3) ]) ,
findall ( Pos , reachable ( Sokoban , Pos ) , Positions ) .
Positions = [(1 ,1) , (1 ,2) , (1 ,3) , (1 ,4) , (1 ,5) ,
(2 ,1) , (2 ,2) , (2 ,3) , (2 ,4) , (2 ,5) ].

Remark: Make sure that every possible position is found exactly once,
as shown in the query above. If you do not succeed in this, then add the
following predicate definition:

reachable_once (S , Loc ) : -
findall (E , reachable (S , E ) , Locs ) ,
list_to_set ( Locs , DistLocs ) ,
member ( Loc , DistLocs ) .

In that case, for the remainder of your program, only use reachable_once.

Exercise 2 Write a predicate possible(Sokoban, CrateId, Location)


that succeeds if Location is a (X,Y) term that represents a location towards
which the player can push the box with Id CrateId on the current setup of
the board. Remark!

• The player can only push a box when he’s located right next to it. If
he’s standing left of a box, he can only push it to the right, etc.

• The player must be able to move the box by at least 1 square.

• The player is not allowed to stop pushing and change position.

3
% The player is not standing next to box 1
? - Sokoban = sokoban (7 ,7 , (1 ,1) , [ wall ((0 ,0) ,(6 ,0) ) ,
wall ((6 ,0) ,(6 ,6) ) , wall ((0 ,6) ,(6 ,6) ) , wall ((0 ,0)
,(0 ,6) ) , wall ((3 ,0) ,(3 ,2) ) , wall ((3 ,4) ,(3 ,6) ) ,
crate (1 ,3 ,3) , storage (1 ,3) ] ,
possible ( Sokoban , 1 , Location ) .
false .

% The player is standing next to box 1.


? - Sokoban = sokoban (7 ,7 , (2 ,3) , [ wall ((0 ,0) ,(6 ,0) ) ,
wall ((6 ,0) ,(6 ,6) ) , wall ((0 ,6) ,(6 ,6) ) , wall ((0 ,0)
,(0 ,6) ) , wall ((3 ,0) ,(3 ,2) ) , wall ((3 ,4) ,(3 ,6) ) ,
crate (1 ,3 ,3) , storage (1 ,3) ] ,
possible ( Sokoban , 1 , Location ) .
Location = (4 ,3) ;
Location = (5 ,3) .

% The box cannot move to the right .


? - Sokoban = sokoban (7 ,7 , (4 ,3) , [ wall ((0 ,0) ,(6 ,0) ) ,
wall ((6 ,0) ,(6 ,6) ) , wall ((0 ,6) ,(6 ,6) ) , wall ((0 ,0)
,(0 ,6) ) , wall ((3 ,0) ,(3 ,2) ) , wall ((3 ,4) ,(3 ,6) ) ,
crate (1 ,5 ,3) , storage (1 ,3) ] ,
possible ( Sokoban , 1 , Location ) .
false .

Opdracht 3 Write a predicate check(Sokoban, Solution) which suc-


ceeds if Solution is indeed a solution for the Sokoban problem. We repre-
sent the solutions from Fabian’s solver using a list of CrateIds. Attention!
A solution is only complete if by the end, every box is standing in a storage
location. Every storage location can contain only a single box. The player
can not pause his pushing motion, so when he wants to push a box in two
different directions back to back, the id of this box should be present in the
list twice.

4
% These examples use the sokoban from Fig . 1.
% Solution in Table 1.
? - check ( sokoban (8 , 9 , (2 ,2) , [ wall ((2 ,0) , (6 ,0) ) ,
wall ((6 ,1) , (6 ,5) ) , wall ((7 ,5) ,(7 ,8) ) , wall ((0 ,8)
, (7 ,8) ) , wall ((0 , 1) , (0 ,8) ) , wall ((1 ,1) ,(2 ,1) ) ,
wall ((1 ,3) ,(2 ,3) ) , wall ((2 ,4) ,(3 ,4) ) , wall ((2 ,5)
,(2 ,5) ) , crate (1 ,3 ,2) , crate (2 ,4 ,3) , crate (3 ,4 ,4)
, crate (4 ,1 ,6) , crate (5 ,3 ,6) , crate (6 ,4 ,6) , crate
(7 ,5 ,6) , storage (1 ,2) , storage (5 ,3) , storage (1 ,4)
, storage (4 ,5) , storage (3 ,6) , storage (6 ,6) ,
storage (4 ,7) ]) , [1 ,6 ,7 ,1 ,2 ,3 ,5 ,4 ,5]) .

true .

? - check ( sokoban (8 , 9 , (2 ,2) , [ wall ((2 ,0) , (6 ,0) ) ,


wall ((6 ,1) , (6 ,5) ) , wall ((7 ,5) ,(7 ,8) ) , wall ((0 ,8)
, (7 ,8) ) , wall ((0 , 1) , (0 ,8) ) , wall ((1 ,1) ,(2 ,1) ) ,
wall ((1 ,3) ,(2 ,3) ) , wall ((2 ,4) ,(3 ,4) ) , wall ((2 ,5)
,(2 ,5) ) , crate (1 ,3 ,2) , crate (2 ,4 ,3) , crate (3 ,4 ,4)
, crate (4 ,1 ,6) , crate (5 ,3 ,6) , crate (6 ,4 ,6) , crate
(7 ,5 ,6) , storage (1 ,2) , storage (5 ,3) , storage (1 ,4)
, storage (4 ,5) , storage (3 ,6) , storage (6 ,6) ,
storage (4 ,7) ]) , [6 ,1 ,7 ,1 ,2 ,3 ,5 ,4 ,5]) .

false .

5
Table 1: Solution for Figure 1.

You might also like