PROGRAM CHASE;
              { Version 2.01 - 11/03/84 - Mike Watkins }

CONST   MAN        = 'O';                     {SYMBOL FOR THE MAN}
        EDGE       = '|';                     {SYMBOL FOR THE FENCE}
        OBST       = '*';                     {SYMBOL FOR AN OBSTRUCTION}
        ROBOT      = 'R';                     {SYMBOL FOR A ROBOT}
        BLANK      = ' ';                     {AN ASCII BLANK}

        DROB       =   3;                     {STARTING NO OF ROBOTS}
        ROBMAX     =  20;                     {MAX NO OF ROBOTS ALLOWED}
        XMAX       =  39;                     {MAX HORIZONTAL FIELD DIMENSION}
        YMAX       =  14;                     {MAX VERTICAL FIELD DIMENSION}

        TOP        =   2;                     {SPACE ABOVE FIELD}
        SIDE       =   5;                     {SPACE TO LEFT OF FIELD}
        Size       =  80;                     { define your console screen size here }

type
       Line        =  string[Size];           { total line length }

VAR     FIELD      : PACKED ARRAY[0..XMAX,0..YMAX] OF CHAR;
        AGAIN,PLAY : BOOLEAN;
        WIN        : BOOLEAN;
        MI,MJ      : INTEGER;                 {COORDINATES OF THE MAN}
        R          : INTEGER;                 {NUMBER OF ROBOTS LEFT}
        RI,RJ      : ARRAY[1..ROBMAX] OF INTEGER;  {ROBOT COORDINATES}
        RNUM       : REAL;
        DIFF       : INTEGER;                 {DIFFICULTY}
        IDIFF      : 0..10;                   {INITIAL DIFFICULTY}
        GAMENU     : INTEGER;                 {GAME NUMBER}
        M          : CHAR;
        NROB       : INTEGER;                 {NUMBER OF ROBOTS}
        WINS       : INTEGER;                 {NUMBER OF GAMES WON}
        GOODCHAR   : SET OF CHAR;             {GOOD CHARACTERS}
        MOVES      : INTEGER;                 {COUNT OF MOVES}
        CRASH      : INTEGER;                 {NO OF ROBOTS "CRASHED"}
        I          : integer;

FUNCTION RND(LO,HI:INTEGER):INTEGER;          {RANDOM NUMBER GENERATOR}
VAR  Q       :REAL;
     I       :INTEGER;
BEGIN
  REPEAT
    RNUM:=RNUM*21.182813+31.415917;
    RNUM:=RNUM-TRUNC(RNUM);
    I:=TRUNC(RNUM*HI);
  UNTIL I>LO;
  RND:=I;
END;


PROCEDURE DOMOVE(COL,ROW:INTEGER;SYMBOL:CHAR); {DISPLAY SYMBOL AT I,J ON FIELD}
BEGIN
  GOTOXY(COL+1,ROW+1);         {POSITION CURSOR}
  WRITE(SYMBOL)
END;            {END OF DOMOVE PROCEDURE}


{ These next two procedures allow centering of lines based on your console
  screen size }

procedure Center (L:Line); { centers text without a cr & lf }
begin
     for I := 1 to (Size - Length(L)) div 2 do write (' ');
     write(L);
end;

procedure Centerln (L:Line); { centers text with a cr & lf}
begin
     for I := 1 to (Size - Length(L)) div 2 do write (' ');
     writeln(L);
end;


PROCEDURE INSTRUCTIONS;                       {DISPLAY INSTRUCTIONS}
VAR M:CHAR;
BEGIN
  ClrScr;
  Centerln ('WELCOME TO THE WONDERFUL, EXCITING, GAME OF CHASE!');
  writeln;Center ('Would you like instructions (Y/N): ');
  READ(Kbd,M);write(M);
  M:=UPCASE(M);
  IF M='Y' THEN
  BEGIN
    WRITELN;WRITELN;
    Centerln ('HERE ARE SOME INSTRUCTIONS:');writeln;
    Centerln ('You, "O",are in a HIGH VOLTAGE maze.');
    Centerln ('The ROBOT computers, "R", are trying to destroy you.');
    Centerln ('To win, you must destroy the computers.');
    Centerln ('This is done by running them into fence posts, "*",');
    Centerln ('or by running them into each other.');
    Centerln ('The diagram below the maze shows how you can move,');
    Centerln ('the ROBOTS will try to follow you.');
    Centerln ('There are 3 ROBOTS to start for a BEGINNER.');
    Centerln ('The number will increase as you win games !');
    WRITELN;
    Centerln ('GOOD LUCK!!!!!')
  END;
END;                                          {END OF INSTRUCTIONS}


PROCEDURE STARTGAME;
VAR    SK: CHAR;
BEGIN
WRITELN;WRITELN;WRITELN;
  Center('Enter a number followed by RETURN: ');READLN(RNUM);
  IF RNUM=0 THEN RNUM:=12.345;
  WHILE RNUM > 200 DO RNUM:=RNUM-200;
  ClrScr;
  Centerln ('HOW GOOD A PLAYER ARE YOU ?');
  WRITELN;
  Centerln ('Beginner     - B');
  Centerln ('Intermediate - I');
  Centerln ('Expert       - E');
  Centerln ('Old Pro      - P');
  WRITELN;
  Center ('Type in your skill: ');
  READ (Kbd,SK);write (SK);
  SK:=UPCASE(SK);
  WRITELN;
  WHILE NOT (SK IN ['B','I','E','P']) DO
  BEGIN
    writeln;Center ('What was that again please ? ');
    READ (Kbd,SK);write (SK);
    SK:=UPCASE(SK);
    WRITELN
  END;
  CASE SK OF
    'B': IDIFF:=0;
    'I': IDIFF:=1;
    'E': IDIFF:=3;
    'P': IDIFF:=5;
  END;
END;


PROCEDURE INITIALIZE;   {SET UP BLANK FIELD SURROUNDED BY FENCE}
VAR I,J:INTEGER;
BEGIN
  FOR I:=0 TO XMAX DO
  BEGIN
    FOR J:=0 TO YMAX DO
    IF((I=0) OR (I=XMAX) OR (J=0) OR (J=YMAX)) THEN FIELD[I,J]:=EDGE
      ELSE FIELD[I,J]:=BLANK
   END;
END;    {END OF INITIALIZE}


PROCEDURE INNERFIELD;   {SET UP MAN, ROBOTS AND OBSTRUCTIONS}
VAR I,J,L,POSTS:INTEGER;
BEGIN
  MI:=RND(0,XMAX); MJ:=RND(0,YMAX); {LOCATE MAN AT ANY RANDOM POSITION}
  FIELD[MI,MJ]:=MAN;
  R:=NROB;
  FOR L:=1 TO R DO                            {NOW DO R ROBOTS}
  BEGIN
    REPEAT
      I:=RND(0,XMAX);J:=RND(0,YMAX);
    UNTIL FIELD[I,J]=BLANK;
    FIELD[I,J]:=ROBOT;
    RI[L]:=I;
    RJ[L]:=J
  END;
  POSTS:=RND(25,35);                          {NOW SET UP 25 TO 35 POSTS}
  FOR L:=1 TO POSTS DO
  BEGIN
    REPEAT
      IF DIFF>3 THEN
      BEGIN
        I:=RND(0,XMAX);
        J:=RND(0,YMAX)
      END ELSE
      BEGIN
        I:=RND(1,XMAX-1);
        J:=RND(1,YMAX-1)
      END;
    UNTIL FIELD[I,J]=BLANK;
    FIELD[I,J]:=OBST
    END;
END;                                          {END OF INNERFIELD}


PROCEDURE MAP;                                {DISPLAY PLAYING FIELD}
VAR I,J:INTEGER;
BEGIN
  ClrScr;
  WRITELN('GAME  DIFF   ROBOTS    WINS    MOVE':79);
  WRITE(' ':44,GAMENU:3,DIFF:5,R:8,WINS:10,MOVES:8);
  GOTOXY(1,1);
  FOR J:=0 TO YMAX DO
  BEGIN
    FOR I:=0 TO XMAX DO WRITE(FIELD[I,J]);
    WRITELN
  END;
  WRITELN;
  WRITELN('1 2 3      Q = Quit');
  WRITELN('4 X 6      5 = No Move');
  WRITE('7 8 9                  MOVE => ');
END;                                          {END OF MAP}

PROCEDURE MOVE;                               {ENTER YOUR MOVE FROM KEYBOARD}
VAR     M : INTEGER;
        C : CHAR;
      BAD : BOOLEAN;
BEGIN
  BAD:=FALSE;
  REPEAT
    WRITE(' ',CHR(8));
    READ (Kbd,C);write (C);
    C:=UPCASE(C);
    IF NOT (C IN GOODCHAR) THEN
    BEGIN
      GOTOXY(5,22);
      BAD:=TRUE;
      WRITE('Bad move, please try again! ':33,CHR(7))
    END;
  UNTIL (C IN GOODCHAR);
  IF BAD THEN
    BEGIN
      GOTOXY(5,22);
      WRITE(' ':40);
      GOTOXY(11,23);
    END;
  IF C='Q' THEN
    BEGIN
     PLAY:=FALSE;
     WIN:=FALSE
    END;
  M:=ORD(C)-48;
  FIELD[MI,MJ]:=BLANK;
  DOMOVE(MI,MJ,BLANK);
      CASE M OF
  7: BEGIN MI:=MI-1; MJ:=MJ-1 END;
  8: MJ:=MJ-1;
  9: BEGIN MI:=MI+1; MJ:=MJ-1 END;
  4: MI:=MI-1;
  5: ;
  6: MI:=MI+1;
  1: BEGIN MI:=MI-1; MJ:=MJ+1 END;
  2: MJ:=MJ+1;
  3: BEGIN MI:=MI+1; MJ:=MJ+1 END
     END;
  MOVES:=MOVES+1;
  IF FIELD[MI,MJ] = BLANK THEN
    BEGIN
      DOMOVE(MI,MJ,MAN);
      FIELD[MI,MJ]:=MAN
    END ELSE
  BEGIN
    IF FIELD[MI,MJ] = EDGE THEN
    BEGIN
      WIN:=FALSE;
      PLAY:=FALSE;
      WRITELN('OUCH, YOU GOT ELECTROCUTED!')
    END ELSE
    BEGIN
      IF FIELD[MI,MJ] = ROBOT THEN
      WRITELN('THWACK! YOU RAN INTO A ROBOT (TURKEY!)') ELSE
      WRITELN('ZZAP! YOU RAN INTO AN ELECTIFIED POST');
      WIN:=FALSE;
      PLAY:=FALSE
    END;
  END;
END;            {END OF MOVE PROCEDURE}


PROCEDURE ROBOTMOVE;    {COMPUTE MOVE FOR R OR FEWER ROBOTS}
VAR M,L,I,J:INTEGER;
BEGIN
  FOR L:=1 TO NROB DO
  BEGIN
    IF((RI[L]<>0) AND (WIN)) THEN
    BEGIN
      FIELD[RI[L],RJ[L]]:=BLANK;
      DOMOVE(RI[L],RJ[L],BLANK);
      IF MI>RI[L] THEN RI[L]:=RI[L]+1;
      IF MI<RI[L] THEN RI[L]:=RI[L]-1;
      IF MJ>RJ[L] THEN RJ[L]:=RJ[L]+1;
      IF MJ<RJ[L] THEN RJ[L]:=RJ[L]-1;
      I:=RI[L];J:=RJ[L];
      IF FIELD[I,J]=BLANK THEN
      BEGIN
        FIELD[RI[L],RJ[L]]:=ROBOT;
        DOMOVE(I,J,ROBOT)
      END
      ELSE
      BEGIN
        IF ((FIELD[I,J]=OBST) OR (FIELD[I,J]=ROBOT))  THEN
        BEGIN
          GOTOXY(XMAX+13,CRASH+4);
          CRASH:=CRASH+1;
          WRITELN('CRASH!! YOU GOT ONE!!');
          R:=R-1;
          GOTOXY(54,2);             {CHANGE NO OF ROBOTS}
          WRITE(R:8);
          RI[L]:=0;
          IF R=0 THEN
          BEGIN
            GOTOXY(XMAX+17,CRASH+4);
            WRITELN('GOOD WORK!');
            GOTOXY(XMAX+9,CRASH+5);
            WRITELN('YOU HAVE DESTROYED THEM ALL!!');
            WIN:=TRUE;
            PLAY:=FALSE
          END;
        END;
      END;
      IF FIELD[RI[L],RJ[L]]=FIELD[MI,MJ] THEN
      BEGIN
        WRITELN('ZAP! A COMPUTER GOT YOU!');
        WIN:=FALSE;
        PLAY:=FALSE
      END;
    END;
 END;
END;                                         {END OF ROBOTMOVE PROCEDURE}



BEGIN             {START OF MAIN PROGRAM}
  GOODCHAR:=['1'..'9','Q'];
  GAMENU:=1;
  WINS:=0;
  AGAIN:=TRUE;
  PLAY:=TRUE;     {INITIALIZE QUIT}
  INSTRUCTIONS;   {DISPLAY INSTRUCTIONS}
  STARTGAME;      {INPUT STARTING POSITION AND SKILL LEVEL}
  DIFF:=IDIFF;    {INITIAL DIFFICULTY LEVEL}
  NROB:=DROB+DIFF*2;  {INITIAL NUMBER OF ROBOTS}
  WHILE AGAIN DO
  BEGIN
    MOVES:=1;WIN:=TRUE;CRASH:=0;
    INITIALIZE;     {CLEARS FIELD[X,Y]}
    INNERFIELD;     {SETS UP PLAYING FIELD}
    WHILE PLAY DO
    BEGIN
      IF MOVES=1 THEN MAP ELSE
      BEGIN
        GOTOXY(71,2);
        WRITELN(MOVES:8);
        DOMOVE(30,18,BLANK)             {INPUT NEXT MOVE}
      END;
      MOVE;         {LETS YOU MOVE}
      IF(PLAY) THEN ROBOTMOVE     {MOVES THE ROBOTS}
    END;
    GOTOXY(1,22);
    Center ('Would you like to play again? (Y/N) ');
    READ(Kbd,M);write (M);
    M:=UPCASE(M);
    IF M='N' THEN AGAIN:=FALSE ELSE
    BEGIN
      PLAY:=TRUE;
      GAMENU:=GAMENU+1;
      IF WIN THEN
      BEGIN
        WINS:=WINS+1;
        IF WINS>2 THEN DIFF:=IDIFF+1;
        IF WINS>5 THEN DIFF:=IDIFF+2;
        IF WINS>8 THEN DIFF:=IDIFF+3;
        IF WINS>11 THEN DIFF:=IDIFF+4;
        IF WINS>15 THEN DIFF:=IDIFF+6;
        IF WINS>20 THEN DIFF:=IDIFF+8;
        IF WINS>30 THEN DIFF:=IDIFF+12;
        NROB:=DROB+2*DIFF
      END;
    END;
  END;
END.
0 THEN DIFF:=IDIFF+8;
        IF WINS>30 THEN DIFF:=IDIFF+12;
        NROB:=DROB+2*D