File : quest.bush


#!/usr/local/bin/bush

-- Quest
--
-- An old BASIC exploration game.
-- Coverted to BUSH, Ken O. Burtch, 2003
-- WARNING: Conversion not finished!!
--
-- THIS PROGRAM WAS TAKEN FROM THE JULY 1979 BYTE MAG.
-- BY LEE DUSBABEK FOR THE FAMOUS SKIP HANSON (WB6YMH)

pragma ada_95;
pragma restriction( no_external_commands );


procedure quest is

number_of_rooms : constant integer := 42; -- was M9
first_treasure_room : constant integer := 23; -- was T1
second_treasure_room : constant integer := 12; -- was T2

room : array( 1..42 ) of integer; -- was W
move : array( 1..42 ) of string; -- movement table, M
-- since BUSH only has 1-D arrays, the 43 elements will be fields.
move_sep : character := ',';

score : integer; -- was S

current_room  : natural := 5; -- was N
save_current  : natural; -- was N9
next_room     : natural; -- was I
N0            : natural; -- was N0
moves : integer := 0; -- was M0
moves_to_find_treasure : integer := 0; -- was M6
treasure_room : integer := first_treasure_room; -- was T
pirate_room   : integer := 0; -- was P
P1 : integer := 0;
N8 : integer;
debug : boolean := true; -- was D
J : natural;

-- for input

a  : string;
a1 : positive;
a2 : natural;
a0 : positive;

procedure get_input is
-- 5000 REM
-- Return in a1 the user's choice from string a
-- a = string containing list of characters
-- a2 = length of a
   q2 : string;
   q : character; -- Q$
begin
   loop
     --q2 := get_line;
     --if strings.length( q2 ) > 0 then
     --   q := strings.element( q2, 1 );
     --else
     --   q := ' ';
     --end if;
     q := strings.to_upper( inkey );
     put( q );
     put( "-" );
     put( a );
     a2 := strings.index( a, q & "" );
     exit when a2 > 0;
  end loop;
  a1 := positive( a2 ); -- WAS a1 := positive( a2 )+1;
end get_input;

procedure tally_score is
-- 3000 REM
begin
  score := 0;
  if treasure_room = -1 then
     score := score + 5;
  end if;
  if pirate_room = 1 then
     score := score + 10;
  end if;
  for j in 2..number_of_rooms loop
    score := score + room(j);
  end loop;
end tally_score;

procedure show_room is
-- 8000 REM
begin

--8050 I=INT(N/5)
--8060 J=N-5*I+1

--8100 ON I+1 GOTO 8200,8210,8220,8230,8240,8250,8260,8270,8280,8290
--8200 ON J GOTO 9000,9010,9020,9030,9040
--8210 ON J GOTO 9050,9060,9070,9080,9090
--8220 ON J GOTO 9100,9110,9120,9130,9140
--8230 ON J GOTO 9150,9160,9170,9180,9190
--8240 ON J GOTO 9200,9210,9220,9230,9240
--8250 ON J GOTO 9250,9260,9270,9280,9290
--8260 ON J GOTO 9300,9310,9320,9330,9340
--8270 ON J GOTO 9350,9360,9370,9380,9390
--8280 ON J GOTO 9400,9410,9420,9430,9440
--8290 ON J GOTO 9450,9460,9470,9480,9490

case current_room is
when 1 => put_line( "YOU'RE AT A DEAD END!" );
when 2 => put_line( "YOU CAN'T GO IN THAT DIRECTION" );
          new_line;
when 3 => put_line( "A TUNNEL GOES NORTH-SOUTH." );
          put_line( "THERE IS AN OPENING TO THE WEST." );
when 4 => put_line( "YOU'RE ON THE BRINK OF A PIT." );
when 5 => put_line( "YOU'RE OUTSIDE THE CAVE." );
          put_line( "GO SOUTH TO ENTER." );
when 6 => put_line( "YOU'RE AT THE HOME OF THE GNOME-KING." );
          put_line( "FORTUNATELY, HE'S GONE FOR THE DAY." );
when 7 => put_line( "THE GNOME KING IS HERE!" );
          put_line( "YOU'D BETTER GET OUT!" );
          new_line;
when 8 => put_line( "YOU'RE LOST IN THE WOODS." );
--when 9 => null;
when 10 => put_line( "YOU'RE NOT GOING TO GET FAR, DIGGING" );
           put_line( "THROUGH ROCK." );
           new_line;
when 11 => put_line( "YOU'RE AT THE BOTTOM OF A PIT. A LITTLE" );
           put_line( "STREAM FLOWS OVER THE ROCKS HERE." );
when 12 => put_line( "YOU'RE AT A DEAD END!" );
when 13 => put_line( "YOU'RE AT A WIDE SPOT.  THERE IS A SOOTY PATCH" );
           put_line( "WHERE SOMEBODY HAS RESTED A TORCH AGAINST THE WALL." );
           put_line( "THERE ARE JAGGED ROCKS ABOVE YOU." );
when 14 => put_line( "YOU'RE IN A CANYON.  HIGH ON THE WALL ABOVE YOU" );
           put_line( "IS SCRATCHED THE MESSAGE    'BILBO WAS HERE'" );
when 15 => put_line( "YOU'RE NOT A BIRD.  YOU CAN'T FLY!" );
           new_line;
when 16 => put_line( "YOU'RE IN A LOW CHAMBER.  A TIGHT TUNNEL GOES" );
           put_line( "EAST, AND YOU CAN WALK TO THE SOUTH OR WEST." );
           put_line( "THERE IS LIGHT TO THE NORTH." );
when 17 => put_line( "IT'S A TIGHT SQUEEZE.  YOU CAN'T GET PAST" );
           put_line( "WITH THE TREASURE." );
           new_line;
when 18 => put_line( "I DON'T THINK YOU CAN FIND THE CAVE." );
           put_line( "YOU'RE AT THE TOP OF A CLIMB." );
           put_line( "BELOW YOU A MESSAGE SAYS" );
           put_line( "     'BILBO WAS HERE'" );
when 19 => put_line( "YOU'RE AT THE NORTH SIDE OF A CHASM," );
           put_line( "TOO WIDE TO JUMP.  RINGING ECHOES FROM" );
           put_line( "BELOW ARE THE ONLY INDICATION OF DEPTH." );
when 20 => put_line( "YOU'RE IN XANADU.  BELOW YOU ALPH,  THE SACRED" );
           put_line( "RIVER RUNS THROUGH CAVERNS MEASURELESS TO MAN," );
           put_line( "DOWN TO A SUNLESS SEA." );
when 22 => put_line( "YOU'RE ON THE LEDGE ABOVE THE GUILLOTINE ROOM." );
when 23 => put_line( "I HEAR THE GIANT THERE!!!" );
           put_line( "YOU'D BETTER GO BACK!" );
           new_line;
when 24 => put_line( "YOU'RE IN THE GIANT'S CAVERN.  BETTER" );
           put_line( "NOT BE HERE WHEN THE GIANT COMES!" );
when 25 => put_line( "YOU'RE IN THE QUEST RESEARCH AND DEVELOPMENT AREA." );
           new_line;
           put_line( "I'M SORRY BUT VISITORS ARE NOT ALLOWED. YOU'LL HAVE" );
           put_line( "TO LEAVE." );
           new_line;
when 26 => put_line( "YOU'RE IN THE CRYSTAL PALACE.  THE WALLS RESONATE" );
           put_line( "WTH AWESOME MUSIC." );
when 27 => put_line( "YOU'RE AT THE TOP OF A GIANT STALACTITE." );
           put_line( "YOU COULD SLIDE DOWN, BUT YOU COULDN'T" );
           put_line( "CLIMB BACK UP." );
when 28 => put_line( "YOU'RE IN A LITTLE GROTTO.  THERE IS A" );
           put_line( "BOOK HERE CALLED JANE'S FIGHTING SHIPS," );
           put_line( "DATED 1763." );
when 29 => put_line( "YOU'RE IN THE GUILLOTINE ROOM.  A SHARP" );
           put_line( "ROCK BALANCES PRECARIOUSLY ON THE" );
           put_line( "LEDGE ABOVE YOU." );
when 30 => put_line( "YOU'RE IN A CHUTE, SCRAMBLING DOWN THE" );
           put_line( "ROCKS!  NO WAY TO STOP!!!    HANG ON!" );
           new_line;
when 31 => put_line( "THE TIGHT TUNNEL TURNS A CORNER." );
when 32 => put_line( "YOU'RE IN A LITTLE TWISTY MAZE" );
when 33 => put_line( "YOU'RE IN A LITTLE TWISTING MAZE." );
when 34 => put_line( "YOU'RE IN A TWISTING LITTLE MAZE." );
when 35 => put_line( "YOU'RE IN A TWISTY LITTLE MAZE." );
when 36 => put_line( "YOU'RE IN A PREHISTORIC DWELLING.  ON" );
           put_line( "THE WALL ARE DRAWINGS OF BISON DONE IN" );
           put_line( "RED CLAY.  THE FLOOR IS STREWN WITH" );
           put_line( "BONES, THE REMAINS OF ANCIENT RITUALS." );
           put_line( "A SMALL TUNNEL GOES THROUGH THE FLOOR." );
when 37 => put_line( "YOU'RE IN A BLACK HOLE.  THE" );
           put_line( "FORCE OF GRAVITY IS OVERWHELMING." );
when 38 => put_line( "YOU'RE IN THE LABYRINTHE." );
when 39 => put_line( "YOU'RE IN THE LABYRINTHE." );
           put_line( "IT'S VERY DARK IN HERE." );
when 40 => put_line( "YOU'RE IN THE ASHRAM.  INCENSE IS HEAVY" );
           put_line( "IN THE AIR, AND ALL DIRECTIONS" );
           put_line( "SEEM THE SAME.");
when others =>
       if treasure_room = integer(current_room) then
          new_line;
          put_line("  THE TREASURE IS HERE!!!!");
       elsif treasure_room = second_treasure_room or
            first_treasure_room /= second_treasure_room or
            first_treasure_room = integer(current_room) then
          new_line;
          put_line( "A NOTE ON THE WALL SAYS PIRATES NEVER LEAVE" );
          put_line( "THEIR TREASURE TWICE IN THE SAME PLACE!" );
       end if;
end case;
end show_room;

procedure check_for_pirate is
-- was 4000 REM
begin
  if integer(current_room) = second_treasure_room then
     return;
  end if;
  if pirate_room = 1 then
     return;
  end if;
  if first_treasure_room = second_treasure_room then
     return;
  end if;
  if treasure_room /= -1 then
     return;
  end if;
  if current_room = 16 then
     pirate_room := 160;
  end if;
  if P1 > 0 then
     P1 := P1+1;
  end if;
  if current_room = 3 then
     P1 := P1+1;
  end if;
  if P1<15 then
     return;
  end if;
  new_line;
  put_line( "SUDDENLY THE PIRATE LEAPS OUT OF THE" );
  put_line( "GLOOM AND GRABS THE TREASURE FROM YOU!" );
  put_line( "'HAH!', HE SHOUTS, 'YOU FOUND MY" );
  put_line( "TREASURE, DID YOU?!   WELL, I'LL HIDE" );
  put_line( "IT BETTER THIS TIME!'" );
  put_line( "AND HE DISAPPEARS INTO THE DARKNESS" );
  put_line( "WITH THE TREASURE." );
  pirate_room := 1;
  treasure_room := second_treasure_room;
end check_for_pirate;

procedure check_for_treasure is
begin
  if treasure_room /= integer(current_room) then
     return;
  end if;
  if treasure_room < 0 then
     return;
  end if;
  if moves_to_find_treasure+5>moves then
     return;
  end if;
  put_line( "  DO YOU WANT TO TAKE IT WITH YOU" );
  loop
    a := "YN";
    a2 := 2;
    get_input;
    exit when a1 in 1..2;
    put_line( "WELL?....." );
  end loop;
  if a1 = 1 then
     treasure_room := -1;
     new_line;
     put_line( "OK, LETS GET OUT OF HERE!" );
  else
     new_line;
     put_line( "WE'LL LEAVE IT HERE AND YOU CAN EXPLORE SOME MORE." );
     moves_to_find_treasure := moves;
  end if;
end check_for_treasure;

procedure show_options is
-- 7500 REM
begin
  new_line;
  put_line( "TYPE N,S,E,W, U   OR D  FOR NORTH, SOUTH," );
  put_line( "EAST, WEST, UP OR DOWN.  TYPE P FOR SCORE" );
  new_line;
end show_options;

procedure get_command is
-- 7000 REM
--
   allowed : constant string := "NEUDWSP"; -- A$
begin
  new_line;
  put( "                      WHICH WAY" );
  loop
    loop
      a2 := 7;
      a := allowed;
      get_input;
      exit when a1 < 8;
      put_line( "WHICH WAY DO YOU WANT TO GO?" );
      show_options;
      show_room;
    end loop;
    exit when a1 < 7;
    tally_score;
    put( "YOU HAVE" ); put( score ); put( " POINTS!" );
    new_line;
  end loop;
end get_command;

-- Main Program Begins

begin

new_line;
put_line( "WARNING: The conversion isn't finished.  This game is not" );
put_line( "working. -- KB" );
new_line; new_line; new_line;
put_line( "  YOU WERE WALKING THROUGH THE WOODS ONE DAY AND YOU" );
put_line( "CAME ACROSS THE ENTRANCE OF A CAVE, COVERED WITH BRUSH." );
put_line( "  PEOPLE SAY THAT MANY YEARS AGO A PIRATE HID HIS" );
put_line( "TREASURE IN THESE WOODS,  BUT NO ONE HAS EVER FOUND IT." );
put_line( "IT MAY STILL BE HERE,  FOR ALL I KNOW." );

move(1) := "1,0,0,0,0,0,0";
move(2) := "-2,101,-2,0,0,0";
move(3) := "33,2,1,10,106,4";
move(4) := "3,30,2,11,2,1";
move(5) := "8,8,15,10,8,16";
move(6) := "16,3,2,10,2,2";
move(7) := "7,-2,101,-2,0,0,0";
move(8) := "18,18,15,10,18,9";
move(9) := "-2,33,5,1,0,-2";
move(10) := "-2,101,-2,0,0,0";
move(11) := "1,13,4,2,1,2";
move(12) := "36,2,1,2,1,2";
move(13) := "2,37,2,1,11,14";
move(14) := "13,1,19,2,31,31";
move(15) := "-2,101,-2,0,0,0";
move(16) := "5,33,2,10,1,106";
move(17) := "-2,101,-2,0,0,0";
move(18) := "-2,101,8,0,0,0";
move(19) := "224,2,2,14,1,42";
move(20) := "226,1,2,2,25,2";
move(21) := "1,226,2,2,38,25";
move(22) := "-2,33,13,50,29,30";
move(23) := "2,1,2,31,2,2";
move(24) := "-2,101,19,0,0,0";
move(25) := "21,20,2,2,1,19";
move(26) := "-2,65,-2,50,11,14";
move(27) := "2,40,2,2,21,20";
move(28) := "-2,60,221,50,14,19";
move(29) := "2,42,2,13,1,1";
move(30) := "34,34,2,1,4,2";
move(31) := "14,14,23,2,1,2";
move(32) := "-2,101,516,0,0,0";
move(33) := "2,1,2,1,116,3";
move(34) := "1,35,2,1,30,30";
move(35) := "2,1,2,37,34,36";
move(36) := "35,2,1,37,34,12";
move(37) := "2,1,35,2,13,2";
move(38) := "2,21,2,116,1,2";
move(39) := "2,40,2,32,21,26";
move(40) := "40,40,2,2,40,41";
move(41) := "40,40,40,2,40,39";
move(42) := "28,28,28,28,28,28";

new_line;

put_line( "WHEN YOU ANSWER A QUESTION, I LOOK AT ONLY" );
put_line( "THE FIRST LETTER, ALTHOUGH YOU CAN TYPE IN" );
put_line( "THE WHOLE WORD IF YOU WANT TOO." );
show_options;

-- MASTER LOOP for restarting game

loop

for j in 1..number_of_rooms loop
    room(j) := 0;
end loop;

new_line;

loop                                               -- game loop

  show_room;                                       -- show first room
  moves := moves + 1;                              -- first move

  save_current := current_room;                    -- remember where we parked
  N8 := 0;                                         -- NQS

  get_command;
                                    -- get a command

  if current_room /= 1 then
     N0 := current_room;
     a0 := a1;
  end if;
  new_line;
  next_room := numerics.value( strings.field( move(a1), current_room, "," ) );

--  loop

    loop
       if next_room = -2 then
          next_room := save_current;
       end if;
       if debug then
          put_line( standard_error, "DEBUG" & strings.image(current_room) &
            " TO" & strings.image(next_room) );
       end if;
       if next_room >= 500 then
          next_room := next_room - 500;
          delay 2.0;
       else
          exit;
       end if;
    end loop;

    if numerics.truncation(next_room/100) = 0 then
       current_room := next_room;
    elsif numerics.truncation(next_room/100) = 1 then
       current_room := next_room-100;
       if treasure_room = -1 then
          current_room := current_room + 1;
       end if;
    else
       current_room := next_room-200;
       if treasure_room = -1 then
          current_room := current_room + natural(pirate_room);
       end if;
    end if;

    if current_room = 1 then
       for j in 1..6 loop
           strings.replace( move(j), current_room, "2", ',' );
       end loop;
    end if;
    strings.replace( move(7-a0), current_room, strings.image(N0), ',' );

-- 6500 REM

    if N8 /= 2 then
       show_room;
    end if;

    room( current_room ) := 1;
    N8 := 8;

    if numerics.value( strings.field( move( 1 ), current_room, move_sep ) ) = -2 then
       next_room := numerics.value( strings.field( move( 6 ), current_room ) );
       J := -1;

       if numerics.value( strings.field( move(4), current_room, move_sep ) ) > numerics.rnd(100) then
          next_room := numerics.value( strings.field( move(5), current_room ) );
       end if;
       J := -1;
       if numerics.value( strings.field( move(2), current_room, move_sep ) ) > numerics.rnd(100) then
          next_room := numerics.value( strings.field( move(3), current_room, move_sep ) );
       end if;
       if debug then
          put_line( "   DEBUG BOUNCE TO" & strings.image( current_room ) );
       end if;
    end if;

-- end loop;

  check_for_teasure;
  check_for_pirate;
  exit when treasure_room < 0 or current_room = 5; -- goto 1400

end loop; -- game loop

tally_score;
new_line;
put_line( " CONGRATULATIONS!!   YOU GOT THE TREASURE" );
put( "OUT IN" );
put( moves );
put( "MOVES AND YOU GOT" );
put(score+10 );
put_line( "POINTS!" );
put_line( "WANT TO HUNT AGAIN?" );
loop
  a := "YN";
  a2 := 2;
  gosub get_input;
  exit when a1 in 1..2;
end loop;
exit when a1 = 2;

end loop; -- master loop here

end quest;