Retrocomputing

Hunt the Wumpus

Wumpus is a hunting game whereby you attempt to kill a strange sort of beast -- namely, a wumpus.

OS-9 Pascal edition

{ *** HUNT THE WUMPUS *** }
program wumpus;
const
  HUNTER = 1;
  WUMPUS = 2;
  PIT1 = 3;
  PIT2 = 4;
  BAT1 = 5;
  BAT2 = 6;
var
  randstate : integer;
  arrows,lt,j,k,o,duel: integer;
  answer: char;
  path: array[1..5] of integer;
  cave: array[1..20,1..3] of integer;
  feature, origsetup: array[HUNTER..BAT2] of integer;

{ Returns a random number between 0.0 and 1.0 }
function random(var block:integer) : real; external;
procedure randomize(var block:integer); external;

{ Provide a random integer 1 <= x <= maxval }
function rnd(maxval:integer):integer;
begin
  rnd := trunc(random(randstate) * maxval) + 1;
end;

{ *** SET UP CAVE (DODECAHEDRAL NODE LIST) *** }
{ Pascal does not have initialization of arrays }
procedure initcave;
  var
    j,k: integer;
    cavefile: text;
  begin
     {
     reset(cavefile, '/d0/games/wumpuscave');
     for j := 1 to 20 do
       for k := 1 to 3 do
         read(cave[j,k]);
     close(cavefile);
     }

     cave[1,1]  := 2;  cave[1,2]  := 5;  cave[1,3]  := 8;
     cave[2,1]  := 1;  cave[2,2]  := 3;  cave[2,3]  := 10;
     cave[3,1]  := 2;  cave[3,2]  := 4;  cave[3,3]  := 12;
     cave[4,1]  := 3;  cave[4,2]  := 5;  cave[4,3]  := 14;
     cave[5,1]  := 1;  cave[5,2]  := 4;  cave[5,3]  := 6;
     cave[6,1]  := 5;  cave[6,2]  := 7;  cave[6,3]  := 15;
     cave[7,1]  := 6;  cave[7,2]  := 8;  cave[7,3]  := 17;
     cave[8,1]  := 1;  cave[8,2]  := 7;  cave[8,3]  := 9;
     cave[9,1]  := 8;  cave[9,2]  := 10; cave[9,3]  := 18;
     cave[10,1] := 2;  cave[10,2] := 9;  cave[10,3] := 11;
     cave[11,1] := 10; cave[11,2] := 12; cave[11,3] := 19;
     cave[12,1] := 3;  cave[12,2] := 11; cave[12,3] := 13;
     cave[13,1] := 12; cave[13,2] := 14; cave[13,3] := 20;
     cave[14,1] := 4;  cave[14,2] := 13; cave[14,3] := 15;
     cave[15,1] := 6;  cave[15,2] := 14; cave[15,3] := 16;
     cave[16,1] := 15; cave[16,2] := 17; cave[16,3] := 20;
     cave[17,1] := 7;  cave[17,2] := 16; cave[17,3] := 18;
     cave[18,1] := 9;  cave[18,2] := 17; cave[18,3] := 19;
     cave[19,1] := 11; cave[19,2] := 18; cave[19,3] := 20;
     cave[20,1] := 13; cave[20,2] := 16; cave[20,3] := 19;
  end;

{ *** LOCATE L ARRAY ITEMS *** }
{ *** 1-YOU, 2-WUMPUS, 3&4-PITS, 5&6-BATS *** }
procedure populate;
  var
    j,k: integer;
    crossover: boolean;
  begin
    repeat
      for j := 1 to 6 do
        begin
         feature[j] := rnd(20);
         origsetup[j] := feature[j]
        end;

     { *** CHECK FOR CROSSOVERS (IE feature[HUNTER]=feature[WUMPUS], ETC) *** }
      crossover := false;
      for j := 1 to 6 do
        for k := 1 to 6 do
           if (j<>k) and (feature[j]=feature[k]) then
             crossover := true;
    until crossover = false;
  end;

{ *** INSTRUCTIONS *** }
procedure instructions;
  var
     cr: char;
  begin
     writeln('WELCOME TO ''HUNT THE WUMPUS''');
     writeln('  THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM');
     writeln('HAS 3 TUNNELS LEADING TO OTHER ROOMS. (LOOK AT A');
     writeln('DODECAHEDRON TO SEE HOW THIS WORKS-IF YOU DON''T KNOW');
     writeln('WHAT A DODECAHEDRON IS, ASK SOMEONE)');
     writeln;
     writeln('     HAZARDS:');
     writeln(' BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM');
     writeln('     IF YOU GO THERE, YOU FALL INTO THE PIT (& LOSE!)');
     writeln(' SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU');
     writeln('     GO THERE, A BAT GRABS YOU AND TAKES YOU TO SOME OTHER');
     writeln('     ROOM AT RANDOM. (WHICH MAY BE TROUBLESOME)');
     write('HIT RETURN TO CONTINUE');
     prompt;
     readln(cr);
     writeln('     WUMPUS:');
     writeln(' THE WUMPUS IS NOT BOTHERED BY HAZARDS (HE HAS SUCKER');
     writeln(' FEET AND IS TOO BIG FOR A BAT TO LIFT).  USUALLY');
     writeln(' HE IS ASLEEP.  TWO THINGS WAKE HIM UP: YOU SHOOTING AN');
     writeln(' ARROW OR YOU ENTERING HIS ROOM.');
     writeln('     IF THE WUMPUS WAKES HE MOVES (P=.75) ONE ROOM');
     writeln(' OR STAYS STILL (P=.25).  AFTER THAT, IF HE IS WHERE YOU');
     writeln(' ARE, HE EATS YOU UP AND YOU LOSE!');
     writeln;
     writeln('     YOU:');
     writeln(' EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW');
     writeln('   MOVING:  YOU CAN MOVE ONE ROOM (THRU ONE TUNNEL)');
     writeln('   ARROWS:  YOU HAVE 5 ARROWS.  YOU LOSE WHEN YOU RUN OUT');
     writeln('   EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING');
     writeln('   THE COMPUTER THE ROOM#S YOU WANT THE ARROW TO GO TO.');
     writeln('   IF THE ARROW CAN''T GO THAT WAY (IF NO TUNNEL) IT MOVES');
     writeln('   AT RANDOM TO THE NEXT ROOM.');
     writeln('     IF THE ARROW HITS THE WUMPUS, YOU WIN.');
     writeln('     IF THE ARROW HITS YOU, YOU LOSE.');
     write('HIT RETURN TO CONTINUE');
     prompt;
     readln(cr);
     writeln('    WARNINGS:');
     writeln('     WHEN YOU ARE ONE ROOM AWAY FROM A WUMPUS OR HAZARD,');
     writeln('     THE COMPUTER SAYS:');
     writeln(' WUMPUS:  ''I SMELL A WUMPUS''');
     writeln(' BAT   :  ''BATS NEARBY''');
     writeln(' PIT   :  ''I FEEL A DRAFT''');
     writeln;
  end;

{ *** PRINT LOCATION & HAZARD WARNINGS *** }
procedure location;
  var
    j,k: integer;
  begin
    writeln;
    for j := 2 to 6 do
        for k := 1 to 3 do
            if cave[feature[HUNTER],k]=feature[j] then
              case j of
                  2: writeln('I SMELL A WUMPUS!');
                3,4: writeln('I FEEL A DRAFT');
                5,6: writeln('BATS NEARBY!');
              end;

    writeln('YOU ARE IN ROOM ', feature[HUNTER]);
    writeln('TUNNELS LEAD TO ', cave[lt,1], ' ', cave[lt,2], ' ', cave[lt,3]);
    writeln
  end;

{ *** CHOOSE OPTION *** }
function askaction:integer;
  var
    i: char;
    o: integer;
  begin
    o := 0;
    repeat
      write('SHOOT OR MOVE (S-M)? ');
      prompt;
      readln(i);
      if (i = 'S') or (i = 's') then
        o := 1;
      if (i = 'M') or (i = 'm') then
        o := 2;
    until o <> 0;
    askaction := o;
  end;

{ *** SEE IF ARROW IS AT feature[HUNTER] OR AT feature[WUMPUS] }
procedure hittest;
  begin
    if lt=feature[WUMPUS] then
      begin
        writeln('AHA! YOU GOT THE WUMPUS!');
        duel := 1
       end
     else if lt=feature[HUNTER] then
       begin
         writeln('OUCH! ARROW GOT YOU!');
         duel := -1
       end;
  end;

{ *** MOVE WUMPUS ROUTINE *** }
procedure movewumpus;
  var
    k: integer;
  begin
    k := rnd(4);
    if k<>4 then
      feature[WUMPUS] := cave[feature[WUMPUS],k];
    if feature[WUMPUS] = lt then
      begin
        writeln('TSK TSK TSK - WUMPUS GOT YOU!');
        duel := -1
      end;
  end;

{ *** ARROW ROUTINE *** }
procedure shootarrow;
  var
    j9,k,k1: integer;
    goodroom: boolean;
  begin
    duel := 0;
    { *** PATH OF ARROW *** }
    repeat
      write('NO. OF ROOMS (1-5)? ');
      prompt;
      readln(j9);
    until (j9 > 0) and (j9 < 6);
    for k := 1 to j9 do
      begin
        repeat
          goodroom := false;
          write('ROOM # ');
          prompt;
          readln(path[k]);
          if k > 2 then
            if path[k] <> path[k-2] then
              goodroom := true
            else
              writeln('ARROWS AREN''T THAT CROOKED - TRY ANOTHER ROOM')
          else
            goodroom := true;
        until goodroom = true;
      end;
      
      { *** SHOOT ARROW *** }
      lt := feature[HUNTER];
      for k := 1 to j9 do
        begin
          for k1 := 1 to 3 do
            if cave[lt,k1]=path[k] then
              lt := path[k]
            else
              lt := cave[lt, rnd(3)]; { *** NO TUNNEL FOR ARROW *** }
          hittest;
        end;

     writeln('MISSED');
     lt := feature[HUNTER];
     { *** MOVE WUMPUS *** }
     movewumpus;
     { *** AMMO CHECK *** }
     arrows := arrows - 1;
     if arrows = 0 then
       duel := -1;
  end;

{ *** MOVE ROUTINE *** }
procedure movehunter;
  label 1045,1145;
  var
    k: integer;
    legal: boolean;
  begin
    duel := 0;
    repeat
      repeat
        write('WHERE TO? ');
        prompt;
        readln(lt);
      until (lt >= 1) and (lt <= 20);
      legal := false;
      for k := 1 to 3 do { *** CHECK IF LEGAL MOVE *** }
        if cave[feature[HUNTER],k]=lt then
          legal := true;
      if lt = feature[HUNTER] then
        legal := true;
      if legal = false then
        write('NOT POSSIBLE -');
    until legal;

     { *** CHECK FOR HAZARDS *** }
1045:
    feature[HUNTER] := lt;
    { *** WUMPUS *** }
    if lt = feature[WUMPUS] then
      begin
        writeln('... OOPS! BUMPED A WUMPUS!');
        { *** MOVE WUMPUS *** }
        movewumpus;
        if duel<>0 then
          goto 1145;
      end;
      { *** PIT *** }
      if (lt=feature[PIT1]) or (lt=feature[PIT2]) then
        begin
          writeln('YYYYIIIIEEEE . . . FELL IN PIT');
          duel := -1;
          goto 1145
        end;

     { *** BATS *** }
     if (lt=feature[BAT1]) or (lt=feature[BAT2]) then
       begin
         writeln('ZAP--SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!');
         lt := rnd(20);
         goto 1045 { See if you landed on something }
       end;
1145:
  end;

begin
  randstate := 0;
  randomize(randstate);

  write('INSTRUCTIONS (Y-N)? ');
  prompt;
  readln(answer);
  if (answer = 'Y') or (answer = 'y') then
    instructions;
  initcave;
  populate;

  while true do
    begin
      { *** SET NO. OF ARROWS *** }
      arrows := 5;
      lt := feature[HUNTER];
      { *** RUN THE GAME *** }
      writeln('HUNT THE WUMPUS');
      repeat
        { *** HAZARD WARNING AND LOCATION *** }
        location;
        { *** MOVE OR SHOOT *** }
        o := askaction;
        if o = 1 then
          shootarrow
        else
          movehunter;
 
      until duel <> 0;
      if duel > 0 then
        writeln('HEE HEE HEE - THE WUMPUS''LL GET YOU NEXT TIME!!')
      else
        writeln('HA HA HA - YOU LOSE!');

      for j := 1 to 6 do
        feature[j] := origsetup[j];

      write('SAME SETUP (Y-N)? ');
      prompt;
      readln(answer);
      if (answer<>'Y') and (answer<>'y') then populate;
    end;

end.