mission2b.adb

--
-- Nom    :
-- Prenom :
-- Groupe :
--

with EcoRobot ;
with Gada.Text_IO ;

procedure Mission2b is

   package E renames EcoRobot ;
   package Txt renames GAda.Text_IO ;

   -- Renvoie le nombre de voisins du robot.
   function Nb_Voisins(Num : Integer) return Integer is
      Nb : Integer := 0 ;
      X : Integer := E.Abscisse(Num) ;
      Y : Integer := E.Ordonnee(Num) ;
   begin
      -- On teste dans les quatre directions.
      if E.Scan(X-1, Y) = E.Robot then
         Nb := Nb + 1 ;
      end if ;

      if E.Scan(X+1, Y) = E.Robot then
         Nb := Nb + 1 ;
      end if ;

      if E.Scan(X, Y-1) = E.Robot then
         Nb := Nb + 1 ;
      end if ;

      if E.Scan(X, Y+1) = E.Robot then
         Nb := Nb + 1 ;
      end if ;
      return Nb ;
   end Nb_Voisins ;

   -- Renvoie le numéro de robot avec le moins de voisins.
   function Num_Danseur return Integer is
      Nb_Min_Voisins : Integer := Integer'Last ;
      Robot_Elu : Integer ;
   begin
      for Num in 1..E.Nombre_Robots loop
         if (not E.Robot_Content(Num)) and Nb_Voisins(Num) < Nb_Min_Voisins then
            Nb_Min_Voisins := Nb_Voisins(Num) ;
            Robot_Elu := Num ;
         end if ;
      end loop ;
      return Robot_Elu ;
   end Num_Danseur ;

   procedure Test_Num_Danseur is
   begin
      Txt.Put_Line("Le robot ayant le moins de voisins est le robot " &
                   "numéro " & Integer'Image(Num_Danseur) & " car il a " &
                   Integer'Image(Nb_Voisins(Num_Danseur)) & " voisins.") ;
   end Test_Num_Danseur ;


   -- Déplace le robot si possible et indique si le déplacement a été fait.
   --
   -- Recopié directement depuis mission1
   --
   function Safe_Walk(Num : Integer ; Direction : Integer) return Boolean is
      -- Coordonnées du robot
      X : Integer := E.Abscisse(Num) ;
      Y : Integer := E.Ordonnee(Num) ;
      Result : Boolean := False ;
   begin
      -- Nouvelles coordonnées selon la direction voulue.
      if Direction = E.Nord then
         Y := Y - 1 ;
      elsif Direction = E.Sud then
         Y := Y + 1 ;
      elsif Direction = E.Est then
         X := X + 1 ;
      else
         X := X - 1 ;
      end if ;

      if E.Scan(X,Y) /= E.Billets and E.Scan(X,Y) /= E.Dehors then
         E.Step(Num, X, Y) ;
         Result := True ;
      end if ;
      return Result ;
   end Safe_Walk ;

   -- Avance jusqu'à un obstacle et revient au point de départ.
   procedure AllerRetour(Num : Integer ; Direction :Integer) is
      Total : Integer := 0 ;
      Res : Boolean ;
      InvDirection : Integer ;
   begin
      while Safe_Walk(Num, Direction) loop
         Total := Total + 1 ;
      end loop ;

      if Direction = E.Nord then
         InvDirection := E.Sud ;
      elsif Direction = E.Sud then
         InvDirection := E.Nord ;
      elsif Direction = E.Est then
         InvDirection := E.Ouest ;
      else
         InvDirection := E.Est ;
      end if ;

      for Pas in 1 .. Total loop
         Res := Safe_Walk(Num, InvDirection) ;
      end loop ;
   end AllerRetour ;


   -- Effectue la chorégraphie d'un robot
   procedure Choregraphie(Num : Integer) is
      Nb_Bords : constant Integer := 4 ;
   begin
      for Ordre in 1..Nb_Bords loop

         if E.Preferences(Num).Bord_Nord = Ordre then
            AllerRetour(Num, E.Nord) ;
         end if ;
         if E.Preferences(Num).Bord_Sud = Ordre then
            AllerRetour(Num, E.Sud) ;
         end if ;
         if E.Preferences(Num).Bord_Est = Ordre then
            AllerRetour(Num, E.Est) ;
         end if ;
         if E.Preferences(Num).Bord_Ouest = Ordre then
            AllerRetour(Num, E.Ouest) ;
         end if ;

      end loop ;

      -- Chemin vers la cible.
      while Safe_Walk(Num, E.Nord) loop
         null ;
      end loop ;

      while Safe_Walk(Num, E.Est) loop
         null ;
      end loop ;
   end Choregraphie ;

   -- Chaque robot fait sa chorégraphie dans l'ordre.
   procedure Sauver_Tous is
   begin
      for Compteur in 1..E.Nombre_Robots loop
         Txt.Put_Line("Nombre de robots contents = " & Integer'Image(E.Nb_Robots_Contents)) ;
         Choregraphie(Num_Danseur) ;
      end loop ;
   end Sauver_Tous ;

begin

   Sauver_Tous ;

end Mission2b ;