The goal go(N, Moves), where N is between 1 and 30, will solve the Nth game included in the code using IDA* search. (A solution to the Nth game requires at least N moves.)
code = 2048 check_determ domains value = integer move = integer posn = move* moves = move* posns = posn* database limit(value) predicates go(integer,moves) game(integer,posn,posn) idastar(posn,posn,moves) nondeterm idastar_1(posns,posn,value,value,value,moves) nondeterm member(posn,posns) nondeterm update(posn,move,posn) value(posn,posn,value) value_1(posn,posn,value,value,value) location(posn,move,value,value,value) clauses go(I, Moves):- game(I, Initial, Final), idastar(Initial, Final, Moves). game( 0, [7,1,6, 5,0,2, 4,3,8], [7,1,6, 5,0,2, 4,3,8]). game( 1, [1,2,6,4,3,8,5,7,0], [1,2,6,4,3,8,5,0,7]). game( 2, [0,5,2,7,8,1,6,4,3], [5,2,0,7,8,1,6,4,3]). game( 3, [2,6,5,3,8,7,1,0,4], [0,6,5,2,3,7,1,8,4]). game( 4, [7,1,3,5,0,2,4,8,6], [7,1,3,4,0,2,8,5,6]). game( 5, [1,4,6,8,3,0,5,7,2], [8,1,6,5,4,3,0,7,2]). game( 6, [2,0,6,3,5,8,4,1,7], [2,5,6,1,8,0,3,4,7]). game( 7, [2,3,7,0,1,8,4,6,5], [2,7,8,1,6,3,4,5,0]). game( 8, [5,8,6,2,7,3,4,0,1], [5,6,3,0,7,8,2,4,1]). game( 9, [3,5,6,1,2,8,4,7,0], [1,3,5,8,2,6,4,0,7]). game(10, [5,1,2,8,6,7,3,4,0], [1,2,0,5,3,7,6,8,4]). game(11, [4,3,6,0,2,5,1,7,8], [4,3,5,1,0,2,7,6,8]). game(12, [2,1,3,7,0,6,5,8,4], [1,6,8,7,2,3,0,5,4]). game(13, [1,0,6,3,5,8,2,4,7], [1,5,7,3,8,4,2,6,0]). game(14, [4,2,3,6,0,5,7,8,1], [0,5,8,4,3,2,6,7,1]). game(15, [6,3,8,0,2,5,1,7,4], [1,2,0,5,8,6,7,3,4]). game(16, [5,3,6,2,1,4,0,7,8], [3,1,6,7,5,4,8,2,0]). game(17, [1,0,6,8,3,2,5,7,4], [8,1,7,2,5,6,0,3,4]). game(18, [3,4,7,1,0,5,2,8,6], [4,7,2,5,1,6,3,8,0]). game(19, [4,1,7,8,3,0,5,6,2], [0,7,2,4,8,1,3,6,5]). game(20, [7,8,3,2,0,5,4,1,6], [6,5,7,8,2,3,0,4,1]). game(21, [5,0,1,8,4,2,3,7,6], [3,8,4,6,1,2,0,7,5]). game(22, [1,2,0,7,4,5,3,6,8], [6,3,4,7,0,1,8,2,5]). game(23, [8,5,2,0,6,7,4,1,3], [1,6,0,7,5,2,3,8,4]). game(24, [5,1,0,6,8,2,7,4,3], [3,1,5,4,0,7,6,2,8]). game(25, [2,8,3,0,1,5,4,7,6], [6,3,4,1,2,7,0,5,8]). game(26, [1,7,5,4,0,3,2,8,6], [0,7,2,5,8,6,4,3,1]). game(27, [6,1,2,5,8,0,4,7,3], [0,4,8,1,7,3,2,5,6]). game(28, [2,4,6,7,0,5,3,1,8], [1,8,3,4,5,7,0,6,2]). game(29, [2,0,1,6,8,4,3,7,5], [0,5,7,3,8,4,1,6,2]). game(30, [0,2,6,8,3,7,5,1,4], [4,2,5,1,3,8,6,7,0]). idastar(_, _, _):- retract(limit(_)), fail. idastar(Initial, Final, Moves):- value(Initial, Final, F), asserta(limit(F)), retract(limit(Limit)), asserta(limit(32767)), idastar_1([Initial], Final, 0, F, Limit, Moves), !. idastar_1([Final|_], Final, _, _, _, []):-!. idastar_1(Posns0, Final, G, F, Limit, [Move|Moves]):- F <= Limit, !, Posns0 = [Posn|Posns], update(Posn, Move, Posn1), not(member(Posn1, Posns)), value(Posn1, Final, H1), G1 = G + 1, F1 = G1 + H1, idastar_1([Posn1|Posns0], Final, G1, F1, Limit, Moves). idastar_1(_, _, _, F, _, _):- limit(NextLimit), F < NextLimit, retract(limit(_)), !, asserta(limit(F)), fail. /* member(X, Xs) is true if the element X is contained in the list Xs. */ member(X, [X|_]). member(X, [_|Xs]):-member(X, Xs). /* update(Posn0, Move, Posn) is true if Move changes Posn0 to Posn. */ update([0,B,C,D,E,F,G,H,I], B, [B,0,C,D,E,F,G,H,I]). update([0,B,C,D,E,F,G,H,I], D, [D,B,C,0,E,F,G,H,I]). update([A,0,C,D,E,F,G,H,I], A, [0,A,C,D,E,F,G,H,I]). update([A,0,C,D,E,F,G,H,I], C, [A,C,0,D,E,F,G,H,I]). update([A,0,C,D,E,F,G,H,I], E, [A,E,C,D,0,F,G,H,I]). update([A,B,0,D,E,F,G,H,I], B, [A,0,B,D,E,F,G,H,I]). update([A,B,0,D,E,F,G,H,I], F, [A,B,F,D,E,0,G,H,I]). update([A,B,C,0,E,F,G,H,I], A, [0,B,C,A,E,F,G,H,I]). update([A,B,C,0,E,F,G,H,I], E, [A,B,C,E,0,F,G,H,I]). update([A,B,C,0,E,F,G,H,I], G, [A,B,C,G,E,F,0,H,I]). update([A,B,C,D,0,F,G,H,I], B, [A,0,C,D,B,F,G,H,I]). update([A,B,C,D,0,F,G,H,I], D, [A,B,C,0,D,F,G,H,I]). update([A,B,C,D,0,F,G,H,I], F, [A,B,C,D,F,0,G,H,I]). update([A,B,C,D,0,F,G,H,I], H, [A,B,C,D,H,F,G,0,I]). update([A,B,C,D,E,0,G,H,I], C, [A,B,0,D,E,C,G,H,I]). update([A,B,C,D,E,0,G,H,I], E, [A,B,C,D,0,E,G,H,I]). update([A,B,C,D,E,0,G,H,I], I, [A,B,C,D,E,I,G,H,0]). update([A,B,C,D,E,F,0,H,I], D, [A,B,C,0,E,F,D,H,I]). update([A,B,C,D,E,F,0,H,I], H, [A,B,C,D,E,F,H,0,I]). update([A,B,C,D,E,F,G,0,I], E, [A,B,C,D,0,F,G,E,I]). update([A,B,C,D,E,F,G,0,I], G, [A,B,C,D,E,F,0,G,I]). update([A,B,C,D,E,F,G,0,I], I, [A,B,C,D,E,F,G,I,0]). update([A,B,C,D,E,F,G,H,0], F, [A,B,C,D,E,0,G,H,F]). update([A,B,C,D,E,F,G,H,0], H, [A,B,C,D,E,F,G,0,H]). /* value(Current, Final, Value) is true if Value is the sum of the */ /* Manhattan distances of each tile in the Current position relative to */ /* the same tile in the Final position. */ value(Current, Final, Value):- value_1(Current, Final, 0, 0, Value). value_1([], _, _, Value, Value). value_1([0|Tiles], Final, N, Value0, Value):-!, N1 = N + 1, value_1(Tiles, Final, N1, Value0, Value). value_1([Tile|Tiles], Final, N, Value0, Value):- location(Final, Tile, 0, Row1, Col1), /* (Row1, Col1) is where the tile should be, */ /* (N div 3, N mod 3) is where the tile is. */ Value1 = Value0 + abs(Row1 - N div 3) + abs(Col1 - N mod 3), N1 = N + 1, value_1(Tiles, Final, N1, Value1, Value). /* location(Position, Tile, 0, Row, Col) is true if (Row, Col) is the */ /* location of the Tile in the Position. */ location([Tile|_], Tile, N, Row, Col):-!, Row = N div 3, Col = N mod 3. location([_|Tiles], Tile, N, Row, Col):- N1 = N + 1, location(Tiles, Tile, N1, Row, Col).