% Name: % Matric#: % Date: %%% File: puzzlesample.pl %%% Author: Tim Smith %%% Created: Mon Oct 04 2004 %%% %%% Template for first MSc AIPP assignment, 2004 % Load the packages necessary for the SICStus random number % generator. :- use_module(library(system)). :- use_module(library(random)). %---------------------------------------------------------------------% % % initialise_randomness/0 grabs the current system time, and uses % this to 'seed' the SICStus random number generator. % initialise_randomness :- datime(datime(_, _, _, Hour, Minute, Second)), NormalHour is integer(((Hour / 24) * 30000) + 1), NormalMinute is integer(((Minute / 60) * 30000) + 1), NormalSecond is integer(((Second / 60) * 30000) + 1), setrand(rand(NormalSecond, NormalMinute, NormalHour)). %---------------------------------------------------------------------% % % play/0 is the main predicate for the human-player version of the % puzzle. It initialises the random number generator, calls % initialise_game/1 to generate a random board, calls display_game/1 % to display the initial game board, then calls play/2 to actually % play the puzzle. % play :- initialise_randomness, initialise_game(Game), display_game(Game), play(Game,0). %---------------------------------------------------------------------% % % play/2 is the main loop for the human-player version of the puzzle. % % The base case is where the current board matches the goal state. play(Game,Count) :- game_over(Game), write('Congratulations you finished the game in '), write(Count), write(' moves!'), nl, !. % Otherwise, we get the player's next move, update the game board, % display the new game board, and then recurse to do it all again. play(Game,Count) :- choose_move(Move), update_game(Game, Move, NewGame), display_game(NewGame), Count1 is Count +1, play(NewGame,Count1). %---------------------------------------------------------------------% % % solve/0 is the main predicate for the automatic solver version % of the puzzle. It initialises the random number generator, calls % initialise_game/1 to generate a random board, calls display_game/1 % to display the initial game board, calls agenda_item/3 to construct % the initial agenda item, then calls solve/3 with an initial agenda % and an empty 'closed' list. One solve/3 finishes, display the list % of moves that it has found. % solve :- initialise_randomness, initialise_game(Game), display_game(Game), agenda_item(Game, [], FirstAgendaItem), solve([FirstAgendaItem], [], Moves), write(Moves). %---------------------------------------------------------------------% % % solve/3 is the main loop for the automatic solver version of % the puzzle. % % The base case is where the board state in the first agenda item % matches the goal state. Once this happens, display the solution and % then return the list of moves as the result. solve([FirstAgendaItem | _], _, Moves) :- agenda_item(Game, Moves, FirstAgendaItem), game_over(Game), display_solution(Game,Moves), !. % Otherwise, generate all of the possible moves from the first % agenda item, keep only the worthwhile ones (the ones which have % a board state we haven't generated yet), add the worthwhile % new agenda items to the agenda, and recurse, moving the agenda % item we've just looked at to the closed list. solve([FirstAgendaItem | RestOfAgenda], AlreadyTried, Moves) :- get_possible_moves(FirstAgendaItem, PossibleMoves), get_worthwhile_moves(PossibleMoves, RestOfAgenda, AlreadyTried, WorthwhileMoves), update_agenda(WorthwhileMoves, RestOfAgenda, NewAgenda), solve(NewAgenda, [FirstAgendaItem | AlreadyTried], Moves). % display_solution/2 takes the list of moves generated by solve/3 and % writes them to the screen as game boards followed by chosen % moves. This allows you to see the solution. It uses update_game/3 and % display_game/1 which you will have written in the first part of the % assignment. display_solution(_,[]). display_solution(Board,[H|T]):- update_game(Board, H, NewBoard), display_solution(NewBoard, T), write('Push '), write(H), nl, display_game(Board). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % Don't modify any of the code above this point. Put your code below, % % in the marked areas. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %---------------------------------------------------------------------% % Put your code for initialise_game/1 here: %---------------------------------------------------------------------% % Put your code for display_game/1 here: %---------------------------------------------------------------------% % Put your code for game_over/1 here: %---------------------------------------------------------------------% % Put your code for choose_move/1 here: %---------------------------------------------------------------------% % Put your code for update_game/3 here: %---------------------------------------------------------------------% % Put your code for agenda_item/3 here: %---------------------------------------------------------------------% % Put your code for get_possible_moves/2 here: %---------------------------------------------------------------------% % Put your code for get_worthwhile_moves/4 here: %---------------------------------------------------------------------% % Put all of the versions of your code for update_agenda/3 here. % Leave only one version uncommented when you submit. You can decide % which to use. %---------------------------------------------------------------------% % solve/1 which can solve the puzzle from a specified start state. % Game must be a board state in your chosen representation. You % can use this to evaluate the different versions of update_agenda/3 solve(Game):- display_game(Game), agenda_item(Game, [], FirstAgendaItem), solve([FirstAgendaItem], [], Moves), write(Moves). %---------------------------------------------------------------------% % Put your report on the behaviour of the different versions of % update_agenda/3 here, between the comment delimiters: /* */