
% Name:
% Matric#:
% Date:


%%% File:     puzzlesample.pl
%%% Author:   Tim Smith <tim.smith@ed.ac.uk>
%%% 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:

/*




*/




