PROGRAM PR_ZMEI;
USES
 B_ZMEI, CRT, Graph;

Label EndGame;

Const SizeX = 15;
      SizeY = 15;

      Def_Rn = 5;
      Def_Hung = 100;
      Go_Stone = 4;

      X_Prg = 135;
      Y_Prg = 10;

      Zmei_Debug = False;
      Way_Debug = False;
      VZmei_Debug = False;


Type TMap = Array[1..SizeX, 1..SizeY]of Byte;

     TWaveMap = RECORD
      Map: Array[1..SizeX, 1..SizeY]of Integer;
      Ex, Ey: Byte;
      N: Integer;
     End;

     TWay = Array[1..SizeX*SizeY]of Byte;

     TPoint = RECORD
      X, Y: Byte;
     End;

     TZmei = RECORD
      L: Word;
      Hung: Word;
      Head: TPoint;
      Telo: Array[1..SizeX*SizeY]of TPoint;
     End;

VAR
 {Описание переменной с параметрами игры}
 ST:PACKED RECORD
     XG,YG:BYTE;{голова  X и Y}
     XR,YR:BYTE;{кролик  X и Y}
     XS,YS:BYTE;{камень  X и Y}
     M:{PACKED ARRAY[1..15,1..15]OF BYTE}TMap;{главный массив}
    END;
 I,J:INTEGER;
 P:POINTER;

 Zmei: TZmei;

 Good_Way, Res_Way: TWay;
 Good_L, Res_L:Byte;
 Max_R: Byte;

 Cur_FWay: TMap;
 Cur_FL: Byte;

 Total_Move: Word;
 Prg: Byte;
 Dx, Dy: ShortInt;

Function IntToStr(N: Integer):String;
Var Res: String;
Begin
 Str(N, Res);
 IntToStr:= Res;
End;

Function StrToInt(N: String):Integer;
Var Res: Integer;
    C: Integer;
Begin
 Val(N, Res, C);
 StrToInt:= Res;
End;


{\/ obrezka konca ydava \/}
Procedure Zmei_Cut(Zmei:TZmei; L:Byte; Var A:TWaveMap);
Begin
If L <= Zmei.L Then
 A.Map[Zmei.Telo[Zmei.L-(L-1)].X, Zmei.Telo[Zmei.L-(L-1)].Y]:= 0;
End;
{/\ obrezka konca ydava /\}


{\/ peremeshenie zmeia v massive \/}
Procedure Zmei_Move(Var Zmei:TZmei; Var A:TMap; Way:TWay; Way_L: Byte; Wx, Wy: Byte);
Var X, Y: Byte;
    I, J: Integer;
    L: Byte;
    Full_Way: Array[1..SizeX*SizeY]of TPoint;
    R, S: Byte;
Begin
L:= Zmei.L;
R:= 0;
S:= 0;
X:= Wx;
Y:= Wy;

FillChar(Full_Way, SizeOf(Full_Way), 0);

Full_Way[1].X:= X;
Full_Way[1].Y:= Y;

For I:=1 To Way_L Do {nahojdenie koordinat pyti}
Begin
 If Way[Way_L-I+1] =1 Then
  Begin Inc(Y); Full_Way[I+1].X:=X;Full_Way[I+1].Y:=Y; If A[X,Y]=2 Then Inc(R); If A[X,Y]=3 Then Inc(S); End;

 If Way[Way_L-I+1] =2 Then
  Begin Dec(X); Full_Way[I+1].X:=X;Full_Way[I+1].Y:=Y; If A[X,Y]=2 Then Inc(R); If A[X,Y]=3 Then Inc(S); End;

 If Way[Way_L-I+1] =3 Then
  Begin Dec(Y); Full_Way[I+1].X:=X;Full_Way[I+1].Y:=Y; If A[X,Y]=2 Then Inc(R); If A[X,Y]=3 Then Inc(S); End;

 If Way[Way_L-I+1] =4 Then
  Begin Inc(X); Full_Way[I+1].X:=X;Full_Way[I+1].Y:=Y; If A[X,Y]=2 Then Inc(R); If A[X,Y]=3 Then Inc(S); End;
End;

Full_Way[Way_L+1].X:= Zmei.Head.X;{v golovy ydava}
Full_Way[Way_L+1].Y:= Zmei.Head.Y;

For J:=1 To L Do {nahojdenie koordinat pyti +ydav}
Begin
 If J >L Then Break;
 Full_Way[Way_L+1+J].X:= Zmei.Telo[J].X;
 Full_Way[Way_L+1+J].Y:= Zmei.Telo[J].Y;
End;

A[Zmei.Head.X, Zmei.Head.Y]:= 0;
For I:=1 To L Do {ydalenie ydava s kartu}
 A[Zmei.Telo[I].X, Zmei.Telo[I].Y]:= 0;

A[Wx, Wy]:= 5;{golova na konec pyti}
Zmei.Head.X:= Wx;
Zmei.Head.Y:= Wy;

Inc(Zmei.L, R+1-S);{odin s`eli}

For I:=2 To Zmei.L+1 Do {otkladuvaem ydava po pyti s y4etom s'edenogo}
Begin
 X:= Full_Way[I].X;
 Y:= Full_Way[I].Y;
 A[X, Y]:= 4;
 Zmei.Telo[I-1].X:= X;
 Zmei.Telo[I-1].Y:= Y;
End;

If VZmei_Debug Then
Begin
 SetColor(7);
 For I:=1 To 13 do
 For J:=1 To 13 do
  OutTextXY((I)*32+12, (J)*32+12,'█');

 SetColor(0);
 OutTextXY((Zmei.Head.X)*32-19, (Zmei.Head.Y)*32-19,'+');

 SetColor(4);
 For I:= 1 To Zmei.L Do
  OutTextXY((Zmei.Telo[I].X)*32-19, (Zmei.Telo[I].Y)*32-19,'+');
End;

End;
{/\ peremeshenie zmeia v massive /\}


{\/ sozdanie kartu voln \/}
Function Create_Wave(Zmei:TZmei; A: TMap; Stone: Integer; Var Wave_A: TWaveMap):Boolean;
Var X, Y: Integer;
    Finded: Boolean;
    N: Integer;
    Xg, Yg: Byte;
    Rx, Ry: Byte;
Begin
FillChar(Wave_A.Map, SizeOf(Wave_A.Map), 0);

Xg:= Zmei.Head.X;
Yg:= Zmei.Head.Y;

For Y:=1 To SizeY Do {создание массива: 0 -пусто; -1 -стенка, удав}
For X:=1 To SizeX Do

 Begin
  If (A[X, Y] =0)Or(A[X, Y] =2) Then
   Wave_A.Map[X, Y]:= 0; {можно ходить}

  If (A[X, Y] =1)Or(A[X, Y] =4)Or(A[X, Y] =5) Then
   Wave_A.Map[X, Y]:= -1; {нельзя ходить}

  If (A[X, Y] =3) Then Wave_A.Map[X, Y]:= Stone;
 End;

Wave_A.Map[Xg, Yg]:= 1;{на голову ходить нельзя}

Finded:= False;{кролик не найден}

For N:= 2 To SizeX*SizeY Do
Begin
 If Dy>0 Then Y:=0
         Else Y:=SizeY;

 Repeat
 Begin
  Y:= Y+ Dy;
  If Dy>0 Then If Y>SizeY Then Break;
  If Dy<0 Then If Y<0 Then Break;

  If Dx>0 Then X:=0
          Else X:=15;
  Repeat
  Begin
   X:= X+ Dx;
   If Dx>0 Then If X>SizeX Then Break;
   If Dx<0 Then If X<0 Then Break;

   If Wave_A.Map[X, Y] = N-1 Then {если предыдущая волна}
    Begin {создание N-ой волны}
{ /\ }If Wave_A.Map[X, Y-1] =0 Then Wave_A.Map[X, Y-1]:= N;{nomer volnu}
      If A[X, Y-1] =2 Then Begin Finded:= True; Dec(Y); End;{кролик найден}
      If Finded Then Break; {выход}

{  > }If Wave_A.Map[X+1, Y] =0 Then Wave_A.Map[X+1, Y]:= N;{nomer volnu}
      If A[X+1, Y] =2 Then Begin Finded:= True; Inc(X); End;{кролик найден}
      If Finded Then Break; {выход}

{ \/ }If Wave_A.Map[X, Y+1] =0 Then Wave_A.Map[X, Y+1]:= N;{nomer volnu}
      If A[X, Y+1] =2 Then Begin Finded:= True; Inc(Y); End;{кролик найден}
      If Finded Then Break; {выход}

{  < }If Wave_A.Map[X-1, Y] =0 Then Wave_A.Map[X-1, Y]:= N;{nomer volnu}
      If A[X-1, Y] =2 Then Begin Finded:= True; Dec(X); End;{кролик найден}
      If Finded Then Break; {выход}

{ !! }{If (Wave_A.Map[X, Y-1] <> N)And(Wave_A.Map[X, Y+1] <> N)And
         (Wave_A.Map[X-1, Y] <> N)And(Wave_A.Map[X+1, Y] <> N) Then Wave_A.Map[X, Y]:= 0;}
    End;
   If Finded Then Break; {выход}
  End;{po X}
  Until X >=SizeX;

 If Finded Then Break; {выход}
 End;{po Y}
 Until Y >=SizeY;

 If Finded Then Break; {выход}

 Zmei_Cut(Zmei, N-1, Wave_A);
End;{volnu}

Wave_A.Map[X, Y]:= N;

Wave_A.Ex:= X;
Wave_A.Ey:= Y;
Wave_A.N:= N;

If N >=SizeX*SizeY Then
 Create_Wave:= False{typik}
Else Create_Wave:= True;
End;
{/\ sozdanie kartu voln /\}


{\/ poisk pyti \/}
Function Find_Way(A: TWaveMap; Var Way: TWay): Integer;
Var X, Y: Byte;
    I, J: Integer;
Begin
If Way_Debug Then
Begin
 SetColor(7);
 For I:=1 To 13 do
 For J:=1 To 13 do
  OutTextXY((I)*32+12, (J)*32+12,'█');
End;

FillChar(Way, SizeX*SizeY, 0);

X:= A.Ex;
Y:= A.Ey;

For I:= A.N-1 DownTo 1 Do {создание массива, где 1 -путь}
Begin
 If A.Map[X, Y-1] =I Then{ /\ }
  Begin
   Y:= Y-1;
   Way[I]:= 3;
  End;

 If A.Map[X+1, Y] =I Then{  > }
  Begin
   X:= X+1;
   Way[I]:= 4;
  End;

 If A.Map[X, Y+1] =I Then{ \/ }
  Begin
   Y:= Y+1;
   Way[I]:= 1;
  End;

 If A.Map[X-1, Y] =I Then{  < }
  Begin
   X:= X-1;
   Way[I]:= 2;
  End;

 If Way_Debug Then
  Begin
   SetColor(0);
   OutTextXY((X)*32-19, (Y)*32-19, '+');
  End;
End;

Find_Way:= A.N -1;
End;
{/\ poisk pyti /\}


{\/ refresh zmeia \/}
Procedure Ref_Zmei(X, Y: Byte);
Var I, J: Integer;
Begin

If ST.M[X, Y] =2 Then{krolik}
 Begin
  Inc(Zmei.L);
  Zmei.Hung:= 0;

  Move(Zmei.Telo[1], Zmei.Telo[2], 2*(Zmei.L-1));

  Zmei.Telo[1].X:= Zmei.Head.X;
  Zmei.Telo[1].Y:= Zmei.Head.Y;
 End Else
 If ST.M[X, Y] =3 Then {ne krolik}
 Begin
  If Zmei.L >0 Then
   Dec(Zmei.L);
  Zmei.Hung:= 0;

  If (Zmei.Head.X <> X)Or(Zmei.Head.Y <> Y) Then
  Begin
   Move(Zmei.Telo[1], Zmei.Telo[2], 2*(Zmei.L));

   Zmei.Telo[1].X:= Zmei.Head.X;
   Zmei.Telo[1].Y:= Zmei.Head.Y;
  End;
 End Else
 Begin
  Inc(Zmei.Hung);
  If (Zmei.Hung >=Def_Hung)And(Zmei.L >0) Then {100 hodov goloden :,( }
   Begin
    Zmei.Hung:= 0;
    Zmei.Telo[Zmei.L].X:= 0;
    Zmei.Telo[Zmei.L].Y:= 0;
    Dec(Zmei.L);
   End;

  If (Zmei.Head.X <> X)Or(Zmei.Head.Y <> Y) Then
  Begin
   Move(Zmei.Telo[1], Zmei.Telo[2], 2*(Zmei.L));

   Zmei.Telo[1].X:= Zmei.Head.X;
   Zmei.Telo[1].Y:= Zmei.Head.Y;
  End;
 End;

Zmei.Head.X:= X;
Zmei.Head.Y:= Y;
End;
{/\ refresh zmeia /\}


{\/ dvijenie na ekrane \/}
Procedure ScrMove(A: TWay; N:Integer);
Var X, Y: Integer;
    I, J: Integer;
Begin
X:= ST.XG;
Y:= ST.YG;

If N >=255 Then Begin Z_RAB(0); Ref_Zmei(X, Y); Inc(Total_Move); End
 Else
For I:=1 To N+1 Do {двигаем удава по пути}
Begin
 If A[I] =1 Then Begin Dec(Y); Ref_Zmei(X, Y); Z_RAB(1); Inc(Total_Move); End Else
 If A[I] =2 Then Begin Inc(X); Ref_Zmei(X, Y); Z_RAB(2); Inc(Total_Move); End Else
 If A[I] =3 Then Begin Inc(Y); Ref_Zmei(X, Y); Z_RAB(3); Inc(Total_Move); End Else
 If A[I] =4 Then Begin Dec(X); Ref_Zmei(X, Y); Z_RAB(4); Inc(Total_Move); End;

 If Total_Move >=1000 Then Exit;
End;

If Zmei_Debug Then
Begin
 SetColor(7);
 For I:=1 To 13 do
 For J:=1 To 13 do
  OutTextXY((I)*32+12, (J)*32+12, '█');

 SetColor(13);
 OutTextXY((Zmei.Head.X)*32-19, (Zmei.Head.Y)*32-19, '+');

 SetColor(12);
 For I:=1 To Zmei.L do
  OutTextXY((Zmei.Telo[I].X)*32-19, (Zmei.Telo[I].Y)*32-19, '+');
End;

End;
{/\ dvijenie na ekrane /\}


{\/ indikator \/}
Procedure Progress_New;
Begin
 Prg:= 0;

 SetColor(15);
 Rectangle(X_Prg, Y_Prg, X_Prg+207, Y_Prg+10);

 SetFillStyle(11, 5);
 FloodFill(X_Prg+1, Y_Prg+1, 15);
End;

Procedure Progress_Tic;
Begin
 Inc(Prg);

 SetColor(13);
 Line(X_Prg+Prg, Y_Prg+1, X_Prg+Prg, Y_Prg+10-1);
 SetColor(15);
End;

Procedure Progress_Clear;
Begin
 Prg:= 0;

 SetFillStyle(11, 5);
 FloodFill(X_Prg+1, Y_Prg+1, 15);
End;
{/\ indikator /\}


{\/ kydaje idti? \/}
Function Step(Z:TZmei; A: TMap; Stone:Integer; Level: Byte):Byte;
Var Wave: TWaveMap;
    Way: TWay;
    L: Byte;
    B: TMap;

    I, Current_Rn: Byte;
    Was: Array[1..Def_Rn]of TPoint;

    Step_Res: Byte;
    CW: Boolean;
    Zmei_B: TZmei;
Begin
Progress_Tic;

Step:= 0;
FillChar(Was, Def_Rn*2, 0);

For Current_Rn:=1 To (Def_Rn-Level+1) Do
Begin
 For I:=1 To (Current_Rn -1) Do {ybiraem s kartu proverennuh krolov}
  A[Was[I].X, Was[I].Y]:= 1;

 CW:= Create_Wave(Z, A, Stone, Wave);
 If (Not CW) Then
  Begin Step:= Level -1; Break; End Else
 If (CW And (Level >=Def_Rn)) Then
  Begin Step:= Level; Break; End;

 L:= Find_Way(Wave, Way);

 For I:=1 To (Current_Rn -1) Do {pokazuvaem na karte proverennuh krolov}
  A[Was[I].X, Was[I].Y]:= 2;

 If Level=1 Then
 Begin
  Move(Way, Cur_FWay, SizeOf(TMap));
  Cur_FL:= L;
 End;

 Was[Current_Rn].X:= Wave.Ex;
 Was[Current_Rn].Y:= Wave.Ey;

 A[Wave.Ex, Wave.Ey]:= 0;

 Move(A, B, SizeOf(A));
 Move(Z, Zmei_B, SizeOf(TZmei));
 Zmei_Move(Zmei_B, B, Way, L, Wave.Ex, Wave.Ey);

 Step_Res:= Step(Zmei_B, B, Stone, Level+1);
 If (Step_Res >= Max_R) Then
  Begin
   If Step_Res > Max_R Then
   Begin
     Max_R:= Step_Res;
{     Step:= Max_R;}

     Move(Cur_FWay, Good_Way, SizeOf(TWay));
     Good_L:= Cur_FL;
   End Else
   If Cur_FL < Good_L then
   Begin
    Max_R:= Step_Res;
{    Step:= Max_R;}

    Move(Cur_FWay, Good_Way, SizeOf(TWay));
    Good_L:= Cur_FL;
   End;
  End;
End;

End;
{/\ kydaje idti? /\}

Procedure ClearAll;
Begin
 Max_R:= 0;
 Good_L:= 255;
 FillChar(Good_Way, SizeOf(Good_Way), 0);
End;


Var CH: Char;
    F: Text;
    Max_WR: Byte;

BEGIN
{RandSeed:= 370;}

 P:=ADDR(ST); {Находим адрес переменной}
 Z_BEGIN(P); {Начать игру!}
 {Начало главного цикла}

 Zmei.Head.X:= ST.XG;
 Zmei.Head.Y:= ST.YG;
 Zmei.L:= 0;
 FillChar(Zmei.Telo, SizeOf(Zmei.Telo), 0);

 Total_Move:= 0;

 FOR I:=1 TO 1000 DO BEGIN
(*****************************************************)
(* А вот тут вам и нужно реализовать свой алгоритм   *)
(* вместо          генератора случайных ходов        *)
      ClearAll;
      Progress_New;
{      If Random(2)=0 Then Dx:=+1
                     Else Dx:=-1;
      If Random(2)=0 Then Dy:=+1
                     Else Dy:=-1;}
       Dx:=1; Dy:=1;

       ST.M[3, 9]:= 1;
       ST.M[7, 2]:= 1;
       ST.M[11, 12]:= 1;
       ST.M[7, 14]:= 1;
       ST.M[14, 11]:= 1;
       ST.M[3, 14]:= 1;
       Step(Zmei, ST.M, -1, 1);
      Max_WR:= Max_R;

      Res_Way:= Good_Way;
      Res_L:= Good_L;

      If Max_R=0 Then
      Begin
       ST.M[3, 9]:= 0;
       ST.M[7, 2]:= 0;
       ST.M[11, 12]:= 0;
       ST.M[7, 14]:= 0;
       ST.M[14, 11]:= 0;
       ST.M[3, 14]:= 0;
       Step(Zmei, ST.M, -1, 1);
       Res_Way:= Good_Way;
       Res_L:= Good_L;
      End;
     {  Dx:=-1; Dy:=-1;
       Step(Zmei, ST.M, -1, 1);

      If Max_R> Max_WR Then
      Begin
       Res_Way:= Good_Way;
       Res_L:= Good_L;
      End Else Begin Max_R:= Max_WR; Dx:=1; Dy:=1; End;}

      If Max_R <=Go_Stone Then
      Begin
        ClearAll;
        Progress_Clear;
        Step(Zmei, ST.M, 0, 1);

        If (Max_R >Go_Stone)Or((Max_R >0)And(Res_L =255)) Then
        Begin
          Res_Way:= Good_Way;
          Res_L:= Good_L;
        End;
      End;

      ScrMove(Res_Way, Res_L);
      For I:=1 To 63 do
       Begin
        Z_RAB(0);
        Inc(Total_Move);
        If Total_Move >= 1000 Then Break;
       End;

      If Total_Move >= 1000 Then GoTo EndGame;
{readkey;}
{      setcolor(0);
      for i:=0 to 14 do
      for j:=0 to 14 do
      begin
       setcolor(15);
       OutTextXY((I)*32+12, (J)*32+12,'█');
       setcolor(0);
       outtextxy(i*32+12, j*32+12,inttostr(st.m[i+1,j+1]));
      end;}

(* Завершение реализации вашего алгоритма            *)
(*****************************************************)
    END;{Конец главного цикла}

 EndGame:
{ Assign(F, 'Res.txt');
 Append(F);
 WriteLn(F, ParamStr(1)+' '+IntToStr(Zmei.L+1));
 Close(F);}

 Z_END; {Закончить игру!}
END.