One Player Games (Puzzles)

player.pl

#!/usr/bin/env swipl

:- initialization(main).

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

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

goal(State) :-
  update_state(State),
  (true(control(Player)) ; role(Player)), % try for more than one player games
  goal(Player, 100).

s(_Move0-State0, does(Player, Move1)-State1) :-
  update_state(State0),
  \+terminal,
  (true(control(Player)) ; role(Player)), % try for more than one player games
  legal(Player, Move1),
  retractall(does(_,_)),
  assertz(does(Player, Move1)),
  setof(Next, next(Next), 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).

main([File]) :-
  consult(File),
  findinit(Start),
  solve(Start, Path),
  format('~w~n', [Path]).

Blocks

blocks.kif

Appears identical to blocksWorld.kif

role(robot).
init(clear(b)).
init(clear(c)).
init(on(c, a)).
init(table(a)).
init(table(b)).
init(step(1)).
next(on(X, Y)) :- does(robot, s(X, Y)).
next(on(X, Y)) :- does(robot, s(_U, _V)), true(on(X, Y)).
next(table(X)) :- does(robot, s(U, _V)), true(table(X)), dif(U, X).
next(clear(Y)) :- does(robot, s(_U, V)), true(clear(Y)), dif(V, Y).
next(on(X, Y)) :- does(robot, u(U, _V)), true(on(X, Y)), dif(U, X).
next(table(X)) :- does(robot, u(X, _Y)).
next(table(X)) :- does(robot, u(_U, _V)), true(table(X)).
next(clear(Y)) :- does(robot, u(_X, Y)).
next(clear(X)) :- does(robot, u(_U, _V)), true(clear(X)).
next(step(Y)) :- true(step(X)), successor(X, Y).
successor(1, 2).
successor(2, 3).
successor(3, 4).
legal(robot, s(X, Y)) :- true(clear(X)), true(table(X)), true(clear(Y)), dif(X, Y).
legal(robot, u(X, Y)) :- true(clear(X)), true(on(X, Y)).
goal(robot, 100) :- true(on(a, b)), true(on(b, c)).
goal(robot, 0) :- \+true(on(a, b)).
goal(robot, 0) :- \+true(on(b, c)).
terminal :- true(step(4)).
terminal :- true(on(a, b)), true(on(b, c)).

Solution: [does(robot, u(c, a)), does(robot, s(b, c)), does(robot, s(a, b))]

Blocks World (two instances, played in parallel)

blocksWorldParallel.kif

blocksWorldParallel.pl

role(robot).
init(clear(b1)).
init(clear(c1)).
init(on(c1, a1)).
init(table(a1)).
init(table(b1)).
init(clear(b2)).
init(clear(c2)).
init(on(c2, a2)).
init(table(a2)).
init(table(b2)).
init(step(1)).
legal(robot, do(ss, X1, Y1, X2, Y2)) :- partofgame1(X1), partofgame1(Y1), partofgame2(X2), partofgame2(Y2), legalstack(X1, Y1), legalstack(X2, Y2).
legal(robot, do(su, X1, Y1, X2, Y2)) :- partofgame1(X1), partofgame1(Y1), partofgame2(X2), partofgame2(Y2), legalstack(X1, Y1), legalunstack(X2, Y2).
legal(robot, do(us, X1, Y1, X2, Y2)) :- partofgame1(X1), partofgame1(Y1), partofgame2(X2), partofgame2(Y2), legalunstack(X1, Y1), legalstack(X2, Y2).
legal(robot, do(uu, X1, Y1, X2, Y2)) :- partofgame1(X1), partofgame1(Y1), partofgame2(X2), partofgame2(Y2), legalunstack(X1, Y1), legalunstack(X2, Y2).
next(on(X, Y)) :- does(robot, do(Move, X, Y, _D1, _D2)), game1stack(Move).
next(on(X, Y)) :- partofgame1(X), partofgame1(Y), does(robot, do(Move, _U, _V, _D1, _D2)), game1stack(Move), true(on(X, Y)).
next(table(X)) :- partofgame1(X), does(robot, do(Move, U, _V, _D1, _D2)), game1stack(Move), true(table(X)), dif(U, X).
next(clear(Y)) :- partofgame1(Y), does(robot, do(Move, _U, V, _D1, _D2)), game1stack(Move), true(clear(Y)), dif(V, Y).
next(on(X, Y)) :- partofgame1(X), partofgame1(Y), does(robot, do(Move, U, _V, _D1, _D2)), game1unstack(Move), true(on(X, Y)), dif(U, X).
next(table(X)) :- does(robot, do(Move, X, _Y, _D1, _D2)), game1unstack(Move).
next(table(X)) :- partofgame1(X), does(robot, do(Move, _U, _V, _D1, _D2)), game1unstack(Move), true(table(X)).
next(clear(Y)) :- does(robot, do(Move, _X, Y, _D1, _D2)), game1unstack(Move).
next(clear(X)) :- partofgame1(X), does(robot, do(Move, _U, _V, _D1, _D2)), game1unstack(Move), true(clear(X)).
next(on(X, Y)) :- does(robot, do(Move, _D1, _D2, X, Y)), game2stack(Move).
next(on(X, Y)) :- partofgame2(X), partofgame2(Y), does(robot, do(Move, _D1, _D2, _U, _V)), game2stack(Move), true(on(X, Y)).
next(table(X)) :- partofgame2(X), does(robot, do(Move, _D1, _D2, U, _V)), game2stack(Move), true(table(X)), dif(U, X).
next(clear(Y)) :- partofgame2(Y), does(robot, do(Move, _D1, _D2, _U, V)), game2stack(Move), true(clear(Y)), dif(V, Y).
next(on(X, Y)) :- partofgame2(X), partofgame2(Y), does(robot, do(Move, _D1, _D2, U, _V)), game2unstack(Move), true(on(X, Y)), dif(U, X).
next(table(X)) :- does(robot, do(Move, _D1, _D2, X, _Y)), game2unstack(Move).
next(table(X)) :- partofgame2(X), does(robot, do(Move, _D1, _D2, _U, _V)), game2unstack(Move), true(table(X)).
next(clear(Y)) :- does(robot, do(Move, _D1, _D2, _X, Y)), game2unstack(Move).
next(clear(X)) :- partofgame2(X), does(robot, do(Move, _D1, _D2, _U, _V)), game2unstack(Move), true(clear(X)).
next(step(Y)) :- true(step(X)), succ(X, Y).
goal(robot, 100) :- game1-100, game2-100.
goal(robot, 50) :- game1-100, game2-0.
goal(robot, 50) :- game1-0, game2-100.
goal(robot, 0) :- game1-0, game2-0.
terminal :- true(step(4)).
terminal :- true(on(a1, b1)), true(on(b1, c1)), true(on(a2, b2)), true(on(b2, c2)).
legalstack(X, Y) :- true(clear(X)), true(table(X)), true(clear(Y)), dif(X, Y).
legalunstack(X, Y) :- true(clear(X)), true(on(X, Y)).
game1-100 :- true(on(a1, b1)), true(on(b1, c1)).
game1-0 :- \+(true(on(a1, b1))).
game1-0 :- \+(true(on(b1, c1))).
game2-100 :- true(on(a2, b2)), true(on(b2, c2)).
game2-0 :- \+(true(on(a2, b2))).
game2-0 :- \+(true(on(b2, c2))).
succ(1, 2).
succ(2, 3).
succ(3, 4).
partofgame1(a1).
partofgame1(b1).
partofgame1(c1).
partofgame2(a2).
partofgame2(b2).
partofgame2(c2).
game1stack(ss).
game1stack(su).
game1unstack(us).
game1unstack(uu).
game2stack(ss).
game2stack(us).
game2unstack(su).
game2unstack(uu).

Blocks World (two instances, played in series)

blocksWorldSerial.pl

role(robot).
init(clear1(b)).
init(clear1(c)).
init(on1(c, a)).
init(table1(a)).
init(table1(b)).
init(step1(1)).
init(clear2(b)).
init(clear2(c)).
init(on2(c, a)).
init(table2(a)).
init(table2(b)).
init(step2(1)).
legal(robot, stack1(X, Y)) :- \+(game1over), legalstack1(X, Y).
legal(robot, unstack1(X, Y)) :- \+(game1over), legalunstack1(X, Y).
legal(robot, stack2(X, Y)) :- game1over, legalstack2(X, Y).
legal(robot, unstack2(X, Y)) :- game1over, legalunstack2(X, Y).
next(on1(X, Y)) :- does(robot, stack1(X, Y)).
next(on1(X, Y)) :- true(on1(X, Y)), does(robot, unstack1(W, _Z)), dif(X, W).
next(on1(X, Y)) :- true(on1(X, Y)), does(robot, stack1(W, _Z)), dif(X, W).
next(on1(X, Y)) :- true(on1(X, Y)), game1over.
next(table1(X)) :- does(robot, unstack1(X, _Y)).
next(table1(X)) :- true(table1(X)), does(robot, unstack1(_Y, _Z)).
next(table1(X)) :- true(table1(X)), does(robot, stack1(Y, _Z)), dif(X, Y).
next(table1(X)) :- true(table1(X)), game1over.
next(clear1(Y)) :- does(robot, unstack1(_X, Y)).
next(clear1(Y)) :- true(clear1(Y)), does(robot, unstack1(_X, _Z)).
next(clear1(Y)) :- true(clear1(Y)), does(robot, stack1(_X, Z)), dif(Y, Z).
next(clear1(X)) :- true(clear1(X)), game1over.
next(step1(Y)) :- \+(game1over), true(step1(X)), succ(X, Y).
next(step1(X)) :- game1over, true(step1(X)).
next(on2(X, Y)) :- does(robot, stack2(X, Y)).
next(on2(X, Y)) :- true(on2(X, Y)), does(robot, unstack2(W, _Z)), dif(X, W).
next(on2(X, Y)) :- true(on2(X, Y)), does(robot, stack2(W, _Z)), dif(X, W).
next(on2(X, Y)) :- true(on2(X, Y)), \+(game1over).
next(table2(X)) :- does(robot, unstack2(X, _Y)).
next(table2(X)) :- true(table2(X)), does(robot, unstack2(_Y, _Z)).
next(table2(X)) :- true(table2(X)), does(robot, stack2(Y, _Z)), dif(X, Y).
next(table2(X)) :- true(table2(X)), \+(game1over).
next(clear2(Y)) :- does(robot, unstack2(_X, Y)).
next(clear2(Y)) :- true(clear2(Y)), does(robot, unstack2(_X, _Z)).
next(clear2(Y)) :- true(clear2(Y)), does(robot, stack2(_X, Z)), dif(Y, Z).
next(clear2(X)) :- true(clear2(X)), \+(game1over).
next(step2(Y)) :- game1over, true(step2(X)), succ(X, Y).
next(step2(X)) :- \+(game1over), true(step2(X)).
next(game1overlock) :- game1termcond.
next(game1overlock) :- true(game1overlock).
terminal :- game2termcond.
goal(robot, 100) :- goal1-100, goal2-100.
goal(robot, 50) :- goal1-100, goal2-0.
goal(robot, 50) :- goal1-0, goal2-100.
goal(robot, 0) :- goal1-0, goal2-0.
game1over :- game1termcond.
game1over :- true(game1overlock).
game1termcond :- true(step1(4)).
game2termcond :- true(step2(4)).
goal1-100 :- true(on1(a, b)), true(on1(b, c)).
goal1-0 :- \+(true(on1(a, b))).
goal1-0 :- \+(true(on1(b, c))).
goal2-100 :- true(on2(a, b)), true(on2(b, c)).
goal2-0 :- \+(true(on2(a, b))).
goal2-0 :- \+(true(on2(b, c))).
legalstack1(X, Y) :- true(clear1(X)), true(table1(X)), true(clear1(Y)), dif(X, Y).
legalunstack1(X, Y) :- true(clear1(X)), true(on1(X, Y)).
legalstack2(X, Y) :- true(clear2(X)), true(table2(X)), true(clear2(Y)), dif(X, Y).
legalunstack2(X, Y) :- true(clear2(X)), true(on2(X, Y)).
succ(1, 2).
succ(2, 3).
succ(3, 4).

Buttons and Lights

There are two versions

buttons.kif

buttons.pl

buttonslights.kif

buttonslights.pl

Coins

coins.kif

[does(you, jump(4, 7)), does(you, jump(6, 2)), does(you, jump(1, 3)), does(you, jump(5, 8))]

Puzzles which this script fails on

http://games.ggp.org/base/games/brainteaserextended/brainteaserextended.kif

http://games.ggp.org/base/games/chineseCheckers1/chineseCheckers1.kif

http://games.ggp.org/base/games/circlesolitaire/circlesolitaire.kif

hanoi.pl