PROGRAM
 mondlandung;
USES
 Crt;
CONST
 grenzeX = 25;
 grenzeY = 79;
 bk      = 26;          {bk = Bremskonstante     }
 bv      = 0.08;        {bv = Benz.-verbr.-konst.}
 tkonst  = 1;
 n       = 20;
TYPE
 TRaumschiff = RECORD
    masse    : REAL;
    mr       : REAL;
    mt       : REAL;
    beschl   : REAL;
    geschw   : REAL;
    hoehe    : REAL;
    fgewicht : REAL;
    fbrems   : REAL;
    fges     : REAL;
    bremsen  : REAL;
    ortsf    : REAL;
 END;
 Matrix = ARRAY [1..grenzeX, 1..grenzeY] OF CHAR;

{Anfangswerte setzen}
PROCEDURE Initialisierung (VAR raumsch : TRaumschiff);
 BEGIN
  WITH raumsch DO
   BEGIN
    mr := 1000;
    mt := 500;
    masse := mr + mt;
    ortsf := 1.62;
    hoehe := 100;
    geschw := 0;
    beschl := 0;
   END;
 END;

{Diese Prozedur zeichnet ein}
{Raumschiff aus Zeichen     }
PROCEDURE Raumschiff (matrix : Matrix; posx, posy : INTEGER);
 BEGIN
   TextColor (yellow);
   gotoxy (posx,posy);
   WriteLn ('  /T\  ');
   gotoxy (posx,posy + 1);
   WriteLn ('  ÛÛÛ  ');
   gotoxy (posx,posy + 2);
   WriteLn ('  ÛLÛ  ');
   gotoxy (posx,posy + 3);
   WriteLn ('  ÛUÛ  ');
   gotoxy (posx,posy + 4);
   WriteLn ('  ÛNÛ  ');
   gotoxy (posx,posy + 5);
   WriteLn ('  ÛAÛ  ');
   gotoxy (posx,posy + 6);
   WriteLn (' /ÛÛÛ\ ');
   gotoxy (posx,posy + 7);
   WriteLn (' I   I ');
   gotoxy (posx,posy + 8);
   WriteLn (' I I I ');
   gotoxy (posx,posy + 9);
   WriteLn (' ~~~~~ ');
   gotoxy (posx - 8,posy + 10);
   WriteLn ('(c) by lampacher martin');
  TextColor (7);
 END;

{Mit diesem Anfangsbildschirm wird dem}
{Benutzer das Spielziel erkl„rt und   }
{auch die Steuerung mitgeteilt        }
PROCEDURE Anfangsscreen (matrix : Matrix);
 VAR
  posx, posy : INTEGER;
 BEGIN
  gotoxy (12,2);
   TextColor (red);
   WriteLn ('MONDLANDESPIEL!!!');
  posx := 64;
  posy := 4;
  Raumschiff (matrix, posx, posy);
  gotoxy (1,6);
  WriteLn ('In diesem Spiel mssen Sie versuchen, den Mondlander ');
  WriteLn ('m”glichst heil wieder am Boden ankommen zu lassen.   ');
  WriteLn ('Steuerung : Tasten 1 - 9 (Bremskraft)                ');
  WriteLn ('Tasten nur so oft antippen, wie das RS bremsen soll! ');
  WriteLn ('Wenn die Endgeschwindigkeit  kleiner als 3 ist, haben');
  WriteLn ('Sie gewonnen!                                        ');
  WriteLn ('Bitte TASTE DRšCKEN um anzufangen!                   ');
  ReadKey;
 END;

{Bildschirmausgabe}
PROCEDURE Anzeige (matrix : Matrix; raumsch : TRaumschiff; brems : INTEGER);
 VAR
  x, xy, i, posx, posy : INTEGER;
  h : REAL;
 BEGIN
  {Damit die Höhe auch nicht negativ}
  {ausgegeben werden kann           }
  WITH raumsch DO
   BEGIN
    IF hoehe < 0 THEN
     h := 0
    ELSE
     h := hoehe;
    {Da mehrere Ausgaben noch während dem     }
    {Rechnen stattfinden, soll die Bremskraft }
    {in ihrer endgültigen Kraft gezeigt werden}
    CASE brems OF
     40  : fbrems := 40 * bk;
     80  : fbrems := 80 * bk;
     120 : fbrems := 120 * bk;
     160 : fbrems := 160 * bk;
     200 : fbrems := 200 * bk;
     240 : fbrems := 240 * bk;
     280 : fbrems := 280 * bk;
     320 : fbrems := 320 * bk;
     360 : fbrems := 360 * bk;
    END;

    {Ausgabe der notwendigen Werte, die}
    {zum Landen benötigt werden        }
    gotoxy (30,2);
    TextColor (red);
    WriteLn ('MONDLANDESPIEL!!!');
    TextColor (7);
    gotoxy (4,6);
    WriteLn ('Gesamtmasse        : ', masse:8:2    ,' kg');
    gotoxy (4,7);
    WriteLn ('Beschleunigung     : ', beschl:8:2   ,' m/s?');
    gotoxy (4,8);
    WriteLn ('Gewichtskraft      : ', fgewicht:8:2 ,' N');
    gotoxy (4,9);
    WriteLn ('Bremskraft         : ', fbrems:8:2   ,' N');
    gotoxy (4,11);
    WriteLn ('Tankinhalt         : ', mt:8:2       ,' kg');
    gotoxy (4,12);
    TextColor (green);
    WriteLn ('H”he               : ', h:8:2 ,' m');
    TextColor (7);
    gotoxy (4,13);
    WriteLn ('Geschwindigkeit    : ', geschw:8:2 ,' m/s');

    {Ausgabe eines "Tachos" für die}
    {Anzeige der Geschwindigkeit   }
    x  := ROUND(geschw);              {xy ist die neue Koordinate, die}
    xy := ABS(25 * x) DIV 20 + 4;     {für die Ausgabe verwendet wird }
    FOR i := 4 TO 29 DO
     BEGIN
      gotoxy  (i,14);
      WriteLn (' ');
     END;
    IF (xy > 25) THEN        {Damit die Ausgabe nicht fehlerhaft}
     xy := 25;               {wird, wird ein Maximum gesetzt    }
    FOR i := 4 TO xy DO
     BEGIN
      gotoxy  (i,14);
      WriteLn ('Û');
     END;

    {Löschen der Meldungen und Hinweise,   }
    {die der Benutzer bekommt (siehe unten)}
    FOR i := 4 TO 30 DO
     BEGIN
      gotoxy  (i,18);
      WriteLn (' ');
     END;

    {Falls die Geschwindigkeit zu groß wird,}
    {Dann wird der Benutzer gewarnt         }
    IF geschw < -10 THEN
     BEGIN
      gotoxy (4,18);
      TextColor (Red);
      WriteLn ('ACHTUNG, Absturzgefahr!!');
      TextColor (7);
     END;

    {Falls sich das Raumschiff in einer  }
    {guten Geschwindigkeit befindet,     }
    {erhält der Spieler einen Hinweis    }
    IF (-2 >= geschw) AND (geschw >= -3) THEN
     BEGIN
      gotoxy (4,18);
      TextColor (yellow);
      WriteLn ('Optimale Geschwindigkeit');
      TextColor (7);
     END;

    {Falls das RS steigt und nicht     }
    {fällt, wird der Benutzer ebenfalls}
    {darauf hingewiesen                }
    IF geschw > 0 THEN
     BEGIN
      gotoxy (4,18);
      TextColor (green);
      WriteLn ('Sie steigen');
      TextColor (7);
     END;

    {Elemente zur Höhendarstellung}
    {am rechten Bildschirmrand    }
    x  := TRUNC(h);                     {xy ist die neue Koordinate, die}
    xy := (ABS(100 - x)) DIV 5 + 5;     {für die Ausgabe verwendet wird }

    {Löschen der vorhergehenden X}
    TextColor (6);
    FOR i := 5 TO 25 DO
     BEGIN
      gotoxy(62,i);
      WriteLn (' ');
     END;

    {Zeichnen eines Randes}
    FOR i := 5 TO 25 DO
     BEGIN
      gotoxy  (60,i);
      WriteLn ('I');
     END;
    FOR i := 5 TO 25 DO
     BEGIN
      gotoxy  (64,i);
      WriteLn ('I');
     END;
    gotoxy (60,4);
    WriteLn ('START');
    gotoxy (60,26);
    Write ('ZIEL!');

    {Setzen der Position des Raumschiffes}
    IF h < 100 THEN
     BEGIN                 {Falls das RS höher fliegt}
      gotoxy (62,xy);      {als der Startpunkt war,  }
      Textcolor (green);   {dann wird es nicht mehr  }
      WriteLn ('X');       {dargestellt              }
      Textcolor (7);
     END;

    {Zeichnen eines kleinen RS}
    posx := 40;
    posy := 16;
    Raumschiff (matrix, posx, posy);
  END;
 END;

{Gedrückte Taste wird ausgewertet}
FUNCTION Bremsung : INTEGER;
 VAR
  faktor : INTEGER;
  ch : CHAR;
 BEGIN
  IF KeyPressed THEN        {Eine Bremskraft wird nur    }
   BEGIN                    {eingelesen, falls eine Taste}
    ch := ReadKey;          {gedrückt wird               }
    CASE ch OF
     '1' : faktor := 40;
     '2' : faktor := 80;
     '3' : faktor := 120;
     '4' : faktor := 160;
     '5' : faktor := 200;
     '6' : faktor := 240;
     '7' : faktor := 280;
     '8' : faktor := 320;
     '9' : faktor := 360;
     ELSE
      faktor := 0;
     END;
   END
  ELSE
   faktor := 0;
  Bremsung := faktor;
 END;

{Berechnung der Werte}
PROCEDURE Berechnung (VAR raumsch : TRaumschiff; brems : INTEGER;
                          matrix : Matrix);
 VAR
  i      : INTEGER;
  deltaT : REAL;
 BEGIN
  WITH raumsch DO
   BEGIN
    deltaT := tkonst / n;
    fbrems := 0;                           {Bremskraft wird wieder auf 0}
    FOR i := 1 TO n DO                     {gesetzt, da aufsummiert wird}
     BEGIN
      IF ((i MOD 8) = 0) THEN              {Die Anzeige wird nur}
       Anzeige (matrix, raumsch, brems);   {alle 8x aktualisiert}
      mt := mt - (brems * bv * deltat);
      IF mt > 0 THEN                       {Rechnen mit einen}
       masse := mt + mr                    {DeltaT Modell    }
      ELSE
       BEGIN
        masse := mr;
        mt := 0;
       END;
      fgewicht := masse * ortsf;
      fbrems   := fbrems + brems * bk * deltaT;
      fges     := fbrems - fgewicht;
      beschl   := fges / masse;
      geschw   := geschw + beschl * deltat;
      hoehe    := hoehe + geschw * deltat;
      Delay (n);
     END;
   END;
 END;

{Bewerten der Landung}
FUNCTION Bewertung (VAR answ : CHAR; geschw : REAL) : INTEGER;
 BEGIN
  gotoxy (1,22);
  IF ABS(geschw) > 3 THEN
   WriteLn ('Sie waren zu schnell unterwegs!')
  ELSE
   WriteLn ('Landung erfolgreich!!!');
  WriteLn ('Nochmal? ("n" für BEENDEN)');
  ReadLn (answ);
 END;

{Eigentliches Programm}
VAR
 schiff            : TRaumschiff;
 screen            : Matrix;
 bremsen, ergebnis : INTEGER;
 antwort           : CHAR;

BEGIN                             {TextMode wird verwendet,  }
 TextMode (C80 + Font8x8);        {damit dieses Programm auch}
 ClrScr;                          {auf 15" Bildschirmen läuft}
 Anfangsscreen (screen);
 REPEAT
  ClrScr;
  Initialisierung (schiff);
  {Berechnungen werden nur durchgeführt,}
  {falls das RS in der Luft ist!!!      }
  WHILE schiff.hoehe >= 0 DO
   BEGIN
    Anzeige (screen, schiff, bremsen);
    IF (schiff.mt > 0) THEN      {Falls der Tank leer ist        }
     bremsen := Bremsung         {kann nicht mehr gebremst werden}
    ELSE
     bremsen := 0;
    Berechnung (schiff, bremsen, screen);
  END;
  Anzeige (screen, schiff, bremsen);
  ergebnis := Bewertung (antwort, schiff.geschw);
 UNTIL antwort = 'n';
END.
