Program
       Campo_de_Batalla;

Uses
    crt,dos;

Const
     tope= 7;
     total= 4;
     //color: array [1..5] of integer= (11,10,12,14,8);
     color: array [1..5] of integer= (9,10,4,14,8);
     giro: array [0..3] of char= ('E','S','O','N');
     puntos: array [1..4] of integer= (300,200,100,0);
     instrucciones: set of char = ['A','R','I','D','S'];
     aleatorio: array [0..3] of char = ('A','R','I','D');
     puntos_inicio: array [1..4,1..2] of integer =
                    ((2,tope),(tope,tope-1),(tope-1,1),(1,2));

Type
    datos = record
          programa,nombre: string;
          x,y,favor,contra,direccion,puntos,peleas: integer;
          end;

Var
   h,m,s,hund: word;
   i,{n,}tiempo: integer;
   turno: array [1..4] of integer;
   persona: array [1..total] of datos;
   choque: array [0..tope+1,0..tope+1] of integer;

Procedure Lee_concursantes;
          var s: string;
              i: integer;
              entrada: text;
          begin
          i:= 0;                     
          assign(entrada,'personas.txt'); reset(entrada);
          while (not eof(entrada)) do
                begin
                Inc(i);
                readln(entrada,s);
                persona[i].programa:= copy(s,1,pos(' ',s)-1);
                persona[i].nombre  := copy(s,pos(' ',s)+1,length(s));
                persona[i].puntos  := 0;
                persona[i].peleas  := 0;
                end;
          close(entrada);
          end;

Procedure Inicializacion;
          var i,m,t: integer;
          begin
          //Falta el random
          //turno[1]:= 1; turno[2]:= 2; turno[3]:= 3; turno[4]:= 4;
          m:= total div 4;
          for i:= 1 to 4 do
              begin
              t:= 4*random(m)+i;
              while (persona[t].peleas=3) do
                    t:= 4*random(m)+i;
              turno[i]:= t;
              Inc(persona[t].peleas);
              end;

          fillchar(choque, sizeof(choque), 0);
          for i:= 0 to tope+1 do
              begin
              choque[0,i]:= 255;
              choque[tope+1,i]:= 255;
              choque[i,0]:= 255;
              choque[i,tope+1]:= 255;
              end;

          for i:= 1 to 4 do
              with persona[turno[i]] do
                   begin
                   x:= puntos_inicio[i,1];
                   y:= puntos_inicio[i,2];
                   favor:= 0;
                   contra:= 0;
                   direccion:= i-1;
                   choque[x,y]:= i;
                   end;
          end;

Procedure Pon_cuadro;
          var i: integer;
          begin
          clrscr;
          textcolor(white);
          write(output,char(218));
          for i:= 1 to tope do
              write(output,char(196));
          write(output,char(191));
          for i:= 1 to tope do
              begin
              gotoxy(1,i+1);  write(output,char(179));
              gotoxy(tope+2,i+1); write(output,char(179));
              end;
          gotoxy(1,tope+2);
          write(output,char(192));
          for i:= 1 to tope do
              write(output,char(196));
          write(output,char(217));

          for i:= 1 to 4 do
              begin
              textcolor(color[i]);
              gotoxy (tope+10,2*i+1);
              writeln(output,persona[turno[i]].nombre);
              end;
          textcolor(white);
          gotoxy (tope+30, 1);
          write(output,'Muertos   Coordenadas   Tiempo');

          gotoxy (80,25);
          end;

Procedure Actualiza;
          var i: integer;
          begin
          for i:= 1 to 4 do
              begin
              textcolor(color[i]);
              gotoxy(persona[turno[i]].x+1,tope+2-persona[turno[i]].y);
              case persona[turno[i]].direccion of
                   0: write(output,char(195));
                   1: write(output,char(194));
                   2: write(output,char(180));
                   3: write(output,char(193));
                   end;
              gotoxy(tope+29,2*i+1);
              write(persona[turno[i]].favor:3,persona[turno[i]].contra:3);
              //write(persona[turno[i]].favor-persona[tueno[i].contra);
              gotoxy(tope+43,2*i+1);
              write('(',persona[turno[i]].x,',',persona[turno[i]].y,') ');
              end;
          end;

Function  Min(a: array of integer): integer;
          var i,m: integer;
          begin
          m:= maxint;
          for i:= 0 to 3 do
              if a[i]<m then m:= a[i];
          min:= m;
          end;

Procedure Acomoda (equipo_m: integer);
          var d,i,j,k,m,dmax,nuevo_x,nuevo_y: integer;
              tablero: array [0..tope+1,0..tope+1] of integer;
          begin
          //Dec(persona[equipo_m].muertos);
          Inc(persona[equipo_m].contra);
          for i:= 0 to tope+1 do
              for j:= 0 to tope+1 do
                  tablero[i,j]:= 9;

          for i:= 1 to 4 do
              begin
              if (i=equipo_m) then continue;
              for j:= persona[i].x to tope do
                  tablero[j,persona[i].y]:= 1;
              for j:= persona[i].x downto 1 do
                  tablero[j,persona[i].y]:= 1;
              for j:= persona[i].y to tope do
                  tablero[persona[i].x,j]:= 1;
              for j:= persona[i].y downto 1 do
                  tablero[persona[i].x,j]:= 1;
              end;

          for k:= 1 to 7 do
              for i:= 1 to tope do
                  for j:= 1 to tope do
                      if tablero[i,j]<=k
                         then continue
                         else tablero[i,j]:= min([tablero[i+1,j],tablero[i-1,j],
                                                 tablero[i,j+1],tablero[i,j-1]])+1;

          dmax:= 0; m:= 0; nuevo_x:= 0; nuevo_y:= 0;
          for i:= 1 to tope do
              for j:= 1 to tope do
                  if tablero[i,j] >= m then
                     begin
                     with persona[i] do
                          d:= abs(x-i) + abs(y-j);
                     if d>dmax then
                        begin
                        m:= tablero[i,j];
                        nuevo_x:= i; nuevo_y:= j;
                        end;
                     end;

          with persona[equipo_m] do
               begin
               gotoxy(x+1,tope+2-y); write(' ');
               choque[x,y]:= 0;
               x:= nuevo_x; y:= nuevo_y;
               choque[x,y]:= equipo_m;
               end;
          end;

Procedure mata_tiempo;
          var t: integer;
              h,m,s,hund: word;
          begin
          delay(50);
          GetTime(h,m,s,hund);
          t:= hund + 100*(s + 60*(m + 60*h));
          textcolor(color[5]);
          gotoxy(tope+55,6);
          write((t-tiempo)/100:0:2,' s');
          gotoxy(80,25);
          end;

Procedure Acciones(i: integer;ch: char);
          var j,dx,dy: integer;
          begin
          with persona[turno[i]] do
               begin
               dx:= 0; dy:= 0;
               Case direccion of
                    0: dx:= 1;
                    1: dy:=-1;
                    2: dx:=-1;
                    3: dy:= 1;
                    end;
               Case ch of
                    'A': if (choque[x+dx,y+dy]=0) then
                            begin
                            gotoxy(x+1,tope+2-y); write(' ');
                            choque[x,y]:= 0;
                            Inc(x,dx); Inc(y,dy);
                            choque[x,y]:= i;
                            end;
                    'R': if (choque[x-dx,y-dy]=0) then
                            begin
                            gotoxy(x+1,tope+2-y); write(' ');
                            choque[x,y]:= 0;
                            Dec(x,dx); Dec(y,dy);
                            choque[x,y]:= i;
                            end;
                    'I': direccion:= (4+direccion-1) mod 4;
                    'D': direccion:= (direccion+1) mod 4;
                    'S': for j:= 1 to 5 do
                             begin
                             if (choque[x+j*dx,y+j*dy] = 255) then break;
                             if (choque[x+j*dx,y+j*dy]<> 0) then
                                begin
                                Acomoda(choque[x+j*dx,y+j*dy]);
                                //Inc(muertos);
                                Inc(favor);
                                end;
                             gotoxy(x+j*dx+1,tope+2 -(y+j*dy));
                             if dx<>0 then write ('-')
                                      else write ('|');
                             mata_tiempo;
                             gotoxy(x+j*dx+1,tope+2 -(y+j*dy));
                             write(' ');
                             end;
                    end;
               end;
          actualiza;
          if (ch<>'S') then
             for j:= 1 to 5 do
                 mata_tiempo;
          end;

Procedure Intercambia_datos;
          var s: string;
              i,j,k: integer;
              //programa: file;
              entrada,salida: text;
          begin

          for i:= 1 to 4 do
              begin
              textcolor(white);
              gotoxy (tope+8,2*i+1);
              write(output,'->');

              assign(salida,'datos.txt');
              assign(entrada,'salida.txt');

              rewrite(salida);
              with persona[turno[i]] do
                   writeln(salida,favor -contra,' ',x,' ',y,' ',giro[direccion]);
              for j:= 1 to 4 do
                  begin
                  if (i=j) then continue;
                  with persona[turno[j]] do
                       writeln(salida,favor -contra,' ',x,' ',y,' ',giro[direccion]);
                  end;
              close(salida);

              rewrite(entrada);
              close(entrada);

              //assign(programa,persona[turno[i]].programa);
              swapvectors;
              exec(persona[turno[i]].programa,'');
              swapvectors;
              for j:= 1 to 5 do
                  mata_tiempo;
              //close(programa);

              reset(entrada);
              readln(entrada,s);
              close(entrada);

              k:= 1;
              s:= upcase(s);
              while (k<=length(s)) and not (s[k] in instrucciones) do
                    Inc(k);
              if (s='') or not (s[k] in instrucciones)
                 then begin
                      textcolor(red);
                      gotoxy (tope+8,2*i+1);
                      write(output,'? ');
                      s[k]:= aleatorio[random(4)];
                      textcolor(color[5]);
                      end
                 else begin
                      gotoxy (tope+8,2*i+1);
                      write(output,'  ');
                      end;
              acciones(i,s[k]);
              end;
          end;

Procedure dar_puntos;
          var c,i,j,n,t: integer;
              muertos,orden: array [1..5] of integer;
          begin
          muertos[5]:= -255; orden[5]:= -1;

          textcolor(white);
          gotoxy (tope+30, 1);
          write(output,'Muertos     Puntos      Tiempo');
          for i:= 1 to 4 do
              with persona[turno[i]] do
                   begin
                   gotoxy(tope+29,2*i+1);
                   clreol;
                   textcolor(color[i]);
                   orden[i]:= turno[i];
                   muertos[i]:= favor-contra;
                   writeln(muertos[i]:4);
                   delay(250);
                   end;

          for i:= 1 to 4 do
              for j:= i downto 2 do
                  if (muertos[j]>muertos[j-1]) then
                     begin
                     t:= muertos[j]; muertos[j]:= muertos[j-1]; muertos[j-1]:= t;
                     t:= orden[j]; orden[j]:= orden[j-1]; orden[j-1]:= t;
                     end;

          i:= 1;
          while (i<5) do
                begin
                n:= i; c:= 0;
                while (muertos[n]=muertos[i]) do
                      begin
                      Inc(c,puntos[i]);
                      Inc(i);
                      end;
                for j:= n to i-1 do
                    begin
                    gotoxy(tope+41,2*orden[j]+1);
                    textcolor(color[orden[j]]);
                    t:= c div (i-n);
                    if (muertos[j]<0) then write(t:3,' - ',-1*muertos[j]*10:2)
                                      else write(t:3,' + ',muertos[j]*10:2);
                    Inc(persona[orden[j]].puntos,t +10*muertos[j]);
                    end;
                end;
          readln;
          end;

Procedure Ganadores;
          var g,i,j,n,t: integer;
              orden,puntos: array [1..total] of integer;
              ganador: array [1..4,0..total] of integer;
          begin
          clrscr;
          fillchar(ganador, sizeof(ganador), 0);
          for i:= 1 to total do
              begin
              orden[i]:= i;
              puntos[i]:= persona[i].puntos;
              end;

          for i:= 1 to total do
              for j:= i downto 2 do
                  if (puntos[j]>puntos[j-1]) then
                     begin
                     t:= puntos[j]; puntos[j]:= puntos[j-1]; puntos[j-1]:= t;
                     t:= orden[j]; orden[j]:= orden[j-1]; orden[j-1]:= t;
                     end;

          i:= 1; g:= 1;
          while (i<= total) and (g<5) do
                begin
                n:= i;
                while (puntos[n]=puntos[i]) and (i<=total) do
                      Inc(i);
                for j:= n to i-1 do
                    begin
                    Inc(ganador[g,0]);
                    ganador[g,ganador[g,0]]:= orden[j];
                    end;
                Inc(g)
                end;

          for i:= 4 downto 1 do
              begin
              textcolor(color[i]);
              writeln(i,' lugar: ');
              for j:= 1 to ganador[i,0] do
                  writeln(persona[ganador[i,j]].nombre);
              writeln;
              delay(250);
              end;
          {
          for i:= 1 to total do
              writeln(persona[i].nombre,' ',persona[i].puntos);
          }
          readln;
          end;

Begin
     randomize;
     lee_concursantes;
     for i:= 1 to 3*(total div 4) do
         begin
         inicializacion;
         pon_cuadro;
         GetTime(h,m,s,hund);
         tiempo:= hund + 100*(s + 60*(m + 60*h));
         actualiza;
         While (not keypressed) do
               intercambia_datos;
         dar_puntos;
         readln;
         end;
     Ganadores;
End.

