Simple game tree rewritten in Game Description Language

Game Description Language

tree1_gdl.pl

:- module(tree1_gdl, 
          [role/1,
           init/1,
           legal/2,
           next/1,
           goal/2,
           terminal/0,
           true/1]).
:- use_module(tree1).
role(robot).

init(a).

true(_).

legal(robot, does(robot, Move)) :-
  true(State0),
  plie(State0, Move, _State1).

next(State1) :- true(State0), does(robot, Move), plie(State0, Move, State1). 

goal(robot, 100) :- true(State0), goal(State0).
goal(robot, 0) :- true(State0), \+goal(State0).

terminal :- true(State0), goal(State0).

Unit Tests

Function

%solve_gdl.pl
:-use_module(tree1_gdl).

update_state(State) :-
  retractall(true(_)),
  forall(member(X, State), assertz(true(X))).

findinit(Start) :-
  setof(Init, init(Init), Start).

findlegal(State0, Role, Legal) :-
  update_state(State0),
  legal(Role, Legal).

findnext(State0, does(Role, Move), State1) :-
  retractall(does(_,_)),
  assertz(does(Role, Move)),
  update_state(State0),
  setof(Next, next(Next), State1).

goal(State) :-
  update_state(State),
  terminal.

s(_Move0-State0, Move1-State1) :-
  findlegal(State0, robot, Move1),
  findnext(State0, Move1, State1).

% solve( Start, Solution):
%   Solution is a path (in reverse order) from Start to a goal

solve( Start, Solution)  :-
  breadthfirst( [ [noop-Start] | Z] - Z, Path),
  findall(Move, member(Move-_State, Path), Moves),
  reverse(Moves, [noop|Solution]).

breadthfirst( [ [Move-State | Path] | _] - _, [Move-State | Path] )  :-
  goal(State).

breadthfirst( [Path | Paths] - Z, Solution)  :-
  extend( Path, NewPaths),
  append( NewPaths, Z1, Z),              % Add NewPaths at end
  Paths \== Z1,                        % Set of candidates not empty
  breadthfirst( Paths - Z1, Solution).

extend( [Node | Path], NewPaths)  :-
  findall( [NewNode, Node | Path],
         ( s( Node, NewNode), \+ member( NewNode, [Node | Path] ) ),
         NewPaths).