{ File: labdef2.pas }

{ Definizioni per matrice labirinto,
    con procedure di lettura da file e stampa su video.
  Vettore percorso di attraversamento,
    con procedura di stampa su video
  e procedura di modifica di una matrice labirinto per evidenziarvi un
  percorso dato;

  Le costanti N, M, PASSAGGIO, e EVIDENTE sono definite nel programma che
  include queste definizioni.
}


const
  NP1   = N + 1;
  MP1   = M + 1;
  NCAMM = n*m - 2*m - 2*n + 6;

type
  IndiceRiga    = 0..NP1;
  IndiceColonna = 1..MP1;
  Labirinto     = array [IndiceRiga, IndiceColonna] of char;
  { Per memorizzare l'attraversamento del labirinto, facciamo uso di un
    vettore, dimesionato secondo il massimo numero di passi possibile in un
    labirinto avente solo i muri perimetrali (con almeno due entrate/uscite) e
    senza muri all'interno (nm-2m-2n+6).
                   
    Ciascun elemento del vettore rappresenta un punto del cammino percorso.
    Se il vettore contiene un cammino effettivo, allora esso termina con un
    punto di passaggio avente coordi pari a N o 1 oppure coordj pari a M o 1.
    Gli elementi successivi del cammino verranno ignorati da una eventuale
    stampa. }
  TNcamm = 1..NCAMM;
  Attraversamento = array [TNcamm] of record
                                        coordi : IndiceRiga;
                                        coordj : IndiceColonna;
                                      end;


  procedure LeggiLabirinto (var f   : text;
                            var lab : Labirinto);
  var
    i : IndiceRiga;
    j : IndiceColonna;

  begin { LeggiLabirinto }
    reset(f);
    for i := 1 to N do
    begin
      for j := 1 to M do
        read(f, lab[i, j]);
      readln(f)
    end
  end; { LeggiLabirinto }


  procedure StampaLabirinto (var lab: Labirinto);
  var
    i : IndiceRiga;
    j : IndiceColonna;

  begin { StampaLabirinto }
    writeln;
    writeln('     LABIRINTO');
    for i := 1 to N do
    begin
      for j := 1 to M do
        write(lab[i, j]);
      writeln;
    end
  end; { StampaLabirinto }


  procedure StampaAttraversamento (var att: Attraversamento; q: integer);
  { stampa il percorso:
    il primo passo (entrata) e l'ultimo (uscita) su linee separate;
    q elementi per linea al massimo }
  var
    k           : TNcamm;    { per scandire l'attraversamento }
    cont        : integer;   { per stampare q passi su una linea }
    finecammino : boolean;   { per valutare quando la stampa ha raggiunto
                               l'ultima componente significativa del cammino }

  begin { StampaAttraversamento }
    writeln;
    writeln('  ATTRAVERSAMENTO del LABIRINTO:');
    { stampa del primo passo }
    writeln('(', att[1].coordi : 2, ',', att[1].coordj : 2, ')');

    cont := 0;               { stampato un passo sulla linea }

    k := 2;                  { prossimo passo da stampare: indice 2 }

                             { init della condizione di fine stampa }
    finecammino := (att[k].coordi = 1) or (att[k].coordj = 1) or
                   (att[k].coordi = N) or (att[k].coordj = M);

    repeat
      { stampa q passi su una linea (o quanti ne rimangono) }
      while (cont < q) and not finecammino do
      begin
        write('    (', att[k].coordi : 2, ',', att[k].coordj : 2, ')');
        cont := cont + 1;    { stampato un altro elemento}
        k := k + 1;          { ci si prepara a stampare il successivo
                               se finecammino=TRUE non si dovra`
                               eseguire la prossima iterazione }
        finecammino := (att[k].coordi = 1) or (att[k].coordj = 1) or
                       (att[k].coordi = N) or (att[k].coordj = M)
      end;

      cont := 0;   { il prossimo while stampera' altri n passi... }
      writeln      { ...sulla riga successiva }
    until finecammino;
    { stampa dell'ultimo passo }
    write('(', att[k].coordi : 2, ',', att[k].coordj : 2, ')')
  end; { StampaAttraversamento }


  procedure StampaPercorsoSuLabirinto (lab: Labirinto; att: Attraversamento);
  { Modifica la matrice labirinto passata per valore in modo che i punti del
    percorso att vengano evidenziati con il carattere EVIDENTE.
    Poi la stampa. }
  var
    k : integer;
  begin
    { primo passo }
    lab[att[1].coordi, att[1].coordj] := EVIDENTE;

    { passi successivi }
    k := 1;
    repeat
      k := k + 1;
      lab[att[k].coordi, att[k].coordj] := EVIDENTE
    until (att[k].coordi = 1) or (att[k].coordj = 1) or
          (att[k].coordi = N) or (att[k].coordj = M);

    StampaLabirinto(lab)
  end; { StampaPercorsoSuLabirinto }