Toggle navigation
?
users online
Logout
Open hangout
Open chat for current file
% s(CASP) Programming :- use_module(library(scasp)). % Uncomment to suppress warnings :- style_check(-discontiguous). :- style_check(-singleton). %:- set_prolog_flag(scasp_unknown, fail). % Define the nodes that exist. These represent areas of a terrain on an RPG map. node(a). node(b). node(c). node(d). node(e). % Define the terrain types. terrain(forest). terrain(grass). terrain(swamp). terrain(sand). terrain(long_grass). terrain(port). terrain(mountain). terrain(ocean). terrain(river). % Define the movement types movement_type(walk). movement_type(sail). movement_type(canoe). % Assign movement types to terrain types has_move_type(forest,walk). has_move_type(grass,walk). has_move_type(swamp,walk). has_move_type(sand,walk). has_move_type(long_grass,walk). has_move_type(port,walk). has_move_type(ocean,sail). has_move_type(port,sail). % Canoeing is just walking but also rivers. has_move_type(river,canoe). has_move_type(X,canoe) :- has_move_type(X,walk). % Flying is where ships can land. has_move_type(grass,fly). has_move_type(long_grass,fly). has_move_type(swamp,fly). % Create a utility predicate for list membership. mem(X,[X|_]). mem(X,[_|T]) :- mem(X,T). % Define whether you can move from one node directly to another given a movement type. adjacent_movable(X,Y,Type) :- node(X), node(Y), X \= Y, adjacent(X,Y), node_terrain(X,T1), node_terrain(Y,T2), has_move_type(T1,Type), has_move_type(T2,Type). % Define whether there is a path from one node to another given a movement type. move_path([X,Y],Type) :- Type \= fly, adjacent_movable(X,Y,Type). move_path([X|Tail],Type) :- Type \= fly, Tail = [First,_], adjacent_movable(X,First,Type), move_path(Tail,Type), not mem(X,Tail). move_path([X,Y],fly) :- node(X), node(Y), node_terrain(X,TX), node_terrain(Y,TY), has_move_type(TX,fly), has_move_type(TY,fly). % Create a utility to find the last element of a list. last([X|[]],X). last([_|T],L) :- last(T,L). % Define a predicate for whether there is a path from one node to another node of a given type. movable(X,Y,Type) :- move_path(L,Type), L = [H|T], H = X, last(T,Y). % Allow the reasoner to make assumptions about adjacency. #abducible adjacent(X,Y). % Allow the reasoner to make assumptions about terrain types. % but require it to reach a grounded conclusion about all nodes. node_terrain(X,ocean) :- node(X), not node_terrain(X,port), %not node_terrain(X,mountain), %not node_terrain(X,river), %not node_terrain(X,long_grass), %not node_terrain(X,swamp), %not node_terrain(X,sand), not node_terrain(X,forest), not node_terrain(X,grass). node_terrain(X,port) :- node(X), not node_terrain(X,ocean), %not node_terrain(X,mountain), %not node_terrain(X,river), %not node_terrain(X,long_grass), %not node_terrain(X,swamp), %not node_terrain(X,sand), not node_terrain(X,forest), not node_terrain(X,grass). %node_terrain(X,mountain) :- % node(X), % not node_terrain(X,ocean), % not node_terrain(X,port), % not node_terrain(X,river), % not node_terrain(X,long_grass), % not node_terrain(X,swamp), % not node_terrain(X,sand), % not node_terrain(X,forest), % not node_terrain(X,grass). %node_terrain(X,river) :- % node(X), % not node_terrain(X,ocean), % not node_terrain(X,port), % not node_terrain(X,mountain), % not node_terrain(X,long_grass), % not node_terrain(X,swamp), % not node_terrain(X,sand), % not node_terrain(X,forest), % not node_terrain(X,grass). %node_terrain(X,long_grass) :- % node(X), % not node_terrain(X,ocean), % not node_terrain(X,port), % not node_terrain(X,mountain), % not node_terrain(X,river), % not node_terrain(X,swamp), % not node_terrain(X,sand), % not node_terrain(X,forest), % not node_terrain(X,grass). %node_terrain(X,swamp) :- % node(X), % not node_terrain(X,ocean), % not node_terrain(X,port), % not node_terrain(X,mountain), % not node_terrain(X,river), % not node_terrain(X,long_grass), % not node_terrain(X,sand), % not node_terrain(X,forest), % not node_terrain(X,grass). %node_terrain(X,sand) :- % node(X), % not node_terrain(X,ocean), % not node_terrain(X,port), % not node_terrain(X,mountain), % not node_terrain(X,river), % not node_terrain(X,long_grass), % not node_terrain(X,swamp), % not node_terrain(X,forest), % not node_terrain(X,grass). node_terrain(X,forest) :- node(X), not node_terrain(X,ocean), not node_terrain(X,port), %not node_terrain(X,mountain), %not node_terrain(X,river), %not node_terrain(X,long_grass), %not node_terrain(X,swamp), %not node_terrain(X,sand), not node_terrain(X,grass). node_terrain(X,grass) :- node(X), not node_terrain(X,ocean), not node_terrain(X,port), %not node_terrain(X,mountain), %not node_terrain(X,river), %not node_terrain(X,long_grass), %not node_terrain(X,swamp), %not node_terrain(X,sand), not node_terrain(X,forest). % Each node may have only one terrain. false :- node_terrain(N,T1), node_terrain(N,T2), T1 \= T2. % Every node must be adjacent to at least one other node. in_adjacency(X) :- adjacent(X,_). in_adjacency(X) :- adjacent(_,X). false :- node(X), not in_adjacency(X). %-movable(X,Y,Z) :- not movable(X,Y,Z). test :- movable(a,b,walk), movable(d,e,walk), not movable(a,d,walk), not movable(a,e,walk), movable(b,d,sail), not movable(b,d,walk), movable(a,e,fly). % Ports must be adjacent to oceans. adjacent_to_ocean(X) :- node(X), node(Y), X\=Y, node_terrain(Y,ocean). false :- node(X), node_terrain(X,port), not adjacent_to_ocean(X). % Ports must not be adjacent to other ports. adjacent_ports :- node(X), node(Y), node_terrain(X,port), node_terrain(Y,port), adjacent(X,Y). false:- adjacent_ports. % This is not working properly, because in disproving the ability to walk from a to d, % for example, it is sufficient to show that there is some hypothetical pair of nodes % for which move_path does not hold for walking. % This goes to how the dual programs are built. Each condition of a rule must be % both necessary for the conclusion to hold, and sufficient to disprove the conclusion % if the preceeding conditions hold. In this case, it is not sufficient that some arbitrary % walking path does not exist to demonstrate that one doesn't exist between two specific % nodes. So the dual program for movable (-movable) will be triggered if a hypothetical path doesn't exist. /** <examples> Your example queries go here, e.g. ?- ? p(X). */