In the previous section, you saw that Prolog can be used to navigate
around structures defined by sets of facts. The following program
navigates in a more literal sense. Please start by looking at the file
entititled BOARD which comes with this supplement. It defines the basic
sells, plus three ones derived from them:
Together, these describe a simple street layout, with squares containing shops and fuel stations. Unlike Monopoly, the squares are not confined to the outside of the board, but can form streets, some looped back on themselves, wandering over its interior.
More specifically, the predicates have the meanings given below:
square(S,X,Y): S is the number of a square, lying at co-ordinate . Each square has a unique number; these are integers (whole numbers), and work upwards from 1. Adjacent squares do not necessarily have adjacent numbers.
building(S,B): B is the name of the building in square number S.
squaredefines where squares lie and what they contain,
joinsdefines how they are connected. There is one clause,
joins(S1,S2)for every pair of connected squares. To make things simple, squares can only be connected by vertical, horizontal, or 45-degree diagonal lines.
in(S,L): The board contains several streets that curve back on themselves, forming closed loops. Each loop has a name (you will see why later). There is one clause,
in(S,L)for every square S that lies in a loop called L. You can think of the loops as being distinct regions of a city, such as the City in London or the central part of Oxford, except that to keep things simple, they do not contain any roads apart from the loop itself.
loop(L): This defines the names of the loops. There is one clause for each loop.
adjacent(S1,S2): This is true if S1 joins S2. Note that it is defined in terms of
joins: S1 is next to S2 if S1 joins S2 or S2 joins S1. The reason for this is something we alluded to in the cave world example of Supplement 2. If Prolog has a fact such as
joins(66,67).it does not automatically assume that the converse -
joins(67,66)- is true. So we have to define a new predicate which holds no matter which way the squares are said to be joined. We could instead have had two sets of facts - both
joins(67,66)- but this would waste space.
The import of this is that if you want to find out about connected
squares, you should use
clockwise(S1,S2): This is true if square S1 and S2 are both in the same loop, and S2 is immediately next to, and clockwise of, S1. Its purpose is to give you a simple way of finding your way round loops. It is defined in terms of
joins, and only works because I took care, when generating the board definition, to make sure that the
joinsfacts always had their arguments in an order which would make it work.
distance(S1,S2,D): This sets D to the distance between S1 and S2. It uses
is, an operator for doing arithmetic that you'll meet in Lesson 6. The formula is the standard one for working out distance in terms of X and Y co-ordinates:
X^2means X squared, and
sqrt(...)means the square root of.
If you care to compare the BOARD file with the diagram of the board, it should become clear what these facts say.