% Missionaries and Cannibals puzzle

include "../library-ontology"
include "../library"

sorts
   RiverBank;

inclusions
   RiverBank << Accumulator;

% Maximum number of missionaries/cannibals
numeric_symbol MaxMiss=3

% Maximum capacity of the boat
numeric_symbol MaxBoatCapacity=2

module MC;

  objects
    M, C : Resource;
    P1, P2 : Place;
    Bank1, Bank2 : RiverBank;
    Boat : Accumulator;

  actions
    Board(Resource, 1..MaxMiss, RiverBank); 
    Disembark(Resource, 1..MaxMiss, RiverBank);
    CrossTo(Place);

  variables
    n     : 1..MaxMiss;
    n1,n2 : 0..MaxMiss;
    r     : Resource;
    b     : RiverBank;
    p     : Place;

  import TRANSFER;
    Transfer(n,r,b,Boat) is Board(r,n,b);
      
  import TRANSFER;
    Transfer(n,r,Boat,b) is Disembark(r,n,b);

  import MOVE;
    Move(Boat,p) is CrossTo(p);

  import NOCONCURRENCY;

  axioms
    Location(Bank1)=P1;
    Location(Bank2)=P2;

    % The boat cannot carry more than its capacity
    constraint -(Amount(M,Boat)=n1 & Amount(C,Boat)=n2 & MaxBoatCapacity < n1+n2); 

    nonexecutable CrossTo(p) if Amount(M,Boat)=0 & Amount(C,Boat)=0;

    % Cannibals should never outnumber missionaries
    constraint -(Amount(M,b)!=0 & Amount(M,b) < Amount(C,b));
    constraint -(Amount(M,Boat)!=0 & Amount(M,Boat) < Amount(C,Boat));