program Sphinx;
(* INGOUFF Christian, 11/01/12 *)
uses crt;
type
	matrix = array of array of integer;
	matchar = array of array of char;

procedure convertGrille(grille : matrix ; var grilchar : matchar ; col, line : integer);
(* INGOUFF Christian, 11/01/12 *)
var
	i,j : integer;
begin
	setLength(grilchar,col,line);
	for i := 0 to col-1 do
		for j := 0 to line-1 do
			case grille[i,j] of
				-42 : grilchar[i,j] := '#'; // Mur
				-10 : grilchar[i,j] := '@'; // Porte d'entrée
				-1, 0 : grilchar[i,j] := ' '; // Vide
				15 : grilchar[i,j] := 'O'; // Pion
				42 : grilchar[i,j] := 'X'; // Trésor
			end;
end;
								

procedure affichGrille(grille : matrix; col,line : integer);
(* INGOUFF Christian, 11/01/12 *)
var
	i, j : integer;
	grilchar : array of array of char;
begin
	convertgrille(grille,grilchar,col,line);
	write(' .');
	for i := 1 to col-1 do
		write('__',i,'___');
	writeln('__',i+1,'__.');
	for i := 0 to line-1 do
	begin
		write(' ');
		for j := 0 to col-1 do
			write('|     ');
		writeln('|');
		write(i+1);
		for j := 0 to col-1 do
			write('|  ',grilchar[i,j],'  ');
		writeln('|');
		write(' ');
		for j := 0 to col-1 do
			write('|_____');
		writeln('|');
	end;
end;

function verifIni(grille : matrix ; tres_col, tres_line, pos_col, pos_line, memory, result : integer):integer;
// INGOUFF Christian, 11/01/12
// result : ini = 0
// memory : départ : 0, bas : 1, haut : 2, gauche : 3, droite : 4
var
	bas, haut, gauche, droite : boolean;
begin
	if ((pos_col = tres_col) and (pos_line = tres_line)) then verifIni := result // cas final
	else if result > 50 then verifIni := -1 // anti boucle
	else
	begin
		bas := (not (pos_line = 7)) and (grille[pos_col,pos_line+1] >= 0);
		haut := (not (pos_line = 0)) and (grille[pos_col,pos_line-1] >= 0);
		gauche := (not (pos_col = 0)) and (grille[pos_col-1,pos_line] >= 0);
		droite := (not (pos_col = 7)) and (grille[pos_col+1,pos_line] >= 0);

		

(*		if (pos_col < tres_col) then // si trésor est à droite
		begin
			if (droite and (memory <> 4)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col+1,pos_line,4,result+1)
			else if (bas and (memory <> 1)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col,pos_line+1,1,result+1)
			else if (haut and (memory <> 2)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col,pos_line-1,2,result+1)
			else verifIni := verifIni(grille,tres_col,tres_line,pos_col-1,pos_line,3,result-1);
		end
		else if (pos_col > tres_col) then // si trésor est à gauche; on exclut le =
		begin
			if (gauche and (memory <> 3)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col-1,pos_line,3,result+1)
			else if (bas and (memory <> 1)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col,pos_line+1,1,result+1)
			else if (haut and (memory <> 2)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col,pos_line-1,2,result+1)
			else verifIni := verifIni(grille,tres_col,tres_line,pos_col-1,pos_line,4,result-1);
		end

		else if (pos_line < tres_line) then // si trésor est vers le bas
		begin
			if (bas and (memory <> 1)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col,pos_line+1,1,result+1)
			else if (droite and (memory <> 4)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col+1,pos_line,4,result+1)
			else if (gauche and (memory <> 3)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col-1,pos_line,3,result+1)
			else verifIni := verifIni(grille,tres_col,tres_line,pos_col,pos_line-1,2,result-1);
		end
		else // si trésor est vers le haut; on exclut le =
		begin
			if (haut and (memory <> 2)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col,pos_line-1,2,result+1)
			else if (droite and (memory <> 4)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col+1,pos_line,4,result+1)
			else if (gauche and (memory <> 3)) then verifIni := verifIni(grille,tres_col,tres_line,pos_col-1,pos_line,3,result+1)
			else verifIni := verifIni(grille,tres_col,tres_line,pos_col,pos_line+1,1,result-1);
		end; *)
	end;
end;

procedure remplCase(var grille : matrix ; col, line, type_case : integer ; var col_case, line_case : integer);
(* INGOUFF Christian, 11/01/12 *)
var
	valide : boolean;
begin
	repeat
		col_case := random(col);
		line_case := random(line);
		valide := grille[col_case,line_case] = 0;
		if valide then
			grille[col_case,line_case] := type_case
	until valide;
end;

procedure iniGrille(var grille:matrix; col, line : integer);
(* Pré-condition : Reçoit un tableau vide de taille définie (non nulle)
   Post-condition : Renvoie la grille remplie
   INGOUFF Christian, 11/01/12 *)
var
	i, j, nb_coups, nb_murs, tresor_col, tresor_line, enter_col, enter_line : integer;
	tmp1, tmp2 : integer;
begin
	nb_murs := trunc(( 15 / 49 ) * ( col * line ));
	for i := 0 to col-1 do
		for j := 0 to line-1 do
			grille[i,j] := 0;
	remplCase(grille,col,line,42,tresor_col,tresor_line); // Trésor = 42
	remplCase(grille,col,line,-10,enter_col,enter_line); // Porte d'entrée = -10
	for i := 1 to nb_murs do
		begin
			remplCase(grille,col,line,-42,tmp1,tmp2); // Mur = -42
			nb_coups := verifIni(grille,tresor_col,tresor_line,enter_col,enter_line,0,0);
			writeln('nb_coups pour ',i,' = ',nb_coups);
		end;
	writeln('Nombre de coups optimal : ',nb_coups);
end;	

var
	grille : matrix;

begin
	randomize;
	setLength(grille,7,7);
	iniGrille(grille,7,7);
	affichGrille(grille,7,7);
end.
