/* missionaries and cannibals. Represent a state by a tuple with three integers (M,C,B) where M is the number of missionaries on the left bank, C is the number of cannibals on the left bank and B is the number of boats on the left bank. */ %:- module(mc, [start/1,goal/1,arc/2,writeState/1]). start((3,3,1)). goal((0,0,_)). % there is an arc from S1 to S2 if there is a possible arc to legal state S2. arc(S1,S2) :- possibleArc(S1,S2), legal(S2). % possibleArc(S1,S2) iff we can go from S1 to (possibly illegal) state S2 possibleArc((M1,C1,B1),(M2,C2,B2)) :- delta(DM,DC,DB), M2 is M1+DM, C2 is C1+DC, B2 is B1+DB. % delta(M,C,B) represents the *change* in the number of missionaries, % cannibals and boats on the left bank of the river, respectively, for a % given potential move. delta(2,0,1). % MM go left delta(1,1,1). % MC go left delta(0,2,1). % CC go left delta(1,0,1). % M go left delta(0,1,1). % C go left delta(-2,0,-1). % MM go right delta(-1,-1,-1). % MC go right delta(0,-2,-1). % CC go right delta(-1,0,-1). % M go right delta(0,-1,-1). % C go right % legal(M,C) is true iff it is a legal state to have M missionaries % and C cannibals on the left bank (checking of course who is then % neccessarily on the right bank). legal((M,C,B)) :- (B=0;B=1), legal1(M,C), MR is 3-M, CR is 3-C, legal1(MR,CR). % legal1(M,C) checks one bank -- the number of missionaries and % cannibals must be between 0 and 3 and no missiionary can be in danger. legal1(M,C) :- M>=0, C>=0, M=<3, C=<3, (M=0;M>=C). writeState((M,C,B)) :- S is 6-M-C, MR is 3-M, CR is 3-C, SR is 6-MR-CR, write('"'), doForN(S,write(' ')), doForN(M,write('M')), doForN(C,write('C')), (B=1 -> write(' |o | ') | write(' | o| ')), doForN(MR,write('M')), doForN(CR,write('C')), doForN(SR,write(' ')), write('"'). doForN(N,_) :- N<1,!. doForN(N,Goal) :- call(Goal), N2 is N-1, doForN(N2,Goal).