home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / CRYPTO2.ZIP / CRYPTO2.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-09-28  |  18.8 KB  |  661 lines

  1. PROGRAM Crypto;
  2.  
  3. { Helps in the decoding of "cryptograms" }
  4.  
  5. {------------------------------------------------------------}
  6. { This program can be copied freely and modified if desired. }
  7. { Inquiries, improvements, complaints can be addressed to:   }
  8. {                                                            }
  9. {                   Scott R. Houck                           }
  10. {                   200 N. Pickett St. #314                  }
  11. {                   Alexandria, VA  22304                    }
  12. {                                                            }
  13. {                   (703) 823-3469                           }
  14. {                                                            }
  15. { Modified by David A. Peterson -- 28 Sept 85                }
  16. {             124 East Rose Place                            }
  17. {             Little Canada, MN  55117                       }
  18. {                                                            }
  19. {             (612) 482-0099                                 }
  20. {                                                            }
  21. {  Modifications for word matching, cryptogram puzzle file.  }
  22. {                                                            }
  23. {------------------------------------------------------------}
  24.  
  25.   CONST
  26.     F1        = #59;    { Extended ASCII codes for function keys }
  27.     F2        = #60;
  28.     F3        = #61;
  29.     F9        = #67;
  30.     F10       = #68;
  31.     Space     = #32;    { ASCII space }
  32.     BackSpace = #08;
  33.     Bell      = #07;
  34.     Escape    = #27;
  35.     NewLine   = #13;
  36.     LineFeed  = #10;
  37.  
  38.     MaxWordLen = 17;
  39.     MaxLines   =  7;
  40.     {
  41.     | IBM line drawing characters -- double lines
  42.     }
  43.     UpLeft2   = #201;
  44.     UpRight2  = #187;
  45.     LoLeft2   = #200;
  46.     LoRight2  = #188;
  47.     Across2   = #205;
  48.     Down2     = #186;
  49.  
  50.  
  51.   TYPE
  52.     CharSet  = SET OF Char;
  53.     _String  = String [80];
  54.     Word     = String [17];
  55.     Movement = ( Ahead, Behind );
  56.  
  57.   VAR
  58.     Line        : ARRAY [1 .. MaxLines] OF _String;
  59.     UnLine      : ARRAY [1 .. MaxLInes] OF _String;
  60.     Words       : ARRAY [1 .. 100] OF Word;
  61.     Locs        : ARRAY [1 .. 100] OF
  62.       RECORD
  63.         X : Byte;
  64.         Y : Byte
  65.       END;
  66.     Def         : ARRAY [Space .. 'Z'] OF Char;
  67.     Count       : ARRAY [Space .. 'Z'] OF Integer;
  68.     Finished    : Boolean;
  69.     NoMoreCodes : Boolean;
  70.     CurWord     : Byte;
  71.     Letter      : Char;
  72.     NumLines    : Integer;
  73.     CurLine     : Integer;
  74.     CurChar     : Integer;
  75.     NumWords    : Integer;
  76.     WhichOne    : Integer;
  77.     InStr       : _String;
  78.  
  79.   PROCEDURE Beep;
  80.  
  81.     BEGIN { Beep }
  82.       Write (Bell)
  83.     END;  { Beep }
  84.  
  85.   FUNCTION DupChar ( Number     : Byte;
  86.                      ASCIIValue : Char ) : _String;
  87.  
  88.     VAR
  89.       Temp : _String;
  90.  
  91.     BEGIN { DupChar }
  92.       FillChar (Temp[1], Number, ASCIIValue);
  93.       Temp[0] := Chr (Number);
  94.       DupChar := Temp
  95.     END;  { DupChar }
  96.  
  97.   FUNCTION StrNum ( Num : Byte;
  98.                     Pad : Boolean ) : _String;
  99.  
  100.     VAR
  101.       _StrNum : _String;
  102.  
  103.     BEGIN { StrNum }
  104.       Str (Num, _StrNum);
  105.       IF Pad AND (Num < 10) THEN
  106.         _StrNum := '0' + _StrNum;
  107.       StrNum := _StrNum
  108.     END;  { StrNum }
  109.  
  110.   PROCEDURE PlaceStr ( X, Y : Byte;
  111.                        PStr : _String );
  112.  
  113.     BEGIN { PlaceStr }
  114.       GotoXy (X, Y);
  115.       Write (PStr)
  116.     END;  { PlaceStr }
  117.  
  118.   PROCEDURE PlaceCursor;
  119.  
  120.     BEGIN { PlaceCursor }
  121.       WITH Locs [CurWord] DO
  122.         GotoXy (X + 7, Y * 3)
  123.     END;  { PlaceCursor }
  124.  
  125.   PROCEDURE MoveCursor ( Move : Movement );
  126.  
  127.     BEGIN { MoveCursor }
  128.       CASE Move OF
  129.         Behind :
  130.           IF CurWord = 1 THEN
  131.             CurWord := NumWords
  132.           ELSE
  133.             CurWord := CurWord - 1;
  134.         Ahead  :
  135.           IF CurWord = NumWords THEN
  136.             CurWord := 1
  137.           ELSE
  138.             CurWord := CurWord + 1
  139.       END
  140.     END;  { MoveCursor }
  141.  
  142.   PROCEDURE ShowCredits;
  143.  
  144.     BEGIN { ShowCredits }
  145.       TextColor (LightCyan);
  146.       Port[985] := 0;
  147.       ClrScr;
  148.       PlaceStr (31, 7, UpLeft2 + DupChar (15, Across2) + UpRight2);
  149.       PlaceStr (31, 8, Down2);
  150.       TextColor (LightRed);
  151.       Write ('  C R Y P T O  ');
  152.       TextColor (LightCyan);
  153.       WriteLn (Down2);
  154.       PlaceStr (31, 9, LoLeft2 + DupChar (15, Across2) + LoRight2);
  155.       TextColor (LightMagenta);
  156.       PlaceStr (27, 12, 'Written by Scott R. Houck');
  157.       Delay (4000)
  158.     END;  { ShowCredits }
  159.  
  160.   PROCEDURE Initialize;
  161.  
  162.     BEGIN { Initialize }
  163.       ClrScr;
  164.       NormVideo;
  165.       CurWord  := 1;
  166.       WhichOne := 0;
  167.       InStr    := '';
  168.       FillChar (Line, SizeOf (Line), 0);
  169.       FillChar (UnLine, SizeOf (UnLine), 0);
  170.       FOR Letter := Space to 'Z' DO
  171.         BEGIN
  172.           IF Letter < 'A' THEN
  173.             Def[Letter] := Letter
  174.           ELSE
  175.             Def[Letter] := Space;
  176.           Count[Letter] := 0
  177.         END;
  178.       Finished    := False;
  179.       NoMoreCodes := False
  180.     END;  { Initialize }
  181.  
  182.   PROCEDURE GetChar ( VAR Ch       : Char;
  183.                           Legal    : CharSet;
  184.                       VAR Extended : Boolean );
  185.  
  186.     VAR
  187.       Ok : Boolean;
  188.  
  189.     BEGIN { GetChar }
  190.       REPEAT
  191.         Read (Kbd, Ch);
  192.         Ch       := UpCase (Ch);
  193.         Ok       := Ch IN Legal;
  194.         Extended := (Ch = Escape) AND KeyPressed;
  195.         IF Ok THEN
  196.           IF extended THEN
  197.             BEGIN
  198.               Read (Kbd, Ch);
  199.               Ok := Ch IN Legal
  200.             END;
  201.         IF NOT Ok THEN
  202.           Beep
  203.       UNTIL Ok
  204.     END;  { GetChar }
  205.  
  206.   PROCEDURE GetLine ( VAR Buffer : _String );
  207.  
  208.     VAR
  209.       Ch       : Char;
  210.       Done     : Boolean;
  211.       Extended : Boolean;
  212.  
  213.     BEGIN { GetLine }
  214.       Done   := False;
  215.       Buffer := '';
  216.       REPEAT
  217.         GetChar (Ch, [BackSpace, NewLine, Escape, F1, F2, Space .. 'Z'], Extended);
  218.         IF NOT Extended THEN
  219.           CASE Ch OF
  220.             BackSpace  :
  221.               IF Buffer = '' THEN
  222.                 Beep
  223.               ELSE
  224.                 BEGIN
  225.                   Write (BackSpace, Space, BackSpace);
  226.                   Delete (Buffer, Length (Buffer), 1)
  227.                 END;
  228.           NewLine      : Done := True;
  229.           Space .. 'Z' :
  230.             IF Length (Buffer) > 65 THEN
  231.               Beep
  232.             ELSE
  233.               BEGIN
  234.                 Buffer := Buffer + Ch;
  235.                 Write (Ch)
  236.               END
  237.           END
  238.         ELSE IF Extended AND (Ch IN [F1, F2] ) THEN
  239.           BEGIN
  240.             Buffer := Ch;
  241.             Done   := True
  242.           END
  243.         ELSE
  244.           Beep
  245.       UNTIL Done;
  246.       WriteLn
  247.     END;  { GetLine }
  248.  
  249.   PROCEDURE DoSample;
  250.  
  251.     BEGIN { DoSample }
  252.       NumLines := 4;
  253.       Line[1]  := 'SR KWA YSZN OW EW LQKMOWVQPXG, OUSG MQWVQPX HSYY IN P QNPY';
  254.       Line[2]  := 'OSXN-GPDNQ.  NPLU OSXN KWA ENRSTN P YNOONQ, OUN GLQNNT SG';
  255.       Line[3]  := 'AMEPONE.  S UPDN STLYAENE P YNOONQ RQNCANTLK LUPQO PTE P';
  256.       Line[4]  := 'MQSTO WMOSWT OWW.'
  257.     END;  { DoSample }
  258.  
  259.   FUNCTION NumStr ( AStr : _String ) : Integer;
  260.  
  261.     VAR
  262.       Error   : Integer;
  263.       _NumStr : Integer;
  264.  
  265.     BEGIN { NumStr }
  266.       FOR Error := Length (AStr) DOWNTO 1 DO
  267.         IF NOT (AStr[Error] IN ['0' .. '9'] ) THEN
  268.           Delete (AStr, Error, 1);
  269.       Val (AStr, _NumStr, Error);
  270.       IF Error > 0 THEN
  271.         _NumStr := 0;
  272.       NumStr := _NumStr
  273.     END;  { NumStr }
  274.  
  275.   PROCEDURE GetFromCryptFile;
  276.  
  277.     VAR
  278.       Len       : Byte;
  279.       CurOne    : Integer;
  280.       CryptFile : Text;
  281.  
  282.     BEGIN { GetFromCryptFile }
  283.       NumLines := 1;
  284.       Assign (CryptFile, 'A:Crypto.Pzl');
  285.       {$I-}
  286.       Reset (CryptFile);
  287.       {$I+}
  288.       IF IoResult = 0 THEN
  289.         ReadLn (CryptFile, InStr)
  290.       ELSE
  291.         InStr := 'Bad File';
  292.       IF InStr[1] <> '!' THEN
  293.         BEGIN
  294.           WriteLn;
  295.           WriteLn ('Unable to get cryptogram from file. Program stops.');
  296.           Halt
  297.         END
  298.       ELSE
  299.         BEGIN
  300.           CurOne   := NumStr (InStr);
  301.           WhichOne := Random (CurOne - 1) + 1;
  302.           REPEAT
  303.             REPEAT
  304.               ReadLn (CryptFile, InStr)
  305.             UNTIL InStr[1] = '#';
  306.             CurOne := NumStr (InStr)
  307.           UNTIL CurOne = WhichOne;
  308.           ReadLn (CryptFile, InStr); { Letter = Letter }
  309.           Def[InStr[1] ] := InStr[5];
  310.           ReadLn (CryptFile, Line[1] );
  311.           IF Length (Line[1] ) > 65 THEN { Move part of it over to next line }
  312.             BEGIN
  313.               Len := Length (Line[1] );
  314.               WHILE Line[1][len] IN [Space .. 'Z'] - [Space] DO
  315.                 BEGIN
  316.                   Line[2] := Line[1][Len] + Line[2];
  317.                   Delete (Line[1], 1, Len);
  318.                   Len := Len - 1
  319.                 END;
  320.               Delete (Line[1], 1, Len) { Remove space at end of line }
  321.             END
  322.         END
  323.     END;  { GetFromCryptFile }
  324.  
  325.   PROCEDURE EnterCode;
  326.  
  327.     VAR
  328.       Done     : Boolean;
  329.       ThisWord : Byte;
  330.       Len      : Byte;
  331.       AString  : _String;
  332.       AWord    : Word;
  333.  
  334.     BEGIN { EnterCode }
  335.       Done     := False;
  336.       NumLines := 1;
  337.       TextColor (LightCyan);
  338.       PlaceStr (10, 3, 'Enter up to ' + StrNum (MaxLines, False) + ' lines of encoded text.  ');
  339.       WriteLn('Press <ENTER> to quit.');
  340.       PlaceStr (11, 5, 'Press <F1> to do a sample code, <F2> to get from file.');
  341.       GotoXy (1, 7);
  342.       REPEAT
  343.         TextColor (LightRed);
  344.         Write ('Line ', NumLines, ':  ');
  345.         NormVideo;
  346.         GetLine (Line[NumLines] );
  347.         IF (Line[NumLines] = '') OR (Line[NumLines][1] IN [F1, F2] ) OR (NumLines = MaxLines) THEN
  348.           Done := True;
  349.         NumLines := Succ (NumLines)
  350.       UNTIL Done;
  351.       NumLines := Pred (NumLines);
  352.       IF      Line[NumLines] = F1 THEN
  353.         DoSample
  354.       ELSE IF Line[NumLines] = F2 THEN
  355.         GetFromCryptFile;
  356.       FOR CurLine := 1 TO NumLines DO
  357.         BEGIN
  358.           FOR CurChar := 1 TO Length (Line[CurLine] ) DO
  359.             Count[Line[CurLine][CurChar] ] := Succ (Count[Line[CurLine][CurChar] ] );
  360.           FOR CurChar := 1 TO Length (Line[CurLine] ) DO
  361.             UnLine[CurLine] := UnLine[CurLine] + Def[Line[CurLine][CurChar] ]
  362.         END;
  363.       FillChar (Words, SizeOf (Words), 0);
  364.       FillChar (Locs, SizeOf (Locs), 0);
  365.       ThisWord := 0;
  366.       FOR CurLine := 1 TO NumLines DO
  367.         BEGIN
  368.           AString := Line[CurLine];
  369.           WHILE Length (AString) > 0 DO
  370.             BEGIN
  371.               AWord := '';
  372.               Len   := 0;
  373.               WHILE (Length (AString) > 0) AND NOT (AString[1] IN ['A' .. 'Z'] ) DO
  374.                 Delete (AString, 1, 1);
  375.               WHILE (Len < Length (AString) ) AND (AString[Len + 1] IN ['A' .. 'Z'] ) DO
  376.                 BEGIN
  377.                   Len := Len + 1;
  378.                   IF Len <= MaxWordLen THEN
  379.                     AWord := AWord + AString[Len]
  380.                 END;
  381.               IF Len > 0 THEN
  382.                 BEGIN
  383.                   ThisWord := ThisWord + 1;
  384.                   WITH Locs[ThisWord] DO
  385.                     BEGIN
  386.                       X := Length (Line[CurLine] ) - Length (AString) + 1;
  387.                       Y := CurLine
  388.                     END;
  389.                   Delete (AString, 1, Len);
  390.                   WHILE (Length (AString) > 0) AND NOT (AString[1] IN ['A' .. 'Z'] ) DO
  391.                     Delete (AString, 1, 1);
  392.                   Words[ThisWord] := AWord
  393.                 END
  394.             END
  395.         END;
  396.       NumWords := ThisWord
  397.     END;  { EnterCode }
  398.  
  399.   PROCEDURE Display;
  400.  
  401.     BEGIN { Display }
  402.       ClrScr;
  403.       NormVideo;
  404.       FOR CurLine := 1 TO NumLines DO
  405.         PlaceStr (8, 3 * CurLine, Line[CurLine] );
  406.       TextColor (LightCyan);
  407.       IF Length (InStr) > 0 THEN
  408.         BEGIN
  409.           PlaceStr (1, 12, InStr);
  410.           PlaceStr (1, 13, 'Cryptogram ' + StrNum (WhichOne, False) )
  411.         END;
  412.       PlaceStr (11, 24, 'Press <F1> for letter frequency chart   <F3> word matches');
  413.       PlaceStr (11, 25, 'Press <F2> to print   <F9> move left    <F10> move right')
  414.     END;  { Display }
  415.  
  416.   PROCEDURE Update;
  417.  
  418.     BEGIN { Update }
  419.       TextColor (LightCyan);
  420.       FOR CurLine := 1 TO NumLines DO
  421.         BEGIN
  422.           GotoXy (8, 3 * CurLine - 1);
  423.           Write (UnLine[CurLine] )
  424.         END;
  425.       NormVideo
  426.     END;  { Update }
  427.  
  428.   PROCEDURE ShowFreq;
  429.  
  430.     VAR
  431.       Key     : Char;
  432.       Letter1 : Char;
  433.       Letter2 : Char;
  434.       CurChar : Integer;
  435.       Count1  : Integer;
  436.       Count2  : Integer;
  437.  
  438.     BEGIN { ShowFreq }
  439.       ClrScr;
  440.       TextColor (LightGreen);
  441.       PlaceStr (20, 3, UpLeft2 + DupChar(39, Across2) + UpRight2);
  442.       FOR CurChar := 1 TO 20 DO
  443.         BEGIN
  444.           PlaceStr (20, CurChar + 3, Down2);
  445.           PlaceStr (60, CurChar + 3, Down2)
  446.         END;
  447.       PlaceStr (20, 24, LoLeft2 + DupChar(39, Across2) + LoRight2);
  448.       TextColor (LightMagenta);
  449.       PlaceStr (24, 4, 'LETTER  FREQ       LETTER  FREQ');
  450.       NormVideo;
  451.       Letter1 := 'A';
  452.       Letter2 := 'N';
  453.       FOR CurChar := 1 TO 13 DO
  454.         BEGIN
  455.           Count1  := Count[Letter1];
  456.           Count2  := Count[Letter2];
  457.           PlaceStr (27, CurChar + 5, Letter1);
  458.           IF Count1 <> 0 THEN
  459.             Write (Count1:7);
  460.           PlaceStr (46, CurChar + 5, Letter2);
  461.           IF Count2 <> 0 THEN
  462.             Write (Count2:7);
  463.           Letter1 := Succ (Letter1);
  464.           Letter2 := Succ (Letter2)
  465.         END;
  466.       PlaceStr (28, 20, '   Alphabet Frequency');
  467.       PlaceStr (28, 21, 'ETAONRISHDLFCMUGPYWBKXJQZ');
  468.       TextColor (LightRed);
  469.       PlaceStr (28, 23, 'PRESS ANY KEY TO CONTINUE');
  470.       Read (Kbd, Key);
  471.       Display;
  472.       Update
  473.     END;  { ShowFreq }
  474.  
  475.   PROCEDURE PrintWork;
  476.  
  477.     BEGIN { PrintWork }
  478.       IF Length (InStr) > 0 THEN
  479.         BEGIN
  480.           WriteLn (Lst, InStr);
  481.           WriteLn (Lst, 'Cryptogram ' + StrNum (WhichOne, False) );
  482.           Write (Lst,   '=============');
  483.           IF WhichOne > 9 THEN
  484.             WriteLn (Lst, '=')
  485.           ELSE
  486.             WriteLn (Lst)
  487.         END;
  488.       FOR CurLine := 1 TO NumLines DO
  489.         BEGIN
  490.           WriteLn (Lst, UnLine[CurLine]);
  491.           WriteLn (Lst, Line[CurLine] );
  492.           WriteLn (Lst)
  493.         END
  494.     END;  { PrintWork }
  495.  
  496.   PROCEDURE ShowMatch;
  497.  
  498.     CONST
  499.       AChar  : Boolean = False;
  500.       MCount : Integer =     0;
  501.  
  502.     VAR
  503.       AMatch : Boolean;
  504.       Len    : Byte;
  505.       MFile  : Text;
  506.       AWord  : Word;
  507.       MWord  : Word;
  508.  
  509.     BEGIN { ShowMatch }
  510.       AWord := Words[CurWord];
  511.       Len   := Length (AWord);
  512.       FOR CurChar := 1 TO Len DO
  513.         BEGIN
  514.           AWord[CurChar] := Def[AWord[CurChar] ];
  515.           IF AWord[CurChar] IN ['A' .. 'Z'] THEN
  516.             AChar := True
  517.         END;
  518.       IF AChar THEN
  519.         BEGIN
  520.           Assign (MFile, 'A:Words' + StrNum (Len, True) + '.Dct');
  521.           Reset (MFile);
  522.           WHILE NOT Eof (MFile) DO
  523.             BEGIN
  524.               ReadLn (MFile, MWord);
  525.               AMatch  := True;
  526.               CurChar := 0;
  527.               REPEAT
  528.                 CurChar := CurChar + 1;
  529.                 IF (AWord[CurChar] <> Space) AND (AWord[CurChar] <> MWord[CurChar] ) THEN
  530.                   AMatch := False
  531.               UNTIL NOT AMatch OR (CurChar = Len);
  532.               IF AMatch THEN
  533.                 BEGIN
  534.                   WITH Locs[CurWord] DO
  535.                     PlaceStr (X + 7, 3 * Y - 1, MWord);
  536.                   Delay (1000)
  537.                 END
  538.             END;
  539.           Close (MFile)
  540.         END;
  541.       WITH Locs[CurWord] DO
  542.         PlaceStr (X + 7, 3 * Y - 1, AWord)
  543.     END;  { ShowMatch }
  544.  
  545.   PROCEDURE InputDef;
  546.  
  547.     VAR
  548.       Done     : Boolean;
  549.       Unique   : Boolean;
  550.       Extended : Boolean;
  551.       DefCh    : Char;
  552.       Code     : Char;
  553.  
  554.     PROCEDURE GetDefCh;
  555.  
  556.       VAR
  557.         CurChar : Integer;
  558.  
  559.       BEGIN { GetDefCh }
  560.         REPEAT
  561.           TextColor (LightMagenta);
  562.           Done   := False;
  563.           Unique := True;
  564.           PlaceStr (15, 23, 'Type the definition for ' + code + ' (space to blank out):  ');
  565.           ClrEol;
  566.           GetChar (DefCh, [Escape, F1, F2, F9, F10, Space, 'A' .. 'Z'], Extended);
  567.           IF Extended THEN
  568.             CASE DefCh OF
  569.               F1  : ShowFreq;
  570.               F2  : PrintWork;
  571.               F9  : MoveCursor (Behind);
  572.               F10 : MoveCursor (Ahead)
  573.             END
  574.           ELSE
  575.             BEGIN
  576.               Done := True;
  577.               Write (DefCh);
  578.               FOR Letter := 'A' to 'Z' DO
  579.                 IF (Def[Letter] = DefCh) AND (Letter <> Code) AND (DefCh <> Space) THEN
  580.                   BEGIN
  581.                     PlaceStr (15, 23, 'You already defined ' + Letter + ' as ' + DefCh + '.');
  582.                     ClrEol;
  583.                     Beep;
  584.                     Delay(2000);
  585.                     Unique := False
  586.                   END;
  587.               IF Unique THEN
  588.                 BEGIN
  589.                   Def[Code] := DefCh;
  590.                   FOR CurLine := 1 TO NumLines DO
  591.                     FOR CurChar := 1 TO Length (Line[CurLine] ) DO
  592.                       UnLine[CurLine][CurChar] := Def[Line[CurLine][CurChar] ]
  593.                 END
  594.             END
  595.         UNTIL Done AND Unique
  596.       END;  { GetDefCh }
  597.  
  598.     BEGIN { InputDef }
  599.       REPEAT
  600.         Done := False;
  601.         TextColor (LightMagenta);
  602.         PlaceStr (15, 23, 'Type a code letter or press <ENTER> to quit:  ');
  603.         ClrEol;
  604.         PlaceCursor;
  605.         GetChar (Code, [NewLine, Escape, F1, F2, F3, F9, F10, 'A' .. 'Z'], Extended);
  606.         IF      Code = NewLine THEN
  607.           Finished := True
  608.         ELSE IF Extended THEN
  609.           CASE Code OF
  610.             F1  : ShowFreq;
  611.             F2  : PrintWork;
  612.             F3  : ShowMatch;
  613.             F9  : MoveCursor (Behind);
  614.             F10 : MoveCursor (Ahead)
  615.           ELSE
  616.             Done := True
  617.           END
  618.         ELSE
  619.           Done := True
  620.       UNTIL Done OR Finished;
  621.       IF NOT Finished AND NOT (Extended AND (Code IN [F1, F2, F9, F10] ) ) THEN
  622.         GetDefCh
  623.     END;  { InputDef }
  624.  
  625.   PROCEDURE DoAnother;
  626.  
  627.     VAR
  628.       Ans      : Char;
  629.       Extended : Boolean;
  630.  
  631.     BEGIN { DoAnother }
  632.       TextColor (LightMagenta);
  633.       PlaceStr (15, 23, 'Do you want to work on another code? (Y/N)  ');
  634.       ClrEol;
  635.       GetChar (Ans, ['Y', 'N'], Extended);
  636.       NoMoreCodes := ans = 'N'
  637.     END;  { DoAnother }
  638.  
  639.   PROCEDURE WrapItUp;
  640.  
  641.     BEGIN { WrapItUp }
  642.       GotoXy (1, 23); ClrEol;
  643.       GotoXy (1, 24); ClrEol;
  644.       GotoXy (1, 25); ClrEol;
  645.       GotoXy (1, 24)
  646.     END;  { WrapItUp }
  647.  
  648.   BEGIN { Crypto }
  649.     ShowCredits;
  650.     REPEAT
  651.       Initialize;
  652.       EnterCode;
  653.       Display;
  654.       REPEAT
  655.         Update;
  656.         InputDef
  657.       UNTIL Finished;
  658.       DoAnother
  659.     UNTIL NoMoreCodes;
  660.     WrapItUp
  661.   END   { Crypto }.