home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1990 / 07 / praxis / wmaster / wmaster.mod < prev   
Encoding:
Text File  |  1989-12-05  |  29.2 KB  |  941 lines

  1. (* ====================================================== *)
  2. (*                   W O R D M A S T E R                  *)
  3. (*    'Künstlich intelligentes' Wortrate-Spielprogramm    *)
  4. (*           (C) 1989 Matthias Uphoff & TOOLBOX           *)
  5. (* ====================================================== *)
  6. (* Hardware: IBM-kompatibler PC/AT  Monochrom/Farbe       *)
  7. (* Compiler: TopSpeed Modula-2  Version 1.14              *)
  8. (* ====================================================== *)
  9.  
  10. MODULE WMaster;
  11.  
  12. IMPORT SYSTEM, IO, FIO, Lib, Str, Window;
  13.  
  14. TYPE
  15.   WortTyp = ARRAY[0..6] OF CHAR;
  16.   FileNameTyp = ARRAY[0..11] OF CHAR;
  17.   CharSet = SET OF CHAR;
  18.  
  19. CONST
  20.   TxtDelTime = 25;   (* Verzögerung bei Textausgabe       *)
  21.   AnzDelTime = 100;  (* Verzögerung bei Anzeige Wortsuche *)
  22.   MaxAnzahl  = 2000; (* Max. Anzahl Wörter in der Liste   *)
  23.   MaxVersNr  = 15;   (* Max. Anzahl Versuche bis Ende     *)
  24.   BS         = 10C;  (* Backspace *)
  25.   GrossBst   = 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ';
  26.   MaxBst     = 29;   (* Anzahl Buchstaben in GrossBst     *)
  27.   Buchstaben = CharSet{'A'..'Z','Ä','Ö','Ü'};
  28.  
  29.                 (* Fensterdefinitionen für Farbbildschirm *)
  30.   FObenDefC = Window.WinDef
  31.               (0, 0, 79, 2,
  32.                Window.White, Window.Blue,
  33.                FALSE, FALSE, FALSE, TRUE,
  34.                Window.SingleFrame,
  35.                Window.LightGray, Window.Blue);
  36.   FLinksDefC = Window.WinDef
  37.               (0, 3, 20, 21,
  38.                Window.LightGreen, Window.Black,
  39.                FALSE, FALSE, FALSE, TRUE,
  40.                Window.SingleFrame,
  41.                Window.Green, Window.Black);
  42.   FMitteDefC = Window.WinDef
  43.               (21, 3, 58, 21,
  44.                Window.Yellow, Window.Black,
  45.                FALSE, FALSE, FALSE, TRUE,
  46.                Window.SingleFrame,
  47.                Window.LightGray, Window.Black);
  48.   FRechtsDefC = Window.WinDef
  49.               (59, 3, 79, 21,
  50.                Window.LightRed, Window.Black,
  51.                FALSE, FALSE, FALSE, TRUE,
  52.                Window.SingleFrame,
  53.                Window.Red, Window.Black);
  54.   FUntenDefC = Window.WinDef
  55.               (0, 22, 79, 24,
  56.                Window.White, Window.Blue,
  57.                FALSE, FALSE, FALSE, TRUE,
  58.                Window.SingleFrame,
  59.                Window.LightGray, Window.Blue);
  60.   FListeDefC = Window.WinDef
  61.               (36,7,45,17,
  62.                Window.LightGray,Window.Blue,
  63.                FALSE, FALSE, FALSE, TRUE,
  64.                Window.DoubleFrame,
  65.                Window.LightGray, Window.Blue);
  66.  
  67.         (* Fensterdefinitionen für Schwarzweiß-Bildschirm *)
  68.   FObenDefSW = Window.WinDef
  69.               (0, 0, 79, 2,
  70.                Window.White, Window.Black,
  71.                FALSE, FALSE, FALSE, TRUE,
  72.                Window.SingleFrame,
  73.                Window.LightGray, Window.Black);
  74.   FLinksDefSW = Window.WinDef
  75.               (0, 3, 20, 21,
  76.                Window.White, Window.Black,
  77.                FALSE, FALSE, FALSE, TRUE,
  78.                Window.SingleFrame,
  79.                Window.LightGray, Window.Black);
  80.   FMitteDefSW = Window.WinDef
  81.               (21, 3, 58, 21,
  82.                Window.White, Window.Black,
  83.                FALSE, FALSE, FALSE, TRUE,
  84.                Window.SingleFrame,
  85.                Window.LightGray, Window.Black);
  86.   FRechtsDefSW = Window.WinDef
  87.               (59, 3, 79, 21,
  88.                Window.White, Window.Black,
  89.                FALSE, FALSE, FALSE, TRUE,
  90.                Window.SingleFrame,
  91.                Window.LightGray, Window.Black);
  92.   FUntenDefSW = Window.WinDef
  93.               (0, 22, 79, 24,
  94.                Window.White, Window.Black,
  95.                FALSE, FALSE, FALSE, TRUE,
  96.                Window.SingleFrame,
  97.                Window.LightGray, Window.Black);
  98.   FListeDefSW = Window.WinDef
  99.               (36,7,45,17,
  100.                Window.LightGray,Window.Black,
  101.                FALSE, FALSE, FALSE, TRUE,
  102.                Window.DoubleFrame,
  103.                Window.LightGray, Window.Black);
  104.  
  105. VAR
  106.   FensterOben,       (* Fenster-Referenzen *)
  107.   FensterUnten,
  108.   FensterMitte,
  109.   FensterLinks,
  110.   FensterRechts: Window.WinType;
  111.   WortListe:     ARRAY[1..MaxAnzahl] OF WortTyp;
  112.   VersComp:      ARRAY[1..MaxVersNr] OF WortTyp;
  113.   RBComp,
  114.   RPComp:        ARRAY[1..MaxVersNr] OF CARDINAL;
  115.   ListPos,           (* Position in Wortliste *)
  116.   WortLaenge,        (* Länge der Wörter in der Liste  *)
  117.   WortAnzahl,        (* Anzahl der Wörter in der Liste *)
  118.   VersSp,            (* Anzahl Versuche Spieler  *)
  119.   VersC,             (* Anzahl Versuche Computer *)
  120.   ScoreSp,           (* Punktestand Spieler  *)
  121.   ScoreC,            (* Punktestand Computer *)
  122.   Runde:             (* Nummer der akt. Spielrunde *)
  123.                 CARDINAL;
  124.   gelernt,           (* Neues Wort in Liste aufgenommen? *)
  125.   ExtKey,            (* Flag für erweiterten Tastencode  *)
  126.   SW:                (* Schwarz-Weiß-Bildschirm?         *)
  127.                  BOOLEAN;
  128.  
  129.  
  130. (* ====================================================== *)
  131. (* ====================================================== *)
  132. (*                 Allgemeine Prozeduren                  *)
  133. (* ====================================================== *)
  134.  
  135. (* =============================== verzögerte Textausgabe *)
  136.  
  137. PROCEDURE WriteStr(s: ARRAY OF CHAR);
  138.    VAR i: CARDINAL;
  139. BEGIN
  140.    FOR i := 0 TO Str.Length(s)-1 DO
  141.      IO.WrChar(s[i]);
  142.      Lib.Delay(TxtDelTime);
  143.    END;
  144. END WriteStr;
  145.  
  146. (* ================ Textzeile ausgeben mit Zeilenvorschub *)
  147.  
  148. PROCEDURE WriteLn(s: ARRAY OF CHAR);
  149. BEGIN
  150.    WriteStr(s);
  151.    IO.WrLn;
  152. END WriteLn;
  153.  
  154. (* ============== Zahl mit führendem Leerzeichen ausgeben *)
  155.  
  156. PROCEDURE WriteNum(n: CARDINAL);
  157.    VAR St: ARRAY[0..9] OF CHAR;
  158.        f:  BOOLEAN;
  159. BEGIN
  160.   Str.CardToStr(LONGCARD(n),St,10,f);
  161.   Str.Insert(St,' ',0);
  162.   WriteStr(St);
  163. END WriteNum;
  164.  
  165. (* ========== Auf Taste warten, in Großbuchstaben wandeln *)
  166.  
  167. PROCEDURE LeseZeichen(): CHAR;
  168.    VAR c: CHAR;
  169. BEGIN
  170.   ExtKey := FALSE;
  171.   Window.CursorOn;
  172.   c := CAP(IO.RdKey());
  173.   Window.CursorOff;
  174.   CASE c OF
  175.     |  0C: c := IO.RdKey();
  176.            ExtKey := TRUE;
  177.     | 'ä': c := 'Ä';
  178.     | 'ö': c := 'Ö';
  179.     | 'ü': c := 'Ü';
  180.   END;
  181.   RETURN c;
  182. END LeseZeichen;
  183.  
  184. (* =========== Test auf Farbe/Schwarzweiß, Fenster öffnen *)
  185.  
  186. PROCEDURE InitScreen;
  187.    VAR R: SYSTEM.Registers;
  188. BEGIN
  189.   R.AH := 15;
  190.   Lib.Intr(R,10H);
  191.   SW := (R.AL = 0) OR (R.AL = 2) OR
  192.         (R.AL = 5) OR (R.AL = 6) OR (R.AL = 7);
  193.   IF SW THEN
  194.     FensterOben := Window.Open(FObenDefSW);
  195.     FensterLinks := Window.Open(FLinksDefSW);
  196.     FensterMitte := Window.Open(FMitteDefSW);
  197.     FensterRechts := Window.Open(FRechtsDefSW);
  198.     FensterUnten := Window.Open(FUntenDefSW);
  199.   ELSE
  200.     FensterOben := Window.Open(FObenDefC);
  201.     FensterLinks := Window.Open(FLinksDefC);
  202.     FensterMitte := Window.Open(FMitteDefC);
  203.     FensterRechts := Window.Open(FRechtsDefC);
  204.     FensterUnten := Window.Open(FUntenDefC);
  205.   END;
  206. END InitScreen;
  207.  
  208. (* ====================================== Wortliste laden *)
  209.  
  210. PROCEDURE LoadListe;
  211.    VAR InFile: FIO.File;
  212.        FName:  FileNameTyp;
  213. BEGIN
  214.   WortAnzahl := 0;
  215.   FIO.IOcheck := FALSE;
  216.   FName := 'LISTEX.DAT';
  217.   FName[5] := CHR(WortLaenge+48);
  218.   InFile := FIO.Open(FName);
  219.   IF FIO.IOresult() = 0 THEN
  220.     REPEAT
  221.       INC(WortAnzahl);
  222.       FIO.RdStr(InFile,WortListe[WortAnzahl]);
  223.     UNTIL FIO.EOF OR (WortAnzahl = MaxAnzahl);
  224.     DEC(WortAnzahl);
  225.   END;
  226.   FIO.Close(InFile);
  227. END LoadListe;
  228.  
  229. (* ================================== Wortliste speichern *)
  230.  
  231. PROCEDURE SaveListe;
  232.    VAR i:       CARDINAL;
  233.        OutFile: FIO.File;
  234.        FName:   FileNameTyp;
  235. BEGIN
  236.   FIO.IOcheck := FALSE;
  237.   FName := 'LISTEX.DAT';
  238.   FName[5] := CHR(WortLaenge+48);
  239.   OutFile := FIO.Create(FName);
  240.   IF FIO.IOresult() = 0 THEN
  241.     FOR i := 1 TO WortAnzahl DO
  242.       FIO.WrStr(OutFile,WortListe[i]);
  243.       FIO.WrLn(OutFile);
  244.     END;
  245.   END;
  246.   FIO.Close(OutFile);
  247. END SaveListe;
  248.  
  249. (* ===================== Liest Antwort nach Ja/Nein-Frage *)
  250.  
  251. PROCEDURE Ja(): BOOLEAN;
  252.   VAR c: CHAR;
  253. BEGIN
  254.   REPEAT
  255.     c := LeseZeichen();
  256.   UNTIL (c = 'J') OR (c = 'N');
  257.   WriteLn(c);
  258.   RETURN c = 'J';
  259. END Ja;
  260.  
  261. (* ==== Gibt den Index eines vorhandenen bzw. die lexiko- *)
  262. (* ==== graphische Position eines neuen Wortes in der     *)
  263. (* ==== Wortliste zurück.                                 *)
  264.  
  265. PROCEDURE WortPos(Wort: ARRAY OF CHAR): CARDINAL;
  266.    VAR p: CARDINAL;
  267.        i: INTEGER;
  268. BEGIN
  269.   p := 0;
  270.   REPEAT
  271.     INC(p);
  272.     i := Str.Compare(Wort,WortListe[p]);
  273.   UNTIL (p = WortAnzahl) OR (i <= 0);
  274.   IF i > 0 THEN INC(p) END;
  275.   RETURN p;
  276. END WortPos;
  277.  
  278. (* ============= Worteingabe mit eventueller Einblendung  *)
  279. (* ============= der Wortliste organisieren               *)
  280.  
  281. PROCEDURE LeseWort(VAR Wort: WortTyp);
  282.    VAR anz,x: CARDINAL;
  283.          c:   CHAR;
  284.  
  285.   (* =============================== Wortliste einblenden *)
  286.  
  287.   PROCEDURE ZeigeWortListe;
  288.      VAR Fenster,
  289.          FensterUnten,
  290.          AktFenster:  Window.WinType;
  291.          fore, back:  Window.Color;
  292.          c:               CHAR;
  293.          Ende:            BOOLEAN;
  294.  
  295.     (* =============== Akt. Ausschnitt der Liste ausgeben *)
  296.  
  297.     PROCEDURE SchreibeListe;
  298.        VAR i,blanks: CARDINAL;
  299.     BEGIN
  300.       blanks := (8-WortLaenge) DIV 2 + 1;
  301.       Window.TextColor(fore); Window.TextBackground(back);
  302.       FOR i := 1 TO 4 DO
  303.         IF (ListPos+i <= 5) THEN
  304.           Window.GotoXY(1,i); Window.ClrEol
  305.         ELSE
  306.           Window.GotoXY(blanks,i);
  307.           IO.WrStr(WortListe[ListPos+i-5])
  308.         END;
  309.       END;
  310.       FOR i := 6 TO 9 DO
  311.         IF (ListPos+i > WortAnzahl+5) THEN
  312.           Window.GotoXY(1,i); Window.ClrEol
  313.         ELSE
  314.           Window.GotoXY(blanks,i);
  315.           IO.WrStr(WortListe[ListPos+i-5])
  316.         END;
  317.       END;
  318.       Window.TextColor(back); Window.TextBackground(fore);
  319.       Window.GotoXY(1,5); Window.ClrEol;
  320.       Window.GotoXY(blanks,5);
  321.       IO.WrStr(WortListe[ListPos]);
  322.     END SchreibeListe;
  323.  
  324.     (* -------------------------------------------------- *)
  325.  
  326.   BEGIN (* von ZeigeWortListe *)
  327.     AktFenster := Window.Top();
  328.     IF SW THEN
  329.       Fenster := Window.Open(FListeDefSW);
  330.       fore := FListeDefSW.Foreground;
  331.       back := FListeDefSW.Background;
  332.       FensterUnten := Window.Open(FUntenDefSW)
  333.     ELSE
  334.       Fenster := Window.Open(FListeDefC);
  335.       fore := FListeDefC.Foreground;
  336.       back := FListeDefC.Background;
  337.       FensterUnten := Window.Open(FUntenDefC)
  338.     END;
  339.     Window.GotoXY(2,1);
  340.     IO.WrStr('['+31C+']' + '['+30C+'] vor/zurück');
  341.     Window.GotoXY(21,1);
  342.     IO.WrStr('[A]..[Z] Anfangsbuchstabe');
  343.     Window.GotoXY(48,1);
  344.     IO.WrStr('[<┘] übernehmen');
  345.     Window.GotoXY(65,1);
  346.     IO.WrStr('[ESC] Abbruch');
  347.     Window.PutOnTop(Fenster);
  348.     Ende := FALSE;
  349.     REPEAT
  350.       SchreibeListe;                 (* 9 Wörter ausgeben *)
  351.       c := LeseZeichen();
  352.       IF ExtKey THEN                  (* Erweiterter Code *)
  353.         IF (c = CHR(72)) AND (ListPos > 1) THEN
  354.           DEC(ListPos);                    (* Cursor oben *)
  355.         ELSIF (c = CHR(80)) AND (ListPos < WortAnzahl) THEN
  356.           INC(ListPos);                   (* Cursor unten *)
  357.         END
  358.       ELSIF c IN Buchstaben THEN      (* Anfangsbuchstabe *)
  359.         ListPos := WortPos(c);
  360.         IF ListPos > WortAnzahl THEN
  361.           ListPos := WortAnzahl
  362.         END;
  363.       ELSIF c = CHR(13) THEN        (* RETURN, übernehmen *)
  364.         Wort := WortListe[ListPos];
  365.         anz := WortLaenge;
  366.         Ende := TRUE;
  367.       ELSIF c = CHR(27) THEN              (* ESC, Abbruch *)
  368.         Ende := TRUE;
  369.       END;
  370.     UNTIL Ende;
  371.     Window.Close(Fenster);
  372.     Window.Close(FensterUnten);
  373.     Window.PutOnTop(AktFenster);
  374.   END ZeigeWortListe;
  375.  
  376.   (* ---------------------------------------------------- *)
  377.  
  378. BEGIN (* von LeseWort *)
  379.   anz := 0; x := Window.WhereX();
  380.   REPEAT
  381.     c := LeseZeichen();
  382.     IF ExtKey THEN                    (* Erweiterter Code *)
  383.       IF c = CHR(59) THEN                  (* F1 gedrückt *)
  384.          ZeigeWortListe;
  385.          IF anz = WortLaenge THEN
  386.            Window.GotoXY(x,Window.WhereY());
  387.            IO.WrStr(Wort);
  388.          END
  389.       END
  390.     ELSIF c IN Buchstaben THEN               (* Buchstabe *)
  391.       Wort[anz] := c;
  392.       INC(anz);
  393.       IO.WrChar(c)
  394.     ELSIF (c = BS) AND (anz > 0) THEN        (* Backspace *)
  395.       DEC(anz);
  396.       IO.WrChar(c)
  397.     ELSIF c = '?' THEN                    (* Fragezeichen *)
  398.       Wort := '?';
  399.       anz := WortLaenge;
  400.       IO.WrChar('?')
  401.     END;
  402.   UNTIL anz = WortLaenge;
  403.   Wort[anz] := 0C;                      (* Ende markieren *)
  404.   IO.WrLn;
  405. END LeseWort;
  406.  
  407. (* ============= Zählt die Treffer, die der Versuch VWort *)
  408. (* ============= gegenüber GWort erzielt. Gibt in rb die  *)
  409. (* ============= Anzahl der richtigen Buchstaben und in   *)
  410. (* ============= rp die richtigen Positionen zurück       *)
  411.  
  412. PROCEDURE ZaehleTreffer(VWort,GWort: WortTyp;
  413.                         VAR rb,rp: CARDINAL);
  414.   VAR TWort: WortTyp;
  415.       i,p:   CARDINAL;
  416. BEGIN
  417.   TWort := GWort;
  418.   rb := 0; rp := 0;
  419.   FOR i := 0 TO WortLaenge-1 DO
  420.     p := Str.Pos(TWort,VWort[i]);
  421.     IF p < MAX(CARDINAL) THEN
  422.       INC(rb);
  423.       TWort[p] := ' ';
  424.     END;
  425.     IF VWort[i] = GWort[i] THEN
  426.       INC(rp);
  427.     END;
  428.   END;
  429. END ZaehleTreffer;
  430.  
  431. (* ======= Gibt TRUE zurück, wenn ein Wort noch nicht in  *)
  432. (* ======= der Liste vorhanden ist. Fragt nach, ob es neu *)
  433. (* ======= aufgenommen werden soll                        *)
  434.  
  435. PROCEDURE NeuesWort(Wort: WortTyp;
  436.                     VAR aufgenommen: BOOLEAN): BOOLEAN;
  437.    VAR p,i: CARDINAL;
  438. BEGIN
  439.   p := WortPos(Wort);
  440.   IF (p > WortAnzahl) OR
  441.      (Str.Compare(Wort,WortListe[p]) <> 0) THEN
  442.     WriteLn(' Das Wort kenne ich noch nicht.');
  443.     WriteLn(' Soll ich es in meinen Wortschatz');
  444.     WriteStr(' aufnehmen? (J/N): ');
  445.     IF Ja() THEN
  446.       IF WortAnzahl < MaxAnzahl THEN
  447.         FOR i := WortAnzahl TO p BY -1 DO
  448.           WortListe[i+1] := WortListe[i];
  449.         END;
  450.         WortListe[p] := Wort;
  451.         INC(WortAnzahl);
  452.         gelernt := TRUE;
  453.       END;
  454.       aufgenommen := TRUE;
  455.     ELSE
  456.       aufgenommen := FALSE;
  457.     END;
  458.     RETURN TRUE
  459.   ELSE
  460.     RETURN FALSE;
  461.   END;
  462. END NeuesWort;
  463.  
  464. (* ======== Versuch anzeigen und Treffer mit #+ markieren *)
  465.  
  466. PROCEDURE ZeigeTreffer(Nr,rb,rp: CARDINAL;
  467.                        Versuch: WortTyp;
  468.                        Fenster: Window.WinType);
  469. BEGIN
  470.    Window.PutOnTop(Fenster);
  471.    Window.GotoXY(2,Nr+1);
  472.    IO.WrCard(Nr,2); WriteStr('. '); WriteStr(Versuch);
  473.    Window.GotoXY(13,Nr+1);
  474.    IO.WrCharRep('#',rp); IO.WrCharRep('+',rb-rp);
  475.    Window.PutOnTop(FensterMitte);
  476. END ZeigeTreffer;
  477.  
  478.  
  479. (* ====================================================== *)
  480. (* ====================================================== *)
  481. (*             Der Spieler ist an der Reihe               *)
  482. (* ====================================================== *)
  483.  
  484. PROCEDURE FrageWort;
  485.    VAR GeheimWort,
  486.        Versuch:  WortTyp;
  487.        VersNr:   CARDINAL;
  488.        gefunden: BOOLEAN;
  489.  
  490.   (* ============ Eingabe und Überprüfung eines Versuches *)
  491.  
  492.   PROCEDURE NaechsterVersuch;
  493.     VAR i:           CARDINAL;
  494.         gueltig,
  495.         aufgenommen: BOOLEAN;
  496.   BEGIN
  497.     INC(VersNr);
  498.     REPEAT
  499.       gueltig := TRUE;
  500.       WriteStr(' Ihr');
  501.       WriteNum(VersNr); WriteStr('. Versuch: ');
  502.       LeseWort(Versuch);
  503.       IF Versuch[0] = '?' THEN
  504.         FOR i := VersNr TO MaxVersNr DO
  505.             ZeigeTreffer(i,0,0,'?',FensterLinks);
  506.         END;
  507.         VersNr := MaxVersNr
  508.       ELSIF NeuesWort(Versuch,aufgenommen) THEN
  509.         IF aufgenommen THEN
  510.           IO.WrLn;
  511.           WriteLn(' Wieder etwas Neues gelernt...');
  512.           IO.WrLn;
  513.           WriteStr(' Ihr'); WriteNum(VersNr);
  514.           WriteStr('. Versuch: '); WriteLn(Versuch);
  515.         ELSE
  516.           IO.WrLn;
  517.           WriteLn(' Dann ist der Versuch ungültig!');
  518.           WriteLn(' Probieren Sie ein anderes Wort.');
  519.           IO.WrLn;
  520.           gueltig := FALSE;
  521.         END
  522.       END
  523.     UNTIL gueltig;
  524.   END NaechsterVersuch;
  525.  
  526.   (* ================= Auswertung und Anzeige der Treffer *)
  527.  
  528.   PROCEDURE TrefferAnzeige;
  529.     VAR i,rb,rp: CARDINAL;
  530.   BEGIN
  531.     IF VersNr = MaxVersNr THEN
  532.       WriteStr(' Das geheime Wort lautet ');
  533.       WriteLn(GeheimWort);
  534.       WriteStr(' Ihnen werden');
  535.       WriteNum(VersNr); WriteLn(' Versuche');
  536.       WriteLn(' angerechnet.');
  537.       WriteLn(' Etwas mehr Ehrgeiz bitte!');
  538.       IO.WrLn;
  539.       gefunden := TRUE
  540.     ELSE
  541.       ZaehleTreffer(Versuch,GeheimWort,rb,rp);
  542.       WriteStr(' Richtige Buchstaben:'); WriteNum(rb);
  543.       IO.WrLn;
  544.       WriteStr(' Richtige Positionen:'); WriteNum(rp);
  545.       IO.WrLn; IO.WrLn;
  546.       ZeigeTreffer(VersNr,rb,rp,Versuch,FensterLinks);
  547.       IF rp = WortLaenge THEN
  548.         WriteLn(' Das war richtig!');
  549.         WriteStr(' Sie haben');
  550.         WriteNum(VersNr); WriteLn(' Versuche gebraucht.');
  551.         IO.WrLn;
  552.         gefunden := TRUE;
  553.       END;
  554.     END;
  555.   END TrefferAnzeige;
  556.  
  557.   (* ---------------------------------------------------- *)
  558.  
  559. BEGIN  (* FrageWort *)
  560.   Window.PutOnTop(FensterUnten);
  561.   Window.GotoXY(12,1); IO.WrStr('[?]  Lösung verraten');
  562.   Window.GotoXY(42,1); IO.WrStr('[F1]  Wortliste zeigen');
  563.   Window.PutOnTop(FensterMitte);
  564.   IO.WrLn;
  565.   VersNr := 0;
  566.   gefunden := FALSE;
  567.   GeheimWort := WortListe[Lib.RANDOM(WortAnzahl) + 1];
  568.   REPEAT
  569.     NaechsterVersuch;
  570.     TrefferAnzeige;
  571.   UNTIL gefunden;
  572.   VersSp := VersNr;
  573.   Window.PutOnTop(FensterUnten); Window.Clear;
  574.   Window.PutOnTop(FensterMitte);
  575. END FrageWort;
  576.  
  577.  
  578. (* ====================================================== *)
  579. (* ====================================================== *)
  580. (*            Der Computer ist an der Reihe               *)
  581. (* ====================================================== *)
  582.  
  583. PROCEDURE RateWort;
  584.    VAR Versuch: WortTyp;
  585.        WortBeg: CHAR;
  586.        VersNr,
  587.        p:       CARDINAL;
  588.        Ende,
  589.        RundeOK: BOOLEAN;
  590.        AnfBst:  ARRAY[0..MaxBst-1] OF CHAR;
  591.  
  592.   (* ====== Falls das Wort nicht ermittelt werden konnte, *)
  593.   (* ====== wird überprüft, ob es sich um ein unbekanntes *)
  594.   (* ====== Wort handelt oder ein Eingabefehler vorliegt  *)
  595.  
  596.   PROCEDURE NichtGefunden;
  597.     VAR Wort: WortTyp;
  598.         p,i,rb,rp:  CARDINAL;
  599.         aufgenommen: BOOLEAN;
  600.   BEGIN
  601.     Window.PutOnTop(FensterMitte);
  602.     WriteLn(' Ich kann das Wort nicht finden.');
  603.     WriteLn(' Bitte geben Sie das Wort ein: ');
  604.     WriteStr(' ');
  605.     LeseWort(Wort);
  606.     IO.WrLn;
  607.     IF NeuesWort(Wort,aufgenommen) THEN
  608.       IF aufgenommen THEN
  609.         FOR i := VersNr TO MaxVersNr DO
  610.             ZeigeTreffer(i,0,0,'?',FensterRechts);
  611.         END;
  612.         VersNr := MaxVersNr
  613.       ELSE
  614.         IO.WrLn;
  615.         WriteLn(' Dann war es ein ungültiges Wort.');
  616.         RundeOK := FALSE;
  617.       END
  618.     ELSE
  619.       p := 1;
  620.       FOR i := 1 TO VersNr-1 DO
  621.         ZaehleTreffer(VersComp[i],Wort,rb,rp);
  622.         IF (rb <> RBComp[i]) OR (rp <> RPComp[i]) THEN
  623.           p := i; RBComp[i] := rb; RPComp[i] := rp;
  624.         END;
  625.       END;
  626.       WriteLn(' Mogeln hat keinen Zweck:');
  627.       WriteStr(' Die Angaben für den');
  628.       WriteNum(p); WriteLn('. Versuch');
  629.       WriteLn(' waren falsch.');
  630.       WriteLn(' Die korrekte Trefferquote ist:');
  631.       WriteStr(' Richtige Buchstaben:');
  632.       WriteNum(RBComp[p]); IO.WrLn;
  633.       WriteStr(' Richtige Positionen:');
  634.       WriteNum(RPComp[p]); IO.WrLn;
  635.       RundeOK := FALSE;
  636.     END;
  637.     IO.WrLn;
  638.     Ende := TRUE;
  639.   END NichtGefunden;
  640.  
  641.   (* ============== Löscht einen Buchstaben aus der Liste *)
  642.   (* ============== der noch möglichen Anfangsbuchstaben  *)
  643.  
  644.   PROCEDURE LoescheAnfBst(c: CHAR);
  645.   BEGIN
  646.     Str.Delete(AnfBst,Str.Pos(AnfBst,c),1);
  647.   END LoescheAnfBst;
  648.  
  649.   (* ======== Ermittelt neuen Versuch durch Vergleich der *)
  650.   (* ======== Wörter aus der Liste mit allen bisherigen   *)
  651.   (* ======== Versuchen und deren Treffern                *)
  652.  
  653.   PROCEDURE NaechsterVersuch;
  654.      VAR VersOK:  BOOLEAN;
  655.          rb,rp,i: CARDINAL;
  656.   BEGIN
  657.     INC(VersNr);
  658.     Window.PutOnTop(FensterRechts);
  659.     Window.GotoXY(2,VersNr+1);
  660.     IO.WrCard(VersNr,2); IO.WrChar('.');
  661.     REPEAT
  662.       INC(p);                  (* nächstes Wort der Liste *)
  663.       WHILE WortBeg <> WortListe[p,0] DO
  664.         (* Kein Wort mehr mit dem akt. Anfangsbuchstaben *)
  665.         LoescheAnfBst(WortBeg);
  666.         IF Str.Length(AnfBst) = 0 THEN
  667.           (* Kein Anfangsbuchstabe mehr da *)
  668.           Window.GotoXY(6,VersNr+1); WriteStr('?     ');
  669.           NichtGefunden;
  670.           RETURN;
  671.         END;
  672.         (* Neuen Anfangsbuchstaben auswürfeln *)
  673.         WortBeg := AnfBst[Lib.RANDOM(Str.Length(AnfBst))];
  674.         (* Position des 1. Wortes bestimmen *)
  675.         p := WortPos(WortBeg);
  676.         IF p > WortAnzahl THEN p := 1 END;  (* Wrap *)
  677.       END;
  678.       (* Nächsten Kandidaten als Versuch eintragen *)
  679.       VersComp[VersNr] := WortListe[p];
  680.       Window.GotoXY(6,VersNr+1);
  681.       IO.WrStr(VersComp[VersNr]);
  682.       Lib.Delay(AnzDelTime);
  683.       (* Wort gegen alle vorherigen Versuche testen *)
  684.       VersOK := TRUE;
  685.       FOR i := 1 TO VersNr-1 DO
  686.         ZaehleTreffer(VersComp[VersNr],VersComp[i],rb,rp);
  687.         IF (rb <> RBComp[i]) OR (rp <> RPComp[i]) THEN
  688.           VersOK := FALSE
  689.         END;
  690.       END;
  691.     UNTIL VersOK;  (* bis alle Treffer übereinstimmen *)
  692.     Window.PutOnTop(FensterMitte);
  693.   END NaechsterVersuch;
  694.  
  695.   (* == Eingabe der Treffer für den Versuch des Rechners. *)
  696.   (* == Mit Backspace kann zur Eingabe für den vorherigen *)
  697.   (* == Versuch zurückgeblättert werden. In diesem Fall   *)
  698.   (* == wird FALSE zurückgegeben. Bei gültiger Eingabe    *)
  699.   (* == wird in rb die Anzahl der richtigen Buchstaben,   *)
  700.   (* == in rp die richtigen Positionen und als Funktions- *)
  701.   (* == ergebnis TRUE zurückgegeben                       *)
  702.  
  703.   PROCEDURE LeseTreffer(VAR rb,rp: CARDINAL): BOOLEAN;
  704.      VAR c: CHAR;
  705.   BEGIN
  706.     WriteStr(' Richtige Buchstaben: ');
  707.     REPEAT
  708.       REPEAT
  709.         c := LeseZeichen();
  710.         IF (c = BackSpace) AND (VersNr > 1) THEN
  711.           Window.PutOnTop(FensterRechts);
  712.           Window.GotoXY(1,VersNr+1); Window.ClrEol;
  713.           Window.GotoXY(13,VersNr); Window.ClrEol;
  714.           Window.PutOnTop(FensterMitte);
  715.           DEC(VersNr);
  716.           AnfBst := GrossBst;
  717.           p := WortPos(VersComp[VersNr]);
  718.           WortBeg := VersComp[VersNr,0];
  719.           IO.WrLn; IO.WrLn;
  720.           RETURN FALSE   (* Zurück zum vorherigen Versuch *)
  721.         END;
  722.         rb := ORD(c)-48;
  723.       UNTIL rb <= WortLaenge;
  724.       WriteLn(c);
  725.       WriteStr(' Richtige Positionen: ');
  726.       REPEAT
  727.         c := LeseZeichen();
  728.         rp := ORD(c)-48;
  729.       UNTIL (rp <= rb) OR (c = BackSpace);
  730.       IF c = BackSpace THEN  (* Zurück zu richtige Buchst *)
  731.         Window.GotoXY(Window.WhereX()+1,Window.WhereY()-1);
  732.         IO.WrChar(c)
  733.       END;
  734.     UNTIL c <> BackSpace;
  735.     WriteLn(c); IO.WrLn;
  736.     RETURN TRUE;                (* Gültige Treffereingabe *)
  737.   END LeseTreffer;
  738.  
  739.   (* ======== Eingabe, Anzeige und Auswertung der Treffer *)
  740.  
  741.   PROCEDURE TrefferAnzeige;
  742.      VAR i: CARDINAL;
  743.   BEGIN
  744.     IF NOT RundeOK THEN
  745.       (* Eingabefehler oder ungültiges Wort *)
  746.       WriteLn(' Ich beginne von vorne.');
  747.     ELSIF VersNr = MaxVersNr THEN
  748.       (* unbekanntes Wort nicht gefunden *)
  749.       WriteLn(' Das kostet Lehrgeld: ');
  750.       WriteStr(' Mir werden'); WriteNum(MaxVersNr);
  751.       WriteLn(' Versuche angerechnet.');
  752.     ELSE
  753.       (* Treffereingabe *)
  754.       Window.PutOnTop(FensterUnten);
  755.       Window.GotoXY(24,1);
  756.       IO.WrStr('[ <══ ]  Letzte Eingabe löschen');
  757.       Window.PutOnTop(FensterMitte);
  758.       REPEAT
  759.         WriteStr(' Mein');
  760.         WriteNum(VersNr); WriteStr('. Versuch: ');
  761.         WriteLn(VersComp[VersNr]);
  762.       UNTIL LeseTreffer(RBComp[VersNr], RPComp[VersNr]);
  763.       (* Trefferanzeige *)
  764.       Window.PutOnTop(FensterUnten); Window.Clear;
  765.       Window.PutOnTop(FensterMitte);
  766.       ZeigeTreffer(VersNr,RBComp[VersNr],RPComp[VersNr],
  767.                    VersComp[VersNr],FensterRechts);
  768.       (* Auswertung: Richtige Positionen =0, der 1. Buch- *)
  769.       (* stabe des Wortes kommt nicht mehr als Anfangs-   *)
  770.       (* buchstabe in Frage                               *)
  771.       IF RPComp[VersNr] = 0 THEN
  772.         LoescheAnfBst(VersComp[VersNr,0]);
  773.         WortBeg := ' ';
  774.       END;
  775.       (* Auswertung: Richtige Buchstaben =0, kein Buch-   *)
  776.       (* stabe des Wortes kann mehr Anfangsbuchstabe sein *)
  777.       IF RBComp[VersNr] = 0 THEN
  778.         FOR i := 1 TO WortLaenge-1 DO
  779.           LoescheAnfBst(VersComp[VersNr,i]);
  780.         END
  781.       END;
  782.       IF RPComp[VersNr] = WortLaenge THEN     (* Heureka! *)
  783.         WriteLn(" Das war's dann wohl...");
  784.         IO.WrLn;
  785.         Ende := TRUE;
  786.       END;
  787.     END;
  788.   END TrefferAnzeige;
  789.  
  790.   (* ---------------------------------------------------- *)
  791.  
  792. BEGIN  (* von RateWort *)
  793.   REPEAT
  794.     IO.WrLn;
  795.     RundeOK := TRUE;
  796.     WriteLn(' Bitte denken Sie sich ein Wort mit');
  797.     WriteNum(WortLaenge);
  798.     WriteLn(' Buchstaben aus und drücken Sie');
  799.     WriteStr(' dann eine Taste. ');
  800.     WortBeg := LeseZeichen();
  801.     IO.WrLn; IO.WrLn;
  802.     VersNr := 0; p := 0;
  803.     Ende := FALSE;
  804.     AnfBst := GrossBst; WortBeg := ' ';
  805.     Window.PutOnTop(FensterRechts); Window.Clear;
  806.     REPEAT
  807.       NaechsterVersuch;
  808.       TrefferAnzeige;
  809.     UNTIL Ende;
  810.   UNTIL RundeOK;
  811.   VersC := VersNr;     (* Benötigte Versuche registrieren *)
  812. END RateWort;
  813.  
  814.  
  815. (* ====================================================== *)
  816. (* ====================================================== *)
  817. (*              Der organisatorische Rahmen               *)
  818. (* ====================================================== *)
  819.  
  820. PROCEDURE Anleitung;
  821.    VAR c: CHAR;
  822. BEGIN
  823.   Window.PutOnTop(FensterMitte);
  824.   IO.WrStr(' Raten Sie ein Wort, das sich WORD-'); IO.WrLn;
  825.   IO.WrStr(' MASTER  ausgedacht hat - oder las-'); IO.WrLn;
  826.   IO.WrStr(' sen  Sie das Programm Ihr Wort ra-'); IO.WrLn;
  827.   IO.WrStr(' ten!  Gewonnen  hat,  wer  weniger'); IO.WrLn;
  828.   IO.WrStr(' Versuche braucht.');                  IO.WrLn;
  829.   IO.WrStr(' Für jeden Versuch gibt es Treffer:'); IO.WrLn;
  830.   IO.WrStr(' - Die  Anzahl  der richtigen Buch-'); IO.WrLn;
  831.   IO.WrStr('   staben');                           IO.WrLn;
  832.   IO.WrStr(' - Die  Anzahl  der richtigen Posi-'); IO.WrLn;
  833.   IO.WrStr('   tionen  (Buchstaben an der rich-'); IO.WrLn;
  834.   IO.WrStr('   tigen Stelle).');                   IO.WrLn;
  835.   IO.WrStr(' Doppelte  Buchstaben  erzielen nur'); IO.WrLn;
  836.   IO.WrStr(' dann  zwei  Treffer, wenn sie auch'); IO.WrLn;
  837.   IO.WrStr(" im  'Geheimwort' doppelt vorhanden"); IO.WrLn;
  838.   IO.WrStr(' sind.');                     IO.WrLn; IO.WrLn;
  839.   IO.WrStr('    Bitte eine Taste drücken....');
  840.   c := IO.RdKey(); Window.Clear;
  841. END Anleitung;
  842.  
  843.  
  844. PROCEDURE Spielstart;
  845.    VAR c: CHAR;
  846. BEGIN
  847.   REPEAT
  848.     WriteLn(' Geben Sie bitte die gewünschte');
  849.     WriteStr(' Wortlänge ein (3..6): ');
  850.     REPEAT
  851.       c := LeseZeichen();
  852.     UNTIL (c >= '3') AND (c <= '6');
  853.     WriteLn(c);
  854.     WortLaenge := ORD(c) - 48;
  855.     LoadListe;
  856.     IF WortAnzahl = 0 THEN
  857.       WriteLn(' Sorry... Es ist keine Datei mit');
  858.       WriteLn(' dieser Wortlänge vorhanden!');
  859.       IO.WrLn;
  860.     END;
  861.   UNTIL WortAnzahl > 0;
  862.   gelernt := FALSE;
  863.   Runde := 0; ScoreC := 0; ScoreSp := 0;
  864.   ListPos := 1;
  865.   Lib.RANDOMIZE;
  866. END Spielstart;
  867.  
  868.  
  869. PROCEDURE Spielstand;
  870. BEGIN
  871.   WriteLn(' Das Ergebnis dieser Runde: ');
  872.   IF VersC < VersSp THEN
  873.     WriteStr(' Ich habe');
  874.     WriteNum(VersSp-VersC); WriteStr(' Versuch');
  875.     IF VersSp-VersC > 1 THEN WriteStr('e') END;
  876.     WriteLn(' weniger');
  877.     WriteLn(' gebraucht und damit gewonnen.');
  878.     ScoreC := ScoreC + VersSp - VersC;
  879.   ELSIF VersSp < VersC THEN
  880.     WriteStr(' Ich habe');
  881.     WriteNum(VersC-VersSp); WriteStr(' Versuch');
  882.     IF VersC-VersSp > 1 THEN WriteStr('e') END;
  883.     WriteLn(' mehr gebraucht');
  884.     WriteLn(' und damit verloren.');
  885.     ScoreSp := ScoreSp + VersC - VersSp;
  886.   ELSE
  887.     WriteStr(' Wir haben beide');
  888.     WriteNum(VersC); WriteStr(' Versuch');
  889.     IF VersC > 1 THEN WriteStr('e') END;
  890.     IO.WrLn;
  891.     WriteLn(' gebraucht.');
  892.   END;
  893.   IO.WrLn;
  894.   WriteStr(' Der Stand nach der');
  895.   WriteNum(Runde); WriteLn('. Runde:');
  896.   WriteNum(ScoreC); WriteStr(' zu'); WriteNum(ScoreSp);
  897.   IF ScoreC > ScoreSp THEN
  898.     WriteLn(' für mich.')
  899.   ELSIF ScoreC < ScoreSp THEN
  900.     WriteLn(' für Sie.')
  901.   ELSE
  902.     WriteLn(' unentschieden.')
  903.   END;
  904.   IO.WrLn;
  905. END Spielstand;
  906.  
  907.  
  908. BEGIN  (* Main *)
  909.   InitScreen;
  910.   Window.PutOnTop(FensterOben);
  911.   Window.GotoXY(10,1);
  912.   WriteStr('W O R D M A S T E R');
  913.   Window.GotoXY(34,1);
  914.   WriteStr('(C) 1989 Matthias Uphoff & TOOLBOX');
  915.   Anleitung;
  916.   Spielstart;
  917.   REPEAT
  918.     INC(Runde);
  919.     Window.PutOnTop(FensterLinks); Window.Clear;
  920.     Window.PutOnTop(FensterRechts); Window.Clear;
  921.     Window.PutOnTop(FensterMitte); Window.Clear;
  922.     WriteStr(' Okay... auf zur');
  923.     WriteNum(Runde); WriteLn('. Runde.');
  924.     WriteStr(' Möchten Sie anfangen? (J/N): ');
  925.     IF Ja() THEN
  926.       FrageWort;
  927.       WriteLn(' Jetzt bin ich an der Reihe!');
  928.       RateWort
  929.     ELSE
  930.       RateWort;
  931.       WriteLn(' Jetzt sind Sie an der Reihe!');
  932.       FrageWort
  933.     END;
  934.     Spielstand;
  935.     WriteStr(' Noch eine Runde? (J/N): ');
  936.   UNTIL NOT Ja();
  937.   IF gelernt THEN SaveListe END;
  938.   Window.FullScreen := Window.Open(Window.FullScreenDef);
  939.   Window.Clear;
  940. END WMaster.
  941.