program aufgabe26;

type TPerson = record
                 name    : string;
                 vorname : string;
                 alter   : integer
              end;

     PPlatz = ^TPlatz;
     TPlatz = record
                 mensch    : TPerson;
                 naechster : PPlatz
             end;

var stuhl,letzter: PPlatz;

procedure einfuegen(n,v : string; a: integer);
var neu : PPlatz;
begin
   new(neu);
   neu^.mensch.name := n;
   neu^.mensch.vorname := v;
   neu^.mensch.alter := a;
   if (stuhl=nil) then begin
      (* es gibt noch keine Personen in der Liste, dies wird das erste Element *)
      letzter := neu;
      stuhl := neu;
      neu^.naechster := stuhl;
   end
   else begin
      (* es gibt schon mindestens eine Person in der Liste *)
      neu^.naechster := stuhl;
      letzter^.naechster := neu;
      letzter := neu;
   end;
end;

procedure ausgeben();
var m : PPlatz;
begin
   if (stuhl<>nil) then begin
      m := stuhl;
      repeat
         writeln(m^.mensch.name,', ',m^.mensch.vorname,', Alter ',m^.mensch.alter);
         m := m^.naechster;
      until (m=stuhl); (* bis wir wieder am Anfang angekommen sind *)
   end
   else writeln('Es ist niemand mehr da.');
   writeln;
end;

procedure aufraeumen();
var m :  PPlatz;
begin
   if (letzter <> nil) then begin
      while (letzter^.naechster<>letzter) do begin
         m := stuhl^.naechster;
         dispose(stuhl);
         letzter^.naechster := m;
         stuhl := m;
      end;
      (* jetzt gibt es nur noch genau einen Eintrag *)
      dispose(stuhl);
      stuhl := nil;
      letzter := nil;
   end;
end;

(* Musterloesung Teil b *)
procedure einen_weiter();
var temp :  PPlatz;
begin
   if (stuhl <> nil) then begin
      temp := stuhl^.naechster;
      letzter := stuhl;
      stuhl := temp;
   end;
end;

(* Musterloesung Teil c *)
procedure reisenachjerusalem();
var temp : PPlatz;
    i : integer;
begin
   if (stuhl <> nil) then begin
      (* stuhl zeigt nachher auf den Stuhl, der weggenommen wird *)
      (* erstmal laeuft die "Musik" zufaellig lange, d.h. die Leute
       *  setzen sich zufaellig oft einen Platz weiter. *)
      (* willkuerlich: hoechstens 20 Iterationen *)
      for i := 1 to random(20)+1 do einen_weiter();
      (* jetzt wird der Stuhl, auf den stuhl zeigt, weggenommen *)
      (* erstmal wird ausgegeben, wer ausscheidet *)
      writeln(stuhl^.mensch.vorname,' ',stuhl^.mensch.name,' scheidet aus.');
      (* war das die letzte Person? *)
      if (stuhl = letzter) then begin
         dispose(stuhl);
         stuhl := nil;
         letzter := nil;
      end
      else begin
         temp := stuhl;
         stuhl := stuhl^.naechster;
         letzter^.naechster := stuhl;
         dispose(temp);         
      end;
   end;
   writeln('Im Kreis sitzen nun noch:');
   ausgeben();
end; { reisenachjerusalem }

begin
   stuhl := nil;
   letzter := nil;
   einfuegen('Duck','Darkwing',1);
   einfuegen('Darko','Donnie',17);
   einfuegen('Lane','Lois',25);
   einfuegen('Peel','Emma',27);
   einfuegen('Summers','Buffy',22);
   ausgeben();
   (* Zum Testen von Teil b und c verwenden: *) 
   einen_weiter();
   ausgeben();
   while (stuhl <> nil) do reisenachjerusalem();
   (* *)
   aufraeumen(); (* das sollte nach der Reise nach Jerusalem nicht mehr noetig sein *)
end.
