I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Hunt the Wumpus

Hunt the Wumpus
You are encouraged to solve this task according to the task description, using any language you may know.

Create a simple implementation of the classic textual game Hunt The Wumpus.

The rules are:

The game is set in a cave that consists of a 20 room labyrinth. Each room is connected to 3 other rooms (the cave is modeled after the vertices of a dodecahedron). The objective of the player is to find and kill the horrendous beast Wumpus that lurks in the cave.

The player has 5 arrows. If they run out of arrows before killing the Wumpus, the player loses the game.

In the cave there are:

• One Wumpus
• Two giant bats
• Two bottomless pits

If the player enters a room with the Wumpus, he is eaten by it and the game is lost.

If the player enters a room with a bottomless pit, he falls into it and the game is lost.

If the player enters a room with a giant bat, the bat takes him and transports him into a random empty room.

Each turn the player can either walk into an adjacent room or shoot into an adjacent room.

Whenever the player enters a room, he "senses" what happens in adjacent rooms. The messages are:

• Nearby Wumpus: "You smell something terrible nearby."
• Nearby bat: "You hear a rustling."
• Nearby pit: "You feel a cold wind blowing from a nearby cavern."

When the player shoots, he wins the game if he is shooting in the room with the Wumpus. If he shoots into another room, the Wumpus has a 75% of chance of waking up and moving into an adjacent room: if this is the room with the player, he eats him up and the game is lost.

This version is implemented using an Ada package and a very short main procedure. The Ada packages are divided into package specifications and package bodies. The package specification contains the API for the package. The package body contains the implementation of the package functionality.

Wumpus package specification

`package Wumpus is   procedure Start_Game;end Wumpus; `

Wumpus package body

`with Ada.Numerics.Discrete_Random;with Ada.Text_IO;         use Ada.Text_IO;with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; package body Wumpus is    -- enumeration for commands   type action is (move, shoot, quit);    -- Constant value 2-d array to represent the dodecahedron room structure    subtype Room_Number is Integer range 0 .. 19;   subtype Adjacencies is Integer range 0 .. 2;    type Rooms is array (Room_Number, Adjacencies) of Integer;    Adjacent_Rooms : constant Rooms :=     ((1, 4, 7), (0, 2, 9), (1, 3, 11), (2, 3, 13), (0, 3, 5), (4, 6, 14),      (5, 7, 16), (0, 6, 8), (7, 9, 17), (1, 8, 10), (9, 11, 18), (2, 10, 12),      (11, 13, 19), (3, 12, 14), (5, 13, 15), (14, 16, 19), (5, 15, 17),      (8, 16, 18), (10, 17, 19), (12, 15, 18));    -- Game global variables   Current_Room      : Room_Number; -- The index number of the current room.   Starting_Position : Room_Number;   Wumpus_Room       : Room_Number;   Bat1_Room         : Room_Number;   Bat2_Room         : Room_Number;   Pit1_Room         : Room_Number;   Pit2_Room         : Room_Number;   Wumpus_Start      : Room_Number;   Bat1_Start        : Room_Number;   Bat2_Start        : Room_Number;   Player_Alive      : Boolean;   Wumpus_Alive      : Boolean;    subtype Arrow_Count is Integer range 0 .. 5;   Num_Arrows : Arrow_Count := 5;    procedure Inspect_Current_Room;    procedure Place_Pits is      -- Pits randomly placed in any room except room 0      subtype pit_rooms is Room_Number range 1 .. 19;      package rand_pit is new Ada.Numerics.Discrete_Random (pit_rooms);      use rand_pit;      Seed : Generator;   begin      Reset (Seed);      Pit1_Room := Random (Seed);      Pit2_Room := Random (Seed);   end Place_Pits;    -- Place bats throughout the map ensuring that the bats will not be placed   -- in the same room as another bat or the wumpus or room 0    procedure Place_Bats is      subtype bat_rooms is Room_Number range 1 .. 19;      package rand_bat is new Ada.Numerics.Discrete_Random (bat_rooms);      use rand_bat;      Seed : Generator;   begin      Reset (Seed);      loop         Bat1_Room := Random (Seed);         exit when Bat1_Room /= Wumpus_Room;      end loop;      loop         Bat2_Room := Random (Seed);         exit when Bat2_Room /= Bat1_Room and Bat2_Room /= Wumpus_Room;      end loop;      Bat1_Start := Bat1_Room;      Bat2_Start := Bat2_Room;   end Place_Bats;    -- Place the Wumpus in any room except room 0    procedure Place_Wumpus is      subtype Wump_Rooms is Room_Number range 1 .. 19;      package rand_wump is new Ada.Numerics.Discrete_Random (Wump_Rooms);      use rand_wump;      Seed : Generator;   begin      Wumpus_Room  := Random (Seed);      Wumpus_Start := Wumpus_Room;   end Place_Wumpus;    -- Place the player in room 0    procedure Place_Player is    begin      Starting_Position := 0;      Current_Room      := 0;   end Place_Player; -- returns True if Room_Id is adjacent to the specified room    function Is_Room_Adjacent     (Cur : Room_Number; Next : Room_Number) return Boolean   is   begin      for I in Adjacencies loop         if Adjacent_Rooms (Cur, I) = Next then            return True;         end if;      end loop;      return False;   end Is_Room_Adjacent;    -- Validates a move is to an adjacent room    function Is_Valid_Move (Room_Id : in Room_Number) return Boolean is   begin      return Is_Room_Adjacent (Current_Room, Room_Id);   end Is_Valid_Move;    procedure Move_Startled_Wumpus is      package rand_move is new Ada.Numerics.Discrete_Random (Adjacencies);      use rand_move;      Seed     : Generator;      New_Room : Adjacencies;   begin      Reset (Seed);      New_Room    := Random (Seed);      Wumpus_Room := Adjacent_Rooms (Wumpus_Room, New_Room);   end Move_Startled_Wumpus;    -- Restarts the game from tthe beginning    procedure Play_Again is      Reply : Character;    begin      Put_Line        ("Would you like to replay the same map? Enter Y to play again.");      Get (Reply);      Skip_Line;      if Reply = 'y' or Reply = 'Y' then         Current_Room := Starting_Position;         Wumpus_Room  := Wumpus_Start;         Bat1_Room    := Bat1_Start;         Bat2_Room    := Bat2_Start;         Num_Arrows   := 5;         Put_Line ("Try not to die this time.");         Inspect_Current_Room;      else         Player_Alive := False;      end if;   end Play_Again;    procedure Perform_Action (Act : action);    -- Starts a new game   procedure Play_Game is      package act_io is new Enumeration_IO (action);      use act_io;      Choice : action;   begin      Put_Line ("Runing the game.");       -- Initialize the game      Place_Wumpus;      Place_Bats;      Place_Pits;      Place_Player;       -- Game set up      Player_Alive := True;      Wumpus_Alive := True;      Num_Arrows   := 5;       -- Inspects the initial room      Inspect_Current_Room;       -- Main game loop       while Player_Alive and then Wumpus_Alive loop         Put_Line ("Enter an action choice.");         Put_Line ("Move");         Put_Line ("Shoot");         Put_Line ("Quit");         Put (">>> ");         loop            Put ("Please make a selection: ");            begin               Get (Choice);               Perform_Action (Choice);               exit;            exception               when others =>                  Put_Line ("Invalid choice. Please try again.");            end;         end loop;      end loop;   end Play_Game;    -- Inspects the current room.   -- This procedure checks for being in the same room as the wumpus, bats, or   -- pits. It also checks adjacent rooms for those items. It prints out the   -- room description    procedure Inspect_Current_Room is      subtype bat_rooms is Room_Number range 1 .. 19;      package rand_bat is new Ada.Numerics.Discrete_Random (bat_rooms);      use rand_bat;      Seed          : Generator;      Room_bat_Left : Room_Number := Current_Room;   begin      if Current_Room = Wumpus_Room then         Put_Line ("The Wumpus ate you!!!");         Put_Line ("LOSER!!!");         Play_Again;      elsif Current_Room = Bat1_Room or else Current_Room = Bat2_Room then         Put_Line ("Snatched by superbats!!");         if Current_Room = Pit1_Room or Current_Room = Pit2_Room then            Put_Line ("Luckily, the bat saved you from the bottomless pit!!");         end if;         Reset (Seed);         loop            Current_Room := Random (Seed);            exit when Current_Room /= Bat1_Room              and then Current_Room /= Bat2_Room;         end loop;         Put_Line ("The bat moved you to room" & Current_Room'Image);         Inspect_Current_Room;          if Room_bat_Left = Bat1_Room then            loop               Bat1_Room := Random (Seed);               exit when Bat1_Room /= Current_Room                 and then Bat1_Room /= Wumpus_Room                 and then Bat1_Room /= Bat2_Room;            end loop;         else            loop               Bat2_Room := Random (Seed);               exit when Bat2_Room /= Current_Room                 and then Bat2_Room /= Wumpus_Room                 and then Bat2_Room /= Bat1_Room;            end loop;         end if;      elsif Current_Room = Pit1_Room or else Current_Room = Pit2_Room then         Put_Line ("YYYIIIIIEEEEEE.... fell in a pit!!");         Put_Line ("GAME OVER LOSER!!!");         Play_Again;      else         Put_Line ("You are in room" & Current_Room'Image);         if Is_Room_Adjacent (Current_Room, Wumpus_Room) then            Put_Line ("You smell a horrid stench...");         end if;         if Is_Room_Adjacent (Current_Room, Bat1_Room)           or else Is_Room_Adjacent (Current_Room, Bat2_Room)         then            Put_Line ("Bats nearby...");         end if;         if Is_Room_Adjacent (Current_Room, Pit1_Room)           or else Is_Room_Adjacent (Current_Room, Pit2_Room)         then            Put_Line ("You feel a draft...");         end if;         Put_Line ("Tunnels lead to rooms");         for I in Adjacencies loop            Put (Item => Adjacent_Rooms (Current_Room, I), Width => 3);         end loop;         New_Line;      end if;   end Inspect_Current_Room;    -- Performs the action specified as the procedure argument   procedure Perform_Action (Act : action) is      New_Room : Room_Number;      Resp     : Character;   begin      case Act is         when move =>            Put_Line ("Which room?");            begin               Get (New_Room);               if Is_Valid_Move (New_Room) then                  Current_Room := New_Room;                  Inspect_Current_Room;               else                  Put_Line ("You cannot move there.");               end if;            exception               when others =>                  Put_Line ("You cannot move there.");            end;         when shoot =>            if Num_Arrows > 0 then               Put_Line ("Which room?");               begin                  Get (New_Room);                  if Is_Valid_Move (New_Room) then                     Num_Arrows := Num_Arrows - 1;                     if New_Room = Wumpus_Room then                        Put_Line ("ARGH.. SPLAT!");                        Put_Line                          ("Contratulations! You killed the Wumpus! You Win.");                        Put_Line ("Type 'Y' to return to the main menu.");                        Wumpus_Alive := False;                        Get (Resp);                        Skip_Line;                     else                        Put_Line ("Miss! But you startled the Wumpus");                        Move_Startled_Wumpus;                        Put_Line ("Arrows Left:" & Num_Arrows'Image);                        if Wumpus_Room = Current_Room then                           Put_Line                             ("The Wumpus attacked you!." &                              " You've been killed.");                           Put_Line ("Game Over!");                           Play_Again;                        end if;                     end if;                  else                     Put_Line ("You cannot shoot there.");                  end if;               exception                  when others =>                     Put_Line ("You cannot shoot there.");               end;            else               Put_Line ("You do not have any arrows!");            end if;         when quit =>            Put_Line ("Quitting the current game.");            Player_Alive := False;      end case;   end Perform_Action;    -- outputs instructions to standard output    procedure Print_Instructions is      C : Character;   begin      Put_Line (" Welcome to 'Hunt the Wumpus'! ");      Put_Line        (" The wumpus lives in a cave of 20 rooms. Each room has 3 tunnels leading to");      Put_Line        (" other rooms. (Look at a dodecahedron to see how this works - if you don't know");      Put_Line (" what a dodecahedron is, ask someone).");      New_Line;      Put_Line (" Hazards:");      New_Line;      Put_Line        (" Bottomless pits - two rooms have bottomless pits in them. If you go there, you ");      Put_Line (" fall into the pit (& lose!)");      New_Line;      Put_Line        (" Super bats - two other rooms have super bats.  If you go there, a bat grabs you");      Put_Line        (" and takes you to some other room at random. (Which may be troublesome). Once the");      Put_Line        (" bat has moved you, that bat moves to another random location on the map.");      New_Line (2);      Put_Line (" Wumpus");      Put_Line        (" The wumpus is not bothered by hazards (he has sucker feet and is too big for a");      Put_Line        (" bat to lift).  Usually he is asleep.  Two things wake him up: you shooting an");      Put_Line        (" arrow or you entering his room. If the wumpus wakes he moves (p=.75) one room or ");      Put_Line        (" stays still (p=.25). After that, if he is where you are, he eats you up and you lose!");      New_Line;      Put_Line (" You");      New_Line;      Put_Line        (" Each turn you may move, save or shoot an arrow using the commands move, save, & shoot.");      Put_Line (" Moving: you can move one room (thru one tunnel).");      Put_Line        (" Arrows: you have 5 arrows. You lose when you run out. You aim by telling the");      Put_Line        (" computer the rooms you want the arrow to shoot to. If the arrow can't go that way");      Put_Line (" (if no tunnel), the arrow will not fire.");      New_Line;      Put_Line (" Warnings");      New_Line;      Put_Line        (" When you are one room away from a wumpus or hazard, the computer says:");      Put_Line (" Wumpus: 'I smell a wumpus'");      Put_Line (" Bat: 'Bats nearby'");      Put_Line (" Pit: 'I feel a draft'");      New_Line;       Put_Line ("Press Y to return to the main menu.");      Get_Immediate (C);      Skip_Line;   end Print_Instructions;    ----------------   -- Start_Game --   ----------------    procedure Start_Game is      subtype Response is Integer range 1 .. 3;      Choice : Response;   begin      loop         Put_Line ("Welcome to Hunt The Wumpus.");         Put_Line ("1) Play Game");         Put_Line ("2) Print Instructions");         Put_Line ("3) Quit");         Put ("Please make a selection: ");         begin            Get (Choice);            Skip_Line;            case Choice is               when 1 =>                  Play_Game;               when 2 =>                  Print_Instructions;               when 3 =>                  Put_Line ("Quitting.");                  exit;            end case;         exception            when others =>               Skip_Line;               Put_Line ("Invalid choice. Please enter a 1, 2 or 3");         end;      end loop;   end Start_Game; end Wumpus; `

Main procedure

` with Wumpus; use Wumpus; procedure Main isbegin   Start_Game;end Main; `

## BASIC

`10 DEFINT A-Z: DIM R(19,3),P(1),B(1)20 FOR I=0 TO 19: READ R(I,0),R(I,1),R(I,2): NEXT30 INPUT "Enter a number";X: X=RND(-ABS(X))40 PRINT: PRINT "*** HUNT THE WUMPUS ***"50 PRINT "-----------------------": PRINT60 FOR I=0 TO 1: GOSUB 500: P(I)=X: GOSUB 500: B(I)=X: NEXT70 GOSUB 500: W=X: GOSUB 500: P=X80 A=590 IF A=0 THEN 340100 IF P=W THEN 410110 IF P=B(0) OR P=B(1) THEN 360120 IF P=P(0) OR P=P(1) THEN 390130 PRINT: FOR I=0 TO 2140 IF R(P,I)=W THEN PRINT "You smell something terrible nearby."150 FOR J=0 TO 1160 IF R(P,I)=B(J) THEN PRINT "You hear a rustling."170 IF R(P,I)=P(J) THEN PRINT "You feel a cold wind blowing from a nearby cavern."180 NEXT J,I190 PRINT USING "You are in room ##. ";P;200 PRINT USING "Tunnels lead to ##; ##; and ##.";R(P,0);R(P,1);R(P,2)210 PRINT USING "You have # arrows.";A: PRINT220 LINE INPUT "M)ove, S)hoot or Q)uit? ";I\$230 S=I\$="S" OR I\$="s": IF S OR I\$="M" OR I\$="m" THEN 260240 IF I\$="Q" OR I\$="q" THEN END250 PRINT "Sorry?": GOTO 220260 INPUT "Which room";X: PRINT270 IF X=R(P,0) OR X=R(P,1) OR X=R(P,2) THEN IF S THEN 290 ELSE P=X: GOTO 90280 PRINT "Cannot get there from here.": GOTO 260290 IF X=W THEN PRINT "Congratulations! You shot the wumpus!": GOTO 440300 PRINT "You missed.": A=A-1: IF RND(1)<.25 THEN 90310 PRINT "The wumpus wakes from his slumber."320 X=RND(1)*3: IF R(R(W,X),3) THEN 320330 R(W,3)=0: W=R(W,X): R(W,3)=1: GOTO 90340 PRINT "As you grasp at your empty quiver, ";350 PRINT "you hear a large beast approaching...": GOTO 410360 PRINT "You have entered the lair of a large bat."370 PRINT "It picks you up and drops you in room";380 P=R(P,RND(1)*3): PRINT P;".": GOTO 90390 PRINT "The ground gives way beneath your feet."400 PRINT "You fall into a deep abyss.": GOTO 430410 PRINT "You find yourself face to face with the wumpus."420 PRINT "It eats you whole."430 PRINT: PRINT "You have met your demise."440 LINE INPUT "Another game (Y/N)?";I\$450 IF I\$="Y" OR I\$="y" THEN 60460 IF I\$<>"N" AND I\$<>"n" THEN PRINT "Sorry?": GOTO 440470 END500 X=RND(1)*20: IF R(X,3)=0 THEN R(X,3)=1: RETURN ELSE 500510 DATA 1,4,7, 0,2,9, 1,3,11, 2,4,13, 0,3,5520 DATA 4,6,14, 5,7,16, 0,6,8, 7,9,17, 1,8,10530 DATA 9,11,18, 2,10,12, 11,13,19, 3,12,14, 5,13,15540 DATA 14,16,19, 6,15,17, 8,16,18, 10,17,19, 12,15,18`

## C++

` // constant value 2d array to represent the dodecahedron// room structureconst static int adjacentRooms[20][3] = {  {1, 4, 7},   {0, 2, 9},   {1, 3, 11},   {2, 4, 13},    {0, 3, 5},  {4, 6, 14},  {5, 7, 16},    {0, 6, 8},   {7, 9, 17},   {1, 8, 10},  {9, 11, 18}, {2, 10, 12}, {11, 13, 19},  {3, 12, 14},  {5, 13, 15},  {14, 16, 19}, {6, 15, 17},  {8, 16, 18}, {10, 17, 19}, {12, 15, 18}}; class WumpusGame {     private:      // Data Members      int numRooms;      int currentRoom, startingPosition; // currentRoom is an integer variable that stores the room the player is currently in (between 0-20)      int wumpusRoom, batRoom1, batRoom2, pitRoom1, pitRoom2; // Stores the room numbers of the respective      int wumpusStart, bat1Start, bat2Start;      bool playerAlive, wumpusAlive; // Are the player and wumpus still alive? True or false.      int numArrows; //store arrow count       // private functions      void PlacePits();      void PlaceBats();      void PlaceWumpus();      void PlacePlayer();      bool IsValidMove(int);      bool IsRoomAdjacent(int, int);      int Move(int);      void InspectCurrentRoom();      void PerformAction(int);      void MoveStartledWumpus(int);      void PlayGame();      void PlayAgain();      void PrintInstructions();       // Access specifier      public:        //public functions        void StartGame();        WumpusGame();}; #include <iostream>#include <stdlib.h>     /* srand, rand */#include <time.h>       /* time */#include <vector>#include <cstring>using namespace std; // default constructorWumpusGame::WumpusGame() {  numRooms = 20;} // This function prints the instructions for the game// to the consolevoid WumpusGame::PrintInstructions() {    char wait;    cout << " Welcome to 'Hunt the Wumpus'! " << endl;    cout << " The wumpus lives in a cave of 20 rooms. Each room has 3 tunnels leading to" << endl;    cout << " other rooms. (Look at a dodecahedron to see how this works - if you don't know" << endl;    cout << " what a dodecahedron is, ask someone). \n" << endl;    cout << " Hazards: \n" << endl;    cout << " Bottomless pits - two rooms have bottomless pits in them. If you go there, you " << endl;    cout << " fall into the pit (& lose!) \n" << endl;    cout << " Super bats - two other rooms have super bats.  If you go there, a bat grabs you" << endl;    cout << " and takes you to some other room at random. (Which may be troublesome). Once the" << endl;    cout << " bat has moved you, that bat moves to another random location on the map.\n\n" << endl;     cout << " Wumpus" << endl;    cout << " The wumpus is not bothered by hazards (he has sucker feet and is too big for a" << endl;    cout << " bat to lift).  Usually he is asleep.  Two things wake him up: you shooting an" << endl;    cout << " arrow or you entering his room. If the wumpus wakes he moves (p=.75) one room or " << endl;    cout << " stays still (p=.25). After that, if he is where you are, he eats you up and you lose!\n" << endl;     cout << " You \n" << endl;    cout << " Each turn you may move, save or shoot an arrow using the commands move, save, & shoot." << endl;    cout << " Moving: you can move one room (thru one tunnel)." << endl;    cout << " Arrows: you have 3 arrows. You lose when you run out. You aim by telling the" << endl;    cout << " computer the rooms you want the arrow to go to.  If the arrow can't go that way" << endl;    cout << " (if no tunnel), the arrow will not fire." << endl;     cout << " Warnings" << endl;    cout << " When you are one room away from a wumpus or hazard, the computer says:" << endl;     cout << " Wumpus: 'I smell a wumpus'" << endl;    cout << " Bat: 'Bats nearby'" << endl;    cout << " Pit: 'I feel a draft'" << endl;     cout << endl;    cout << "Press Y to return to the main menu." << endl;    cin >> wait; } // This function will place two bats throughout the map// this ensures that the bats will not be place in the same// room as another bat or the wumpusvoid WumpusGame::PlaceBats() {  srand (time(NULL));  bool validRoom = false;  while(!validRoom){      batRoom1 = rand() % 20 + 1;      if(batRoom1 != wumpusRoom)          validRoom = true;  }   validRoom = false;  while(!validRoom){      batRoom2 = rand() % 20 + 1;      if(batRoom2 != wumpusRoom && batRoom2 != batRoom1)          validRoom = true;  }  bat1Start = batRoom1;  bat2Start = batRoom2;} // this function randomly places the pits// throughout the map excluding room 0void WumpusGame::PlacePits() {    srand (time(NULL));    pitRoom1 = rand() % 20 + 1;    pitRoom2 = rand() % 20 + 1;} // this function randomly places the wumpus in a room// without being in room number 0void WumpusGame::PlaceWumpus() {    srand (time(NULL));    int randomRoom = rand() % 20 + 1;    wumpusRoom = randomRoom;    wumpusStart = wumpusRoom;} // place the player in room 0void WumpusGame::PlacePlayer() {    startingPosition = 0;    currentRoom = Move(0);} // This is a  method that checks if the user inputted a valid room to move to or not.// The room number has to be between 0 and 20, but also must be adjacent to the current room.bool WumpusGame::IsValidMove(int roomID) {    if (roomID < 0) return false;    if (roomID > numRooms) return false;    if (!IsRoomAdjacent(currentRoom, roomID)) return false;     return true;} // This method returns true if roomB is adjacent to roomA, otherwise returns false.// It is a helper method that loops through the adjacentRooms array to check.// It will be used throughout the app to check if we are next to the wumpus, bats, or pits// as well as check if we can make a valid move.bool WumpusGame::IsRoomAdjacent(int roomA, int roomB){    for (int j = 0; j < 3; j++)    {        if (adjacentRooms[roomA][j] == roomB){          return true;        }    }    return false;} // This method moves the player to a new room and returns the new room. It performs no checks on its own.int WumpusGame::Move(int newRoom){    return newRoom;} // Inspects the current room.// This method check for Hazards such as being in the same room as the wumpus, bats, or pits// It also checks if you are adjacent to a hazard and handle those cases// Finally it will just print out the room descriptionvoid WumpusGame::InspectCurrentRoom() {    srand (time(NULL));    if (currentRoom == wumpusRoom)    {        cout << "The Wumpus ate you!!!" << endl;        cout << "LOSER!!!" << endl;        PlayAgain();    }    else if (currentRoom == batRoom1 || currentRoom == batRoom2)    {        int roomBatsLeft = currentRoom;        bool validNewBatRoom = false;        bool isBatRoom = false;        cout << "Snatched by superbats!!" << endl;        if(currentRoom == pitRoom1 || currentRoom == pitRoom2)            cout << "Luckily, the bats saved you from the bottomless pit!!" << endl;        while(!isBatRoom){            currentRoom = Move(rand() % 20 + 1);            if(currentRoom != batRoom1 && currentRoom != batRoom2)                isBatRoom = true;        }        cout << "The bats moved you to room ";	      cout << currentRoom << endl;        InspectCurrentRoom();         if(roomBatsLeft == batRoom1){            while(!validNewBatRoom){                batRoom1 = rand() % 19 + 1;                if(batRoom1 != wumpusRoom && batRoom1 != currentRoom)                    validNewBatRoom = true;            }        } else {            while(!validNewBatRoom){                batRoom2 = rand() % 19 + 1;                if(batRoom2 != wumpusRoom && batRoom2 != currentRoom)                    validNewBatRoom = true;            }        }    }    else if(currentRoom == pitRoom1 || currentRoom == pitRoom2)    {        cout << "YYYIIIIIEEEEE.... fell in a pit!!!" << endl;        cout << "GAME OVER LOSER!!!" << endl;        PlayAgain();    }    else    {        cout << "You are in room ";        cout << currentRoom << endl;        if (IsRoomAdjacent(currentRoom, wumpusRoom)){            cout << "You smell a horrid stench..." << endl;        }        if (IsRoomAdjacent(currentRoom, batRoom1) || IsRoomAdjacent(currentRoom, batRoom2)){            cout << "Bats nearby..." << endl;        }        if (IsRoomAdjacent(currentRoom, pitRoom1) || IsRoomAdjacent(currentRoom, pitRoom2)){            cout << "You feel a draft..." << endl;        }        cout << "Tunnels lead to rooms " << endl;        for (int j = 0; j < 3; j++)        {            cout << adjacentRooms[currentRoom][j];            cout << " ";        }        cout << endl;    }} // Method accepts an int which is the command the user inputted.// This method performs the action of the command or prints out an error.void WumpusGame::PerformAction(int cmd) {    int newRoom;    switch (cmd)    {         case 1:            cout << "Which room? " << endl;            try            {                cin >> newRoom;                // Check if the user inputted a valid room id, then simply tell the player to move there.                if (IsValidMove(newRoom))                {                    currentRoom = Move(newRoom);                    InspectCurrentRoom();                }                else                {                    cout << "You cannot move there." << endl;                }            }            catch (...) // Try...Catch block will catch if the user inputs text instead of a number.            {                cout << "You cannot move there." << endl;            }            break;        case 2:            if(numArrows > 0){                cout << "Which room? " << endl;                try                {                    cin >> newRoom;                    // Check if the user inputted a valid room id, then simply tell the player to move there.                    if (IsValidMove(newRoom))                    {                        numArrows--;                        if(newRoom == wumpusRoom){                            cout << "ARGH.. Splat!" << endl;                            cout << "Congratulations! You killed the Wumpus! You Win." << endl;                            cout << "Press 'Y' to return to the main menu." << endl;                            wumpusAlive = false;                            cin >> newRoom;                            cin.clear();                            cin.ignore(10000, '\n');                        }                        else                        {                            cout << "Miss! But you startled the Wumpus" << endl;                            MoveStartledWumpus(wumpusRoom);                            cout << "Arrows Left: ";                            cout << numArrows << endl;                            if(wumpusRoom == currentRoom){                                cout << "The wumpus attacked you! You've been killed." << endl;                                cout << "Game Over!" << endl;                                PlayAgain();                            }                         }                    }                    else                    {                        cout << "You cannot shoot there." << endl;                    }                }                catch (...) // Try...Catch block will catch if the user inputs text instead of a number.                {                    cout << "You cannot shoot there." << endl;                }            } else            {                cout << "You do not have any arrows!" << endl;            }            break;        case 3:            cout << "Quitting the current game." << endl;            playerAlive = false;            break;        default:            cout << "You cannot do that. You can move, shoot, save or quit." << endl;            break;    }} // this function moves the wumpus randomly to a room that is adjacent to// the wumpus's current positionvoid WumpusGame::MoveStartledWumpus(int roomNum){    srand (time(NULL));    int rando = rand() % 3;    if(rando != 3)        wumpusRoom = adjacentRooms[roomNum][rando];} // This restarts the map from the begiinningvoid WumpusGame::PlayAgain(){    char reply;    cout << "Would you like to replay the same map? Enter Y to play again." << endl;    cin >> reply;    if(reply == 'y' || reply == 'Y'){        currentRoom = startingPosition;        wumpusRoom = wumpusStart;        batRoom1 = bat1Start;        batRoom2 = bat2Start;        cout << "Try not to die this time. \n" << endl;        InspectCurrentRoom();    } else {        playerAlive = false;    } } // PlayGame() method starts up the game.// It houses the main game loop and when PlayGame() quits the game has ended.void WumpusGame::PlayGame(){	int choice;  bool validChoice = false; 	cout << "Running the game..." << endl;   // Initialize the game	PlaceWumpus();	PlaceBats();	PlacePits();	PlacePlayer(); 	// game set up	playerAlive = true;	wumpusAlive = true;	numArrows = 3;     //Inspects the initial room    InspectCurrentRoom();     // Main game loop.    while (playerAlive && wumpusAlive)    {        cout << "Enter an action choice." << endl;        cout << "1) Move" << endl;        cout << "2) Shoot" << endl;        cout << "3) Quit" << endl;        cout << ">>> ";         do        {            validChoice = true;            cout << "Please make a selection: ";            try            {                cin >> choice;                switch (choice)                {                    case 1:                        PerformAction(choice);                        break;                    case 2:                        PerformAction(choice);                        break;                    case 3:                        PerformAction(choice);                        break;                    default:                        validChoice = false;                        cout << "Invalid choice. Please try again." << endl;                        cin.clear();		                    cin.ignore(10000, '\n');                        break;                }            }            catch (...)            {                validChoice = false;                cout << "Invalid choice. Please try again." << endl;                cin.clear();                cin.ignore(10000, '\n');            }         } while (validChoice == false);    }} // this function begins the game loopvoid WumpusGame::StartGame() { 	srand (time(NULL));	int choice;  bool validChoice;  bool keepPlaying;  wumpusStart = bat1Start = bat2Start = -1;   do {      keepPlaying = true;      cout << "Welcome to Hunt The Wumpus." << endl;      cout << "1) Play Game" << endl;      cout << "2) Print Instructions" << endl;      cout << "3) Quit" << endl;       do      {          validChoice = true;          cout << "Please make a selection: ";          try          {              cin >> choice;              switch (choice)              {                  case 1:                      PlayGame();                      break;                  case 2:                      PrintInstructions();                      break;                  case 3:                      cout << "Quitting." << endl;                      keepPlaying = false;                      break;                  default:                      validChoice = false;                      cout << "Invalid choice. Please try again." << endl;                      cin.clear();                      cin.ignore(10000, '\n');                      break;              }          }          catch (...)          {              validChoice = false;              cout << "Invalid choice. Please try again." << endl;              cin.clear();              cin.ignore(10000, '\n');          }       } while (validChoice == false);  } while (keepPlaying);} int main() {    // create wumpus game object    WumpusGame game;    // start the game    game.StartGame();}  `

## Common Lisp

` ;;; File: HuntTheWumpus.lisp  (setf *random-state* (make-random-state t))(defvar numRooms 20)(defparameter Cave #2A((1 4 7)   (0 2 9)   (1 3 11)   (2 4 13)  (0 3 5)               (4 6 14)  (5 7 16)    (0 6 8)   (7 9 17)   (1 8 10)               (9 11 18) (2 10 12) (11 13 19)  (3 12 14)  (5 13 15)               (14 16 19) (6 15 17)  (8 16 18) (10 17 19) (12 15 18))) (defun PrintInstructions()    (print " Welcome to 'Hunt the Wumpus'! " )    (print " The wumpus lives in a cave of 20 rooms. Each room has 3 tunnels leading to")    (print " other rooms. (Look at a dodecahedron to see how this works - if you don't know")    (print " what a dodecahedron is, ask someone). ")    (print " Hazards: ")  (terpri)    (print " Bottomless pits - two rooms have bottomless pits in them. If you go there, you ")    (print " fall into the pit (& lose!) ")  (terpri)    (print " Super bats - two other rooms have super bats.  If you go there, a bat grabs you")    (print " and takes you to some other room at random. (Which may be troublesome). Once the")    (print " bat has moved you, that bat moves to another random location on the map.")  (terpri)  (terpri)     (print " Wumpus")    (print " The wumpus is not bothered by hazards (he has sucker feet and is too big for a")    (print " bat to lift).  Usually he is asleep.  Two things wake him up: you shooting an")    (print " arrow or you entering his room. If the wumpus wakes he moves (p=.75) one room or ")    (print " stays still (p=.25). After that, if he is where you are, he eats you up and you lose!")  (terpri)     (print " You ")  (terpri)    (print " Each turn you may move, save or shoot an arrow using the commands move, save, & shoot.")    (print " Moving: you can move one room (thru one tunnel).")    (print " Arrows: you have 3 arrows. You lose when you run out. You aim by telling the")    (print " computer the rooms you want the arrow to go to.  If the arrow can't go that way")    (print " (if no tunnel), the arrow will not fire.")     (print " Warnings")    (print " When you are one room away from a wumpus or hazard, the computer says:")     (print " Wumpus: 'I smell a wumpus'")    (print " Bat: 'Bats nearby'")    (print " Pit: 'I feel a draft'") (terpri)    (print "Press Y to return to the main menu.")    (defvar again)    (setq goBack (read))    (if (string= goBack "Y")      (StartGame)    ) ) (defun PlacePlayer()  (setq startingPosition 0)  (setq currentRoom (Move 0)) )  (defun PlaceWumpus()  (setq wumpusRoom (round (+ 1 (random 19))))  (setq wumpusStart wumpusRoom)) (defun PlacePits()  (setq pitRoom1 (round (+ 1 (random 19))))  (setq pitRoom2 (round (+ 1 (random 19))))) (defun PlaceBats()    (let ((validRoom T))      (loop while validRoom        do          (setq batRoom1 (round (+ 1 (random 19))))          (if (/= batRoom1 wumpusRoom)            (setf validRoom nil))))    (let ((validRoom T))      (loop while validRoom        do          (setq batRoom2 (round (+ 1 (random 19))))          (if (and (/= batRoom2 wumpusRoom) (/= batRoom2 batRoom1))            (setf validRoom nil))))    (setq bat1Start batRoom1)    (setq bat2Start batRoom2)) (defun Move (newRoom)  (return-from Move newRoom)) (defun IsValidMove (roomID)  (if (< roomID 0)    (return-from IsValidMove nil)  )  (if (> roomID numRooms)    (return-from IsValidMove nil)  )  (if (eq (IsRoomAdjacent currentRoom roomID) nil)    (return-from IsValidMove nil)  )  (return-from IsValidMove T)) (defun IsRoomAdjacent (roomA roomB)  (loop for j from 0 to 2    do    (if (= (aref Cave roomA j) roomB)      (return-from IsRoomAdjacent T)    )  )  (return-from IsRoomAdjacent nil)) (defun InspectCurrentRoom()  (if (= currentRoom wumpusRoom)    (progn      (print "The Wumpus ate you!!!")      (print "LOSER!!!")      (StartGame)    )    (if (or (= currentRoom batRoom1) (= currentRoom batRoom2))      (progn        (defvar roomBatsLeft currentRoom)        (defvar validNewBatRoom nil)        (defvar isBatRoom nil)        (print "Snatched by superbats!!")        (if (or (= currentRoom pitRoom1) (= currentRoom pitRoom2))            (print "Luckily, the bats saved you from the bottomless pit!!")        )        (loop while (eq isBatRoom nil)          do            (defvar rand)            (setq rand (round (+ 1 (random 19))))            (setq currentRoom rand)            (if (and (/= currentRoom batRoom1) (/= currentRoom batRoom2))              (setf isBatRoom T)            )        )        (setf isBatRoom nil)        (print "The bats moved you to room")        (print currentRoom)        (InspectCurrentRoom)        (if (= roomBatsLeft batRoom1)          (loop while (not validNewBatRoom)            do               (setq batRoom1 (round (+ 1 (random 19))))               (if (and (/= batRoom1 wumpusRoom) (/= batRoom1 currentRoom))                 (setq validNewBatRoom T)               )          )          (loop while (not validNewBatRoom)            do               (setq batRoom2 (round (+ 1 (random 19))))               (if (and (/= batRoom2 wumpusRoom) (/= batRoom2 currentRoom))                 (setq validNewBatRoom T)               )          )        )      )      (if (or (= currentRoom pitRoom1) (= currentRoom pitRoom2))        (progn          (print "YYYIIIIIIEEEEE.... fell in a pit!!!")          (print "GAME OVER LOSER!!!")          (StartGame)        )        (progn             (print "You are in room")            (print currentRoom)            (if (eq (IsRoomAdjacent currentRoom wumpusRoom) T)              (print "You smell a horrid stench...")            )            (if (or (eq (IsRoomAdjacent currentRoom batRoom1) T) (eq (IsRoomAdjacent currentRoom batRoom2) T))              (print "Bats nearby...")            )            (if (or (eq (IsRoomAdjacent currentRoom pitRoom1) T) (eq (IsRoomAdjacent currentRoom pitRoom2) T))              (print "You feel a draft")            )            (print "Tunnels lead to rooms")            (loop for i from 0 to 2 do                (print (aref Cave currentRoom i))            )            (terpri)         )      )    )  )) (defun moveStartledwumpus(roomNum)    (defvar rando)    (setq rando (random 4))    (if (/= rando 3)      (setq wumpusRoom (aref Cave roomNum rando))    )) (defun PreformAction(cmd)  (defvar newRoom)  (case cmd    (1      (print "Which room?")      (setq newRoom (read))      (if (eq (IsValidMove newRoom) T)        (progn          (setq currentRoom (Move newRoom))          (InspectCurrentRoom)        )        (print "You cannot move there")      )    )    (2      (if (> numArrows 0)        (progn          (print "Which room?")          (setq newRoom (read))          (if (eq (IsValidMove newRoom) T)            (progn              (setq numArrows (- numArrows 1))              (if (= newRoom wumpusRoom)                (progn                  (print "ARGH.. Splat!")                  (print "Congratulations! You killed the Wumpus! You Win.")                  (setq wumpusAlive nil)                  (terpri)                  ;;;(StartGame)                )                (progn                  (print "Miss! but you startled the Wumpus")                  (moveStartledwumpus wumpusRoom)                  (print "Arrows Left")                  (print numArrows)                  (if (= wumpusRoom currentRoom)                    (progn                    (print "The wumpus attacked you! You've been killed.")                    (print "Game Over!")                    (terpri)                    (StartGame)                    )                  )                 )              )            )            (print "You cannot shoot there")          )        )        (progn           (print "You do not have any arrows!")           ;;;(print "Game Over!")           (terpri)           ;;;(StartGame)          )      )    )    (3      (print "Quiting the current game.")      (setq playerAlive nil)      (terpri)      ;;;(StartGame)    )    (otherwise      (print "You cannot do that. You can move, shoot, save or quit.")    )  ) )   (defun Playgame()  (defvar choice)  (defvar validChoice nil)   (print "Running the game...")   ;;;Initialize the game  (PlaceWumpus)  (PlaceBats)  (PlacePits)  (PlacePlayer)   ;;;game set up  (setq playerAlive T)  (setq wumpusAlive T)  (setq numArrows 3)   ;;;InspectCurrentRoom  (InspectCurrentRoom)   ;(loop while (and (eq playerAlive T) (eq wumpusAlive T))  ;  do  (loop do      (print "Enter an action choice")      (print "1) Move")      (print "2) Shoot")      (print "3) Quit")      (print ">>>") ;    (loop while (eq validChoice nil)     (loop do        (setq validChoice T)        (defvar choice)        (setq choice (read))        (case choice          (1 (PreformAction choice))          (2 (PreformAction choice))          (3 (PreformAction choice))          (otherwise            (setq validChoice nil)            (print "Invalid choice. Please try again.")          )      )   while (eq validChoice nil)) while (and (eq playerAlive T) (eq wumpusAlive T))))  (defun StartGame()   (let ((keepPlaying T))    (loop while keepPlaying      do      (print "Welcome to Hunt The Wumpus.")      (print "1) Play Game")      (print "2) Print Instructions")      (print "3) Quit")      (let ((validChoice T))        (loop while validChoice          do          (print "Please make a selection") (terpri)          (defvar selection)          (setq selection (read))          (case selection            (1 (Playgame))            (2 (PrintInstructions))            (3 (setf keepPlaying nil))            (otherwise              (setq validChoice nil)              (print "Invalid choice. Please try again.")            )           )           (setf validChoice nil)            )       )      (setf keepPlaying nil)    )  ) )(StartGame) `

## FORTRAN

This code names rooms by alphabetic character, thereby making use of index function and simplifying the input to single characters. Compiled with gfortran, source compatible with FORTRAN 2008. You're welcome to move this content to a separate webpage.

```Makefile
```
` # gnu make COMMON := -Wall -g -fPIC -fopenmpoverride FFLAGS += \${COMMON} -ffree-form -fall-intrinsics -fimplicit-none %: %.F08	gfortran -std=f2008 \$(FFLAGS) \$< -o [email protected] %.o: %.F08	gfortran -std=f2008 -c \$(FFLAGS) \$< -o [email protected] %: %.f08	gfortran -std=f2008 \$(FFLAGS) \$< -o [email protected] %.o: %.f08	gfortran -std=f2008 -c \$(FFLAGS) \$< -o [email protected] `

The paint subroutine is a place-holder where is envisioned to place additional symbols representing possible hazards and determined hazards. With ANSI graphics or actual pictures. Source:

` ! compilation, linux.  Filename htw.f90! a=./htw && make \$a && \$a ! default answers eliminate infinite cycles,! as does the deal subroutine. module constants  implicit none  integer, parameter :: you = 1  integer, parameter :: wumpus = 2  integer, parameter :: pit1 = 3  integer, parameter :: pit2 = 4  integer, parameter :: bat1 = 5  integer, parameter :: bat2 = 6  character(len=20), parameter :: rooms = 'ABCDEFGHIJKLMNOPQRST'  character(len=3), dimension(20), parameter :: cave = (/          &    & 'BEH','ACJ','BDL','CEN','ADF','EGO','FHQ','AGI','HJR','BIK', &    & 'JLS','CKM','LNT','DMO','FNP','OQT','GPR','IQS','KRT','MPS'  &    & /)end module constants program htw  use constants  implicit none  ! occupied(you:you) is the room letter  character(len=bat2) :: occupied!  character(len=22) :: test ! debug  deal  integer :: arrows  logical :: ylive, wlive  ! get instructions out of the way  if (interact('Do you want instructions (y-n):') .eq. 'Y') then    call instruct  end if  ! initialization  arrows = 5  call random_seed()  call deal(rooms, occupied)!  call deal(rooms, test)  ! debug  deal!  write(6,*) test(1:20)   ! debug  deal  ylive = .true.  wlive = .true.  write(6,*) 'Hunt the wumpus'  do while (ylive .and. wlive)    call paint(occupied(you:you))    call warn(occupied)    if (interact('Move or shoot (m-s):') .eq. 'S') then      call shoot(occupied)      arrows = arrows - 1    else      call move(occupied)    end if    wlive = 0 .lt. (index(rooms, occupied(wumpus:wumpus)))    ylive = (fate(occupied) .and. (0 .lt. arrows)) .or. (.not. wlive)  end do  if (wlive) then    write(6,*) 'The wumpus lives.  Game over.'  else    write(6,*) 'You killed the wumpus lives.  Game over.'  end if contains   subroutine paint(room)    ! interesting game play when the map must be deciphered    ! The wumpus map was well known, so it is provided    implicit none    character(len=31), dimension(14), parameter :: map = (/ &      & '     A...................B     ', &      & '   ..  \               /  .    ', &      & '   .     H-----I------J    .   ', &      & '  ..    /      |       \   .   ', &      & '  .    G _   . R- _     \   .  ', &      & ' ..   /    Q        -S---K  .  ', &      & ' .   /     \         /   \   . ', &      & ' . _-F_     \       /    _L_ . ', &      & 'E -    \_   /P-----T   _/   \ C', &      & ' ..       O/        \M/    ... ', &      & '   ...     \__    _ /   ...    ', &      & '      ...     \ N/   ...       ', &      & '         ...    | ...          ', &      & '            ... D              '  &      & /)    character(len=31) :: marked_map    character(len=1), intent(in) :: room    integer :: i, j    write(6,*)    do i=1, 14      marked_map = map(i)      j = index(marked_map, room)      if (0 < j) then        marked_map(j:j) = 'y'      end if      ! write(6,'(a,6x,a)') map(i), marked_map  ! noisy      write(6,'(6x,a)') marked_map    end do    write(6,*)    write(6,'(3a/)') 'you are in room ', room, ' marked with y'  end subroutine paint   function raise(c) ! usually named "to_upper"    ! return single character input as upper case    implicit none    character(len=1), intent(in) :: c    character(len=1) :: raise    character(len=26), parameter :: lower_case = 'abcdefghijklmnopqrstuvwxyz'    character(len=26), parameter :: upper_case = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'    integer :: n    n = index(lower_case, c)    if (n .ne. 0) then      raise = upper_case(n:n)    else      raise = c    end if  end function raise   function interact(prompt)    implicit none    ! prompt, get answer, return as upper case    character(len=1) :: interact    character(len=*), intent(in) :: prompt    character(len=1) :: answer    write(6,*) prompt    read(5,*) answer    interact = raise(answer)  end   subroutine instruct    implicit none    write(6,*) 'Welcome to wumpus hunt'    write(6,*) ''    write(6,*) 'The wumpus sleeps within a cave of 20 rooms.'    write(6,*) 'Goal: shoot the wumpus with 1 of 5 crooked arrows.'    write(6,*) 'Each room has three tunnels leading to other rooms.'    write(6,*) 'At each turn you can move or shoot up to 5 rooms distant'    write(6,*) ''    Write(6,*) 'Hazards:'    write(6,*) ' 2 rooms have bottomless pits.  Enter and lose.'    write(6,*) ' 2 rooms have giant bats.  Enter & they carry you elsewhere.'    write(6,*) ' 1 room holds the wumpus.  Enter and it eats you.'    write(6,*) ''    write(6,*) 'Warnings: Entering a room adjoining a hazard'    write(6,*) ' Pit "I feel a draft"'    write(6,*) ' Bat "Bat nearby"'    write(6,*) ' Wumpus "I smell a wumpus"'    write(6,*) ''    write(6,*) 'Shooting awakens the wumpus, which moves to an'    write(6,*) 'adjoining room with (75%) else stays put.'    write(6,*) 'The wumpus eats you if it enters your space.'    write(6,*) 'choose arrow path wisely lest you shoot yourself'  end subroutine instruct   integer function random_integer(n)    implicit none    ! return a random integer from 1 to n    ! replaces FN[ABC]    integer, intent(in) :: n    double precision :: r    call random_number(r)    random_integer = 1 + int(r * n)  end function random_integer   subroutine deal(deck, hand)    ! deal from deck into hand ensuring to not run indefinitely    ! by selecting from set of valid indexes    implicit none    character(len=*), intent(in) :: deck    character(len=*), intent(out) :: hand    integer, dimension(:), allocatable :: idx    integer :: k, j, n    n = len(deck)    allocate(idx(n))    do k=1, n      idx(k) = k    end do    do k=1, min(len(deck), len(hand))      j = random_integer(n)      hand(k:k) = deck(idx(j):idx(j))      idx(j:n-1) = idx(j+1:n) ! shift indexes      n = n - 1    end do    deallocate(idx)  end subroutine deal   subroutine warn(occupied)    use constants    implicit none    character(len=6), intent(in) :: occupied    character(len=3) :: neighbors    neighbors  = cave(index(rooms, occupied(you:you)))    if (0 .lt. index(neighbors, occupied(wumpus:wumpus))) write(6,*) 'I smell a wumpus!'    if (0 .lt. (index(neighbors, occupied(pit1:pit1)) + index(neighbors, occupied(pit2:pit2)))) &      & write(6,*) 'I feel a draft.'    if (0 .lt. (index(neighbors, occupied(bat1:bat1)) + index(neighbors, occupied(bat2:bat2)))) &      & write(6,*) 'Bats nearby.'    ! write(6,*) occupied  ! debug  end subroutine warn   subroutine shoot(occupied)    use constants    implicit none    character(len=3), dimension(5), parameter :: ordinal = (/'1st','2nd','3rd','4th','5th'/)    character(len=6), intent(inout) :: occupied    character(len=5) :: path    character(len=3) :: neighbors    character(len=1) :: arrow ! location    integer :: i, j, n    logical :: valid    n = max(1, index(rooms(1:5), interact('Use what bow draw weight? a--e for 10--50 #s')))    ! well, this is the intent I understood of the description    write(6,*) 'define your crooked arrow''s path'    do i=1, n      path(i:i) = interact(ordinal(i)//' ')    end do    ! verify path    valid = .true.    do i=3, n  ! disallow 180 degree turn      j = i - 1      valid = valid .and. (path(i:i) .ne. path(j:j))    end do    if (.not. valid) write(6,*)'Arrows are''t that crooked!'    ! author David Lambert    arrow = occupied(you:you)    do i=1, n ! verify connectivity      j = index(rooms, arrow)      neighbors = cave(j)      if (0 .lt. index(neighbors, path(i:i))) then        arrow = path(i:i)      else        valid = .false.      end if    end do    if (.not. valid) then ! choose random path, which can include U-turn, lazy.      do i=1, n        j = index(rooms, arrow)        neighbors = cave(j)        call deal(neighbors, arrow)        path(i:i) = arrow      end do    end if    ! ... and the arrow    i = mod(index(path, occupied(you:you)) + 6, 7)    j = mod(index(path, occupied(wumpus:wumpus)) + 6, 7)    if (i .lt. j) then      write(6, *) 'Oooof!  You shot yourself'      occupied(you:you) = 'x'    else if (j .lt. i) then      write(6, *) 'Congratulations!  You slew the wumpus.'      occupied(wumpus:wumpus) = 'x'    else ! wumpus awakens, rolls over and back to sleep or moves.      i = index(rooms, occupied(wumpus:wumpus))      neighbors = cave(i)      call deal(neighbors // occupied(wumpus:wumpus), occupied(wumpus:wumpus))    end if  end subroutine shoot   subroutine move(occupied)    use constants    implicit none    character(len=6), intent(inout) :: occupied    character(len=3) :: neighbors    integer :: i    neighbors = cave(index(rooms, occupied(you:you)))    i = index(neighbors, interact('Where to? '//neighbors//'  defaults to '//neighbors(1:1)))    i = max(1, i)    occupied(you:you) = neighbors(i:i)  end subroutine move   logical function fate(occupied)    ! update position of you and bat    ! return    use constants    implicit none    character(len=6), intent(inout) :: occupied    character(len=1) :: y, w, p1, p2, b1, b2    integer :: i    y = occupied(you:you)    if (0 .eq. index(rooms, y)) then      fate = .false.      return    end if    w = occupied(wumpus:wumpus)    if (0 .eq. index(rooms, w)) then      fate = .true.      return    end if    p1 = occupied(pit1:pit1)    p2 = occupied(pit2:pit2)    b1 = occupied(bat1:bat1)    b2 = occupied(bat2:bat2)    ! avoiding endless flight, the bats can end up in same room    ! these bats reloacate.  They also grab you before falling    ! into pit.    if (w .eq. y) then      write(6,*)'You found the GRUEsome wumpus.  It devours you.'      fate = .false.      return    end if    if ((b1 .eq. y) .or. (b2 .eq. y)) then      write(6,*)'A gigantic bat carries you to elsewhereville, returning to it''s roost.'      i = random_integer(len(rooms))      y = rooms(i:i)      occupied(you:you) = y    end if    if (w .eq. y) then      write(6,*)'and drops you into the wumpus''s GRUEtesque fangs'      fate = .false.    else if ((p1 .eq. y) .or. (p2 .eq. y)) then      write(6,*)'you fall into a bottomless pit'      fate = .false.    else      fate = .true.    end if  end function fate end program htw `

short sample run

```\$ ./htw
Do you want instructions (y-n):
n
Hunt the wumpus

A...................B
..  \               /  .
.     H-----I------J    .
..    /      |       \   .
.    G _   . R- _     \   .
..   /    Q        -S---K  .
.   /     \         /   \   .
. _-F_     \       /    _L_ .
y -    \_   /P-----T   _/   \ C
..       O/        \M/    ...
...     \__    _ /   ...
...     \ N/   ...
...    | ...
... D

you are in room E marked with y

Bats nearby.
Move or shoot (m-s):
m
Where to? ADF  defaults to A
x
A gigantic bat carries you to elsewhereville, returning to it's roost.

A...................B
..  \               /  .
.     H-----I------J    .
..    /      |       \   .
.    G _   . R- _     \   .
..   /    Q        -S---K  .
.   /     \         /   \   .
. _-F_     \       /    _y_ .
E -    \_   /P-----T   _/   \ C
..       O/        \M/    ...
...     \__    _ /   ...
...     \ N/   ...
...    | ...
... D

you are in room L marked with y

I feel a draft.
Move or shoot (m-s):
m
Where to? CKM  defaults to C
c
you fall into a bottomless pit
The wumpus lives.  Game over.
```

## FreeBASIC

`data 7,13,19,12,18,20,16,17,19,11,14,18,13,15,18,9,14,16,1,15,17,10,16,20,6,11,19,8,12,17data 4,9,13,2,10,15,1,5,11,4,6,20,5,7,12,3,6,8,3,7,10,2,4,5,1,3,9,2,8,14data 1,2,3,1,3,2,2,1,3,2,3,1,3,1,2,3,2,1 randomize timer dim shared as ubyte i, j, tunnel(1 to 20, 1 to 3), lost(1 to 6, 1 to 3), targdim as ubyte player = int(rnd*20)+1, wump, bat1, bat2, pit1, pit2, d6, epidim as ubyte arrows = 5dim as string choice for i = 1 to 20    'set up rooms    for j = 1 to 3         read tunnel(i,j)    next jnext i for i = 1 to 6   'set up list of permuatations of 1-2-3    for j = 1 to 3        read lost(i,j)    next jnext i 'place wumpus, bats, and pitsdo    wump = int(rnd*20)+1loop until wump <> playerdo    pit1 = int(rnd*20)+1loop until pit1 <> playerdo    pit2 = int(rnd*20)+1loop until pit2 <> player andalso pit2 <> pit1do    bat1 = int(rnd*20)+1loop until bat1 <> player andalso bat1 <> pit1 andalso bat1 <> pit2do    bat2 = int(rnd*20)+1loop until bat2 <> player andalso bat2 <> pit1 andalso bat2 <> pit2 andalso bat2 <> bat1 do    if player = wump then        print "You have been eaten by the Wumpus!"        goto defeat    end if    if player = pit1 or player = pit2 then        print "Aaaaaaaaaaa! You have fallen into a bottomless pit."        goto defeat    end if    if player = bat1 or player = bat2 then        print "A bat has carried you into another empty room."        do            player = (rnd*20)+1         loop until player <> wump andalso player <> pit1 andalso player <> pit2 andalso player <> bat1 andalso player <> bat2    end if    print using "You are in room ##. There are tunnels to rooms ## ## and ##."; player; tunnel(player,1); tunnel(player,2); tunnel(player,3)    print using "You have ## arrows left."; arrows    d6 = 1 + int(rnd*6)    for i = 1 to 3        epi = tunnel(player,lost(d6,i))        if epi = wump then            print "You smell something terrible nearby."        end if        if epi = bat1 or epi = bat2 then            print "You hear a rustling."        end if        if epi = pit1 or epi = pit2 then            print "You feel a cold wind blowing from a nearby cavern."        end if    next i    choices:    print    print "What would you like to do? Type A to shoot an arrow, or a number to move to another room."    input choice    select case left(choice,1)        case "a", "A"            input "Which room would you like to shoot into? ", targ            if targ = player then                print "You shot yourself. Why would you want to do such a thing?"                goto defeat            end if            if targ = wump then goto victory            if targ = tunnel(player,1) or targ = tunnel(player,2) or targ = tunnel(player,3) then                print "The Wumpus awakes!"                if rnd < 0.75 then                    print "He moves to a nearby cavern."                    wump = tunnel(wump, 1+int(rnd*3))                else                    print "He goes back to sleep."                end if            else                print "You can't shoot that room from here."                goto choices            end if            arrows -= 1        case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"            targ = valint(choice)            if targ = player then print "You are already there."            if targ = tunnel(player,1) or targ = tunnel(player,2) or targ = tunnel(player,3) then                print using "You walk to room ##"; targ                player = targ            else                print "You can't get there from here."            end if        case else            print "You are making no sense."    end selectloop until arrows = 0print "You have run out of arrows!"defeat:print "You lose! Better luck next time."endvictory:print "You have slain the Wumpus!"print "You have won!"end`

## Go

I've tried to stick as closely as possible to the task description but, as some points are unclear, I've had to make the following assumptions:

1. The bats and the pits are in separate rooms but the Wumpus can be in any room whether there's another hazard in it or not.

2. The game starts with the player in room 1 which initially contains no hazards.

3. If a bat transports the player to a random empty room, it returns to its original room.

4. If the Wumpus wakes up and moves to an 'adjacent' room, it means a room adjacent to the Wumpus not necessarily the player.

`package main import (    "bufio"    "fmt"    "log"    "math/rand"    "os"    "strconv"    "strings"    "time") var cave = map[int][3]int{    1: {2, 3, 4}, 2: {1, 5, 6}, 3: {1, 7, 8}, 4: {1, 9, 10}, 5: {2, 9, 11},    6: {2, 7, 12}, 7: {3, 6, 13}, 8: {3, 10, 14}, 9: {4, 5, 15}, 10: {4, 8, 16},    11: {5, 12, 17}, 12: {6, 11, 18}, 13: {7, 14, 18}, 14: {8, 13, 19},    15: {9, 16, 17}, 16: {10, 15, 19}, 17: {11, 20, 15}, 18: {12, 13, 20},    19: {14, 16, 20}, 20: {17, 18, 19},} var player, wumpus, bat1, bat2, pit1, pit2 int var arrows = 5 func isEmpty(r int) bool {    if r != player && r != wumpus && r != bat1 && r != bat2 && r != pit1 && r != pit2 {        return true    }    return false} func sense(adj [3]int) {    bat := false    pit := false    for _, ar := range adj {        if ar == wumpus {            fmt.Println("You smell something terrible nearby.")        }        switch ar {        case bat1, bat2:            if !bat {                fmt.Println("You hear a rustling.")                bat = true            }        case pit1, pit2:            if !pit {                fmt.Println("You feel a cold wind blowing from a nearby cavern.")                pit = true            }        }    }    fmt.Println()} func check(err error) {    if err != nil {        log.Fatal(err)    }} func plural(n int) string {    if n != 1 {        return "s"    }    return ""} func main() {    rand.Seed(time.Now().UnixNano())    player = 1    wumpus = rand.Intn(19) + 2 // 2 to 20    bat1 = rand.Intn(19) + 2    for {        bat2 = rand.Intn(19) + 2        if bat2 != bat1 {            break        }    }    for {        pit1 = rand.Intn(19) + 2        if pit1 != bat1 && pit1 != bat2 {            break        }    }    for {        pit2 = rand.Intn(19) + 2        if pit2 != bat1 && pit2 != bat2 && pit2 != pit1 {            break        }    }    scanner := bufio.NewScanner(os.Stdin)    for {        fmt.Printf("\nYou are in room %d with %d arrow%s left\n", player, arrows, plural(arrows))        adj := cave[player]        fmt.Printf("The adjacent rooms are %v\n", adj)        sense(adj)        var room int        for {            fmt.Print("Choose an adjacent room : ")            scanner.Scan()            room, _ = strconv.Atoi(scanner.Text())            if room != adj[0] && room != adj[1] && room != adj[2] {                fmt.Println("Invalid response, try again")            } else {                break            }        }        check(scanner.Err())        var action byte        for {            fmt.Print("Walk or shoot w/s : ")            scanner.Scan()            reply := strings.ToLower(scanner.Text())            if len(reply) != 1 || (len(reply) == 1 && reply[0] != 'w' && reply[0] != 's') {                fmt.Println("Invalid response, try again")            } else {                action = reply[0]                break            }        }        check(scanner.Err())        if action == 'w' {            player = room            switch player {            case wumpus:                fmt.Println("You have been eaten by the Wumpus and lost the game!")                return            case pit1, pit2:                fmt.Println("You have fallen down a bottomless pit and lost the game!")                return            case bat1, bat2:                for {                    room = rand.Intn(19) + 2                    if isEmpty(room) {                        fmt.Println("A bat has transported you to a random empty room")                        player = room                        break                    }                }            }        } else {            if room == wumpus {                fmt.Println("You have killed the Wumpus and won the game!!")                return            } else {                chance := rand.Intn(4) // 0 to 3                if chance > 0 {        // 75% probability                    wumpus = cave[wumpus][rand.Intn(3)]                    if player == wumpus {                        fmt.Println("You have been eaten by the Wumpus and lost the game!")                        return                    }                }            }            arrows--            if arrows == 0 {                fmt.Println("You have run out of arrows and lost the game!")                return            }        }    }}`

`import System.Randomimport System.IOimport Data.Listimport Data.Charimport Control.Monad -- Roomscave :: [[Int]]cave = [    [1,4,7],    [0,2,9],   [1,3,11],   [2,4,13],   [0,3,5],    [4,6,14],   [5,7,16],  [0,6,8],    [7,9,17],   [1,8,10],    [9,11,18],  [2,10,12], [11,13,19], [3,12,14],  [5,13,15],    [14,16,19], [6,15,17], [8,16,18],  [10,17,19], [12,15,18]] caveSize :: IntcaveSize = length cave -- Game statedata GameState = GameState {    wumpus :: Int,    player :: Int,    arrows :: Int,    pits :: [Int],    bats :: [Int]} -- Print the state of the gameinstance Show GameState where    show g = "You are in room " ++ show (player g) ++ ". " ++             "Adjacent rooms are: " ++ (intercalate ", " \$ map show adjs) ++             ".\nYou have " ++ show (arrows g) ++ " arrows.\n\n" ++             adjMsgs         where adjs    = cave!!player g              adj     = any (`elem` adjs) . (\$ g)              adjMsgs = unlines \$                  ["You smell something terrible nearby." | adj \$ pure.wumpus]               ++ ["You hear a rustling." | adj bats]               ++ ["You feel a cold wind blowing from a nearby cavern." | adj pits] -- Generate random initial stateinitGame :: StdGen -> GameStateinitGame g =     GameState {wumpus=w, player=p, arrows=5, pits=[p1,p2], bats=[b1,b2]}    where [w, p, p1, p2, b1, b2] = take 6 \$ nub \$ map (`mod` 20) \$ randoms g -- Move wumpus into adjacent free room (if possible)moveWumpus :: GameState -> StdGen -> GameStatemoveWumpus s g    | null freeAdj = s    | otherwise = s {wumpus = freeAdj!!(fst \$ randomR (0, length freeAdj-1) g)}    where freeAdj = [r | r <- cave!!wumpus s, not \$ elem r \$ pits s++bats s] -- Move player into random adjacent roommovePlayer :: GameState -> StdGen -> GameState movePlayer s g = s {player = (cave !! player s) !! (fst \$ randomR (0,2) g)} -- Move or shootdata Action = Move | Shoot | Quit deriving ShowinputAction :: IO ActioninputAction = do    putStr "M)ove, S)hoot or Q)uit? "    hFlush stdout    ch <- getChar    putStrLn ""     case toLower ch of        'm' -> return Move        's' -> return Shoot        'q' -> return Quit        _   -> putStrLn "Invalid command" >> inputAction -- Get room from current roominputDestination :: Int -> IO IntinputDestination cur = do    putStr "Where to? "    hFlush stdout    input <- getLine    case reads input of        []      -> err "Sorry?"        [(x,_)] -> if x `elem` (cave !! cur)                   then return x                   else err "Can't get there from here."  where    err x = putStrLn x >> inputDestination cur -- Input yes or noinputYesNo :: IO BoolinputYesNo = do    ch <- getChar    case toLower ch of        'n' -> putStrLn "" >> return False        'y' -> putStrLn "" >> return True        _   -> putStr (map chr [7,8]) >> inputYesNo -- See if anything has happened to the playerdata PlayerState = NoArrows | Bat | Pit | Wumpus | Alive deriving ShowplayerState :: GameState -> PlayerStateplayerState s | player s == wumpus s   = Wumpus              | player s `elem` bats s = Bat               | player s `elem` pits s = Pit              | arrows s == 0          = NoArrows              | otherwise              = Alive -- Game loopdata GameResult = Win | Lose | Stop deriving Showgame :: GameState -> IO GameResultgame s = case playerState s of    Wumpus   -> putStrLn "You find yourself face to face with the wumpus."             >> putStrLn "It eats you alive in one bite.\n"             >> return Lose    Pit      -> putStrLn "You fall into a deep pit. Death waits at the bottom.\n"             >> return Lose    Bat      -> putStrLn "You have walked into the lair of a giant bat."             >> putStrLn "It picks you up and deposits you outside.\n"             >> newStdGen >>= game . movePlayer s    NoArrows -> putStrLn "You notice you are out of arrows."             >> putStrLn "You hear a large beast approaching.\n"             >> return Lose    Alive    -> do        putStrLn ""         putStrLn \$ show s        action <- inputAction        case action of            Quit -> return Stop            _    -> do                dest <- inputDestination (player s)                case action of                    Move  -> game s {player = dest}                    Shoot -> shoot s dest -- Shoot at the wumpusshoot :: GameState -> Int -> IO GameResultshoot s tgt    | tgt == wumpus s = do        putStrLn "Congratulations! You shot the wumpus!\n"        return Win    | otherwise = do        let s'' = s { arrows = pred \$ arrows s }        putStrLn "That's a miss."        awake <- randomRIO (0,3::Int)        if awake /= 0 then do            putStrLn "The wumpus wakes from his slumber."            newStdGen >>= game . moveWumpus s''        else            game s'' -- Play a gameplayGame :: IO () playGame = do    result <- newStdGen >>= game . initGame     case result of        Stop -> return ()        _    -> do            case result of                Lose -> putStrLn "You have met your demise."                Win  -> putStrLn "You win!"            putStr "\nAnother game? (Y/N) "            inputYesNo >>= flip when playGame main :: IO ()main = do    hSetBuffering stdin NoBuffering    hSetBuffering stdout NoBuffering    putStrLn "*** HUNT THE WUMPUS ***"    putStrLn ""    playGame`

## IS-BASIC

`100 PROGRAM "Wumpus.bas"110 RANDOMIZE 120 NUMERIC RO(1 TO 20,1 TO 3),LO(1 TO 20),WPOS130 LET ARROWS=5:LET L=1140 CALL INIT150 DO 160   PRINT :PRINT "You are in room";L170   PRINT "Tunnels lead to ";RO(L,1);RO(L,2);RO(L,3)180   IF MON(1) THEN PRINT "You smell something terrible nearby."190   IF MON(2) OR MON(3) THEN PRINT "You hear a rustling."200   IF MON(4) OR MON(5) THEN PRINT "You feel a cold wind blowing from a nearby cavern."210   PRINT :PRINT "Shoot or move? (S-M)"220   DO 230     LET K\$=UCASE\$(INKEY\$)240   LOOP UNTIL K\$="S" OR K\$="M"250   IF K\$="M" THEN ! Move260     INPUT PROMPT "No. of rooms: ":I\$270     LET I=VAL(I\$)280     IF CHK(I) THEN290       LET L=I300     ELSE 310       PRINT "Not possibile."320     END IF 330   ELSE  ! Shoot340     INPUT PROMPT "Where? ":I\$350     LET I=VAL(I\$)360     IF CHK(I) THEN370       IF LO(I)=1 THEN380         PRINT "You kill the Monster Wumpus.":PRINT "You win.":EXIT DO390       ELSE 400         PRINT "Arrows aren't that crooked - Try another room."410         IF RND(4)<3 THEN420           PRINT "You woke the Wumpus and he moved."430           LET LO(WPOS)=0:LET WPOS=RO(WPOS,RND(2)+1):LET LO(WPOS)=1440         END IF 450         LET ARROWS=ARROWS-1460         IF ARROWS=0 THEN PRINT "You ran out of arrows.":EXIT DO470       END IF 480     ELSE 490       PRINT "Not possibile."500     END IF 510   END IF 520   SELECT CASE LO(L)530   CASE 1540     PRINT "You eaten by Wumpus.":EXIT DO550   CASE 2,3560     PRINT "A giant bat takes you in another room.":LET I=L570     DO 580       LET L=RND(19)+1590     LOOP UNTIL I<>L600   CASE ELSE610   END SELECT 620   IF LO(L)=4 OR LO(L)=5 THEN PRINT "You fall into a bottomless pit.":EXIT DO630 LOOP 640 DEF MON(X)=X=LO(RO(L,1)) OR X=LO(RO(L,2)) OR X=LO(RO(L,3))650 DEF CHK(X)=X=RO(L,1) OR X=RO(L,2) OR X=RO(L,3)660 DEF INIT670   TEXT 40:PRINT "Hunt the Wumpus";CHR\$(241)680   FOR I=1 TO 20 ! Create the cave690     LET LO(I)=0700     FOR J=1 TO 3710       READ RO(I,J)720     NEXT 730   NEXT 740   LET WPOS=RND(19)+2:LET LO(WPOS)=1750   FOR I=2 TO 5760     DO 770       LET T=RND(19)+2780     LOOP UNTIL LO(T)=0790     LET LO(T)=I800   NEXT 810 END DEF 820 DATA 2,6,5,3,8,1,4,10,2,5,2,3,1,14,4,15,1,7,17,6,8,7,2,9,18,8,10,9,3,11830 DATA 19,10,12,11,4,13,20,12,14,5,11,13,6,16,14,20,15,17,16,7,18,17,9,19,18,11,20,19,13,16`

## Julia

A translation from the original Basic, using the original Basic code and text at https://github.com/kingsawyer/wumpus/blob/master/wumpus.basic as a guide.

`const starttxt = """      ATTENTION ALL WUMPUS LOVERS!!!     THERE ARE NOW TWO ADDITIONS TO THE WUMPUS FAMILY     OF PROGRAMS.       WUMP2:  SOME DIFFERENT CAVE ARRANGEMENTS      WUMP3:  DIFFERENT HAZARDS """ const helptxt = """     WELCOME TO 'HUNT THE WUMPUS'      THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM     HAS 3 TUNNELS LEADING TO OTHER ROOMS. (LOOK AT A     DODECAHEDRON TO SEE HOW THIS WORKS-IF YOU DON'T KNOW     WHAT A DODECAHEDRON IS, ASK SOMEONE)          HAZARDS:     BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM         IF YOU GO THERE, YOU FALL INTO THE PIT (& LOSE!)     SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU         GO THERE, A BAT GRABS YOU AND TAKES YOU TO SOME OTHER         ROOM AT RANDOM. (WHICH MIGHT BE TROUBLESOME)          WUMPUS:     THE WUMPUS IS NOT BOTHERED BY THE HAZARDS (HE HAS SUCKER     FEET AND IS TOO BIG FOR A BAT TO LIFT).  USUALLY     HE IS ASLEEP. TWO THINGS WAKE HIM UP: YOUR ENTERING     HIS ROOM OR YOUR SHOOTING AN ARROW.         IF THE WUMPUS WAKES, HE MOVES (P=.75) ONE ROOM     OR STAYS STILL (P=.25). AFTER THAT, IF HE IS WHERE YOU     ARE, HE EATS YOU UP (& YOU LOSE!)          YOU:     EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW       MOVING: YOU CAN GO ONE ROOM (THRU ONE TUNNEL)       ARROWS: YOU HAVE 5 ARROWS. YOU LOSE WHEN YOU RUN OUT.       EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING       THE COMPUTER THE ROOM#S YOU WANT THE ARROW TO GO TO.       IF THE ARROW CAN'T GO THAT WAY (IE NO TUNNEL) IT MOVES       AT RANDOM TO THE NEXT ROOM.         IF THE ARROW HITS THE WUMPUS, YOU WIN.         IF THE ARROW HITS YOU, YOU LOSE.         WARNINGS:        WHEN YOU ARE ONE ROOM AWAY FROM WUMPUS OR HAZARD,        THE COMPUTER SAYS:     WUMPUS-  'I SMELL A WUMPUS'     BAT   -  'BATS NEARBY'     PIT   -  'I FEEL A DRAFT'  """ function queryprompt(query, choices, choicetxt="")    carr = map(x -> uppercase(strip(string(x))), collect(choices))    while true        print(query, " ", choicetxt == "" ? carr : choicetxt, ": ")        choice = uppercase(strip(readline(stdin)))        if choice in carr            return choice        end        println()    endend function wumpushunt(cheatmode = false)    println(starttxt)    arrows = 5    rooms = Vector{Vector{Int}}()    push!(rooms, [2,6,5], [3,8,1], [4,10,2], [5,2,3], [1,14,4], [15,1,7],        [17,6,8], [7,2,9], [18,8,10], [9,3,11], [19,10,12], [11,4,13],        [20,12,14], [5,11,13], [6,16,14], [20,15,17], [16,7,18],        [17,9,19], [18,11,20], [19,13,16])    roomcontents = shuffle(push!(fill("Empty", 15), "Bat", "Bat", "Pit", "Pit", "Wumpus"))    randnextroom(room) = rand(rooms[room])    newplayerroom(cr, range = 40) = (for i in 1:range cr = randnextroom(cr) end; cr)     function senseroom(p)        linkedrooms = rooms[p]        if cheatmode            println("linked rooms are \$(rooms[p]), which have \$(roomcontents[rooms[p][1]]),                 \$(roomcontents[rooms[p][2]]), \$(roomcontents[rooms[p][3]])")        end        if any(x -> roomcontents[x] == "Wumpus", linkedrooms)            println("I SMELL A WUMPUS!")        end        if any(x -> roomcontents[x] == "Pit", linkedrooms)            println("I FEEL A DRAFT")        end        if any(x -> roomcontents[x] == "Bat", linkedrooms)            println("BATS NEARBY!")        end    end     function arrowflight(arrowroom)        if roomcontents[arrowroom] == "Wumpus"            println("AHA! YOU GOT THE WUMPUS!")            return("win")        elseif any(x -> roomcontents[x] == "Wumpus", rooms[arrowroom])            numrooms = rand([0, 1, 2, 3])            if numrooms > 0                println("...OOPS! BUMPED A WUMPUS!")                wroom = rooms[arrowroom][findfirst(x -> roomcontents[x] == "Wumpus", rooms[arrowroom])]                for i in 1:3                    tmp = wroom                    wroom = rand(rooms[wroom])                    if wroom == playerroom                        println("TSK TSK TSK- WUMPUS GOT YOU!")                        return "lose"                    else                        roomcontents[tmp] = roomcontents[wroom]                        roomcontents[wroom] = "Wumpus"                    end                end            end        elseif arrowroom == playerroom            println("OUCH! ARROW GOT YOU!")            return "lose"        end        return ""    end     println("HUNT THE WUMPUS")    playerroom = 1    while true        playerroom = newplayerroom(playerroom)        if roomcontents[playerroom] == "Empty"            break        end    end    while arrows > 0        senseroom(playerroom)        println("YOU ARE IN ROOM \$playerroom. TUNNELS LEAD TO ", join(rooms[playerroom], ";"))        choice = queryprompt("SHOOT OR MOVE (H FOR HELP)", ["S", "M", "H"])        if choice == "M"            choice = queryprompt("WHERE TO", rooms[playerroom])            playerroom = parse(Int, choice)            if roomcontents[playerroom] == "Wumpus"                println("TSK TSK TSK- WUMPUS GOT YOU!")                return "lose"            elseif roomcontents[playerroom] == "Pit"                println("YYYIIIIEEEE . . . FELL IN PIT")                return "lose"            elseif roomcontents[playerroom] == "Bat"                senseroom(playerroom)                println("ZAP--SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!")                playerroom = newplayerroom(playerroom, 10)            end        elseif choice == "S"            distance = parse(Int, queryprompt("NO. OF ROOMS(1-5)", 1:5))            choices = zeros(Int, 5)            arrowroom = playerroom            for i in 1:distance                choices[i] = parse(Int, queryprompt("ROOM #", 1:20, "1-20"))                while i > 2 && choices[i] == choices[i-2]                    println("ARROWS AREN'T THAT CROOKED - TRY ANOTHER ROOM")                    choices[i] = parse(Int, queryprompt("ROOM #", 1:20, "1-20"))                end                arrowroom = choices[i]            end            arrowroom = playerroom            for rm in choices                if rm != 0                    if !(rm in rooms[arrowroom])                        rm = rand(rooms[arrowroom])                    end                    arrowroom = rm                    if (ret = arrowflight(arrowroom)) != ""                        return ret                    end                end            end            arrows -= 1            println("MISSED")        elseif choice == "H"            println(helptxt)        end    end    println("OUT OF ARROWS.\nHA HA HA - YOU LOSE!")    return "lose"end while true    result = wumpushunt()    println("Game over. You \$(result)!")    if queryprompt("Play again?", ["Y", "N"]) == "N"        break    endend `

## M2000 Interpreter

For Windows only (in Linux you hear nothing, using Wine 3.6): In Sense() you can change Print with Speech so you Hear your sense;

` Module WumpusGame {      Print "Game: Hunt The Wumpus"      Arrows=5      Dim Room(1 to 20)      Room(1)=(2,6,5),(3,8,1),(4,10,2),(5,2,3),(1,14,4)      Room(6)=(15,1,7),(17,6,8),(7,2,9),(18,8,10),(9,3,11)      Room(11)=(19,10,12),(11,4,13),(20,12,14),(5,11,13), (6,16,14)      Room(16)=(20,15,17),(16,7,18),(17,9,19),(18,11,20),(19,13,16)      Enum Things {EmptyRoom, Bat1, Bat2, Pit1, Pit2, Wumpus}      Dim Content(1 to 20)=EmptyRoom      i=each(Things,2)  ' from 2 to End      While i {            r=random(1,20)            if Content(r)<>EmptyRoom then restart            Content(r)=Eval(i)      }      WumpusPos=r      PlayerPos=-1      TranspotPlayer()      Done=False      \\ Help is statement but here used as variable      Help=False      While Arrows>0 And Not Done {            Sense()            Print "W- Walk, T - Throw Arrow, G - Give up or H for Help"            a\$=Ucase\$(Key\$)            If a\$="W" Then {                  Print "Choose Tunnel to Walk: 1, 2 or 3"                  r=Val("0"+Key\$)-1                  if r>=0 and r<=2 then {                        PlayerPos=Array(room(PlayerPos), r)                        Select Case Content(PlayerPos)                        Case Wumpus                        Eaten()                        Case Pit1, Pit2                        {                              Arrows=0                              Print "You fall to a bottomless pit;"                        }                        Case Bat1, Bat2                        {                              Print "A giant bat takes you in another room;"                              TranspotPlayer()                        }                        End Select                  }            } Else.if a\$="T" Then {                  Arrows--                  Print "Choose Tunnel to Throw Arrow: 1, 2  or 3"                        r=Val("0"+Key\$)-1                  if r>=0 and r<=2 then {                        i=room(PlayerPos)                        If Content(Array(i, r))=Wumpus then {                              Done=True                      } Else.if random(1,4)<4 then WakeWumpus()                  }                        } Else.if a\$="G" Then {                   Arrows=0            } Else.if a\$="H" Then Help~      }      If Done then Print "You kill the Monster Wumpus; You Win.": Exit      Print "You loose."       Sub TranspotPlayer()            local r=random(1,20)            While Content(r)<>EmptyRoom {r=random(1,20)}            PlayerPos=r      End Sub      Sub WakeWumpus()            local j=array(room(WumpusPos),random(0,2))            If content(j)=EmptyRoom Then {                  swap content(j), content(WumpusPos)                  WumpusPos=j                  If WumpusPos=PlayerPos then Eaten()            }      End Sub      Sub Eaten()            Arrows=0            Print "You eaten by Wumpus;"      End Sub      Sub Sense()            local k=Room(PlayerPos)            local j=each(k), Wumpus_near, bat_near, pit_near            If Help then Print "Player Room:";PlayerPos, "Wumpus Room:";WumpusPos            While j {                  If Help Then Print "Tunnel:";j^+1, "Room:";Array(j), "Content:";eval\$(content(array(j)))                  Select Case content(array(j))                  Case Bat1, Bat2                  bat_near=True                  Case Pit1, Pit2                  pit_near=True                  Case Wumpus                  Wumpus_near=True                  End Select            }            If Wumpus_near Then Print "You smell something terrible nearby."            If bat_near Then Print "You hear a rustling."            if pit_near Then Print "You feel a cold wind blowing from a nearby cavern."      End Sub    }WumpusGame  `

## MiniScript

`exits = [[1,4,7], [0,2,9], [1,3,11], [2,4,13], [0,3,5],  [4,6,14], [5,7,16], [0,6,8], [7,9,17], [1,8,10],  [9,11,18], [2,10,12], [11,13,19], [3,12,14], [5,13,15],  [14,16,19], [6,15,17], [8,16,18], [10,17,19], [12,15,18]]hazard = [null] * 20emptyRoom = function()	while true		room = floor(rnd * 20)		if not hazard[room] then return room	end whileend functionfor i in range(1, 2)	hazard[emptyRoom] = "bat"	hazard[emptyRoom] = "pit"end forhazard[emptyRoom] = "wumpus" print "*** HUNT THE WUMPUS ***"print "-----------------------"curRoom = emptyRoomarrows = 5 checkWumpus = function()	if hazard[curRoom] == "wumpus" then		print "You find yourself face to face with the wumpus."		print "It eats you whole."		print "GAME OVER"; exit	end if	end function while true	print "You are in room " + curRoom + "."	checkWumpus	for r in exits[curRoom]		if hazard[r] == "wumpus" then print "You smell something terrible nearby."		if hazard[r] == "bat" then print "You hear a rustling."		if hazard[r] == "pit" then print "You feel a cold wind blowing from a nearby cavern."	end for	print "Tunnels lead to: " + exits[curRoom].join(", ")	print "You have " + arrows + " arrows."; print	while true		m = input("M)ove, S)hoot, or Q)uit? ").lower		if m == "q" then exit		if m != "m" and m != "s" then continue		target = input("Which room? ").val		if exits[curRoom].indexOf(target) == null then			print "Cannot get there from here."		else if m == "m" then			curRoom = target			if hazard[curRoom] == "bat" then				print "You have entered the lair of a giant bat."				curRoom = emptyRoom				print "It picks you up and drops you in room " + curRoom + "."			else if hazard[curRoom] == "pit" then				print "The ground gives way beneath your feet."				print "You fall into a deep abyss."				print "GAME OVER"; exit			end if		else			arrows = arrows - 1			if hazard[target] == "wumpus" then				print "Congratulations!  You shot the wumpus!"				exit			end if			print "You missed."			if rnd < 0.75 then				print "The wumpus wakes from his slumber."				hazard[hazard.indexOf("wumpus")] = null				hazard[emptyRoom] = "wumpus"				checkWumpus			end if			if arrows == 0 then				print "As you grasp at your empty quiver, "				print "you hear a large beast approaching..."				hazard[curRoom] = "wumpus"				checkWumpus			end if		end if		break	end whileend while`

## Nim

Translation of: Go
`import random, strformat, strutils type Adjacent = array[3, int] const Cave: array[1..20, Adjacent] =    [ 1: [2, 3, 4],     2: [1, 5, 6],     3: [1, 7, 8],     4: [1, 9, 10],      5: [2, 9, 11],    6: [2, 7, 12],    7: [3, 6, 13],    8: [3, 10, 14],      9: [4, 5, 15],   10: [4, 8, 16],   11: [5, 12, 17],  12: [6, 11, 18],     13: [7, 14, 18],  14: [8, 13, 19],  15: [9, 16, 17],  16: [10, 15, 19],     17: [11, 20, 15], 18: [12, 13, 20], 19: [14, 16, 20], 20: [17, 18, 19]] type Game = object  player: int  wumpus: int  bat1: int  bat2: int  pit1: int  pit2: int  arrows: int  proc initGame(): Game =  result.player = 1  result.wumpus = rand(2..20)  result.bat1 = rand(2..20)  while true:    result.bat2 = rand(2..20)    if result.bat2 != result.bat1: break  while true:    result.pit1 = rand(2..20)    if result.pit1 notin [result.bat1, result.bat2]: break  while true:    result.pit2 = rand(2..20)    if result.pit2 notin [result.bat1, result.bat2, result.pit1]: break  result.arrows = 5  func isEmpty(game: Game; room: int): bool =  room notin [game.player, game.wumpus, game.bat1, game.bat2, game.pit1, game.pit2]   proc sense(game: Game; adj: Adjacent) =  var bat, pit = false  for ar in adj:    if ar == game.wumpus:      echo "You smell something terrible nearby."    if ar in [game.bat1, game.bat2]:      if not bat:        echo "You hear a rustling."        bat = true    elif ar in [game.pit1, game.pit2]:      if not pit:        echo "You feel a cold wind blowing from a nearby cavern."        pit = true  echo()  func plural(n: int): string =  if n > 1: "s" else: ""  proc play(game: var Game) =   while true:     echo &"\nYou are in room {game.player} with {game.arrows} arrow{plural(game.arrows)} left"    let adj = Cave[game.player]    echo "The adjacent rooms are ", adj.join(", ")    game.sense(adj)     var room: int    while true:      stdout.write "Choose an adjacent room: "      stdout.flushFile()      try:        room = stdin.readLine().parseInt()        if room notin adj:          raise newException(ValueError, "")        break      except ValueError:        echo "Invalid response, try again"      except EOFError:        quit "\nEnd of file encountered; quitting.", QuitFailure     var action: char    while true:      stdout.write "Walk or shoot (w/s): "      stdout.flushFile()      try:        let reply = stdin.readLine()        if reply.len != 1 or reply[0] notin ['w', 's']:          echo "Invalid response, try again"        action = reply[0]        break      except EOFError:        quit "\nEnd of file encountered; quitting.", QuitFailure     if action == 'w':      game.player = room      if game.player == game.wumpus:        echo "You have been eaten by the Wumpus and lost the game!"        return      if game.player in [game.pit1, game.pit2]:        echo "You have fallen down a bottomless pit and lost the game!"        return      if game.player in [game.bat1, game.bat2]:        while true:          room = rand(2..20)          if game.isEmpty(room):            echo "A bat has transported you to a random empty room"            game.player = room            break     else:      if room == game.wumpus:        echo "You have killed the Wumpus and won the game!!"        return      let chance = rand(3)      if chance > 0:        game.wumpus = Cave[game.wumpus].sample()        if game.player == game.wumpus:          echo "You have been eaten by the Wumpus and lost the game!"          return      dec game.arrows      if game.arrows == 0:        echo "You have run out of arrows and lost the game!"        return  randomize()var game = initGame()game.play()`
Output:
```You are in room 1 with 5 arrows left
The adjacent rooms are 2, 3, 4
You hear a rustling.

Walk or shoot (w/s): w

You are in room 2 with 5 arrows left
The adjacent rooms are 1, 5, 6

Walk or shoot (w/s): w

You are in room 5 with 5 arrows left
The adjacent rooms are 2, 9, 11

Walk or shoot (w/s): w

You are in room 9 with 5 arrows left
The adjacent rooms are 4, 5, 15
You smell something terrible nearby.

Walk or shoot (w/s): s
You have killed the Wumpus and won the game!!```

## Perl

Besides running in a terminal, it also can run under xinetd.

`#!/usr/bin/perl use strict; # see https://rosettacode.org/wiki/Hunt_the_Wumpususe warnings;use List::Util qw( shuffle );\$| = 1; my %tunnels = qw(A BKT B ACL C BDM D CEN E DFO F EGP G FHQ H GIR I HJS  J IKT K AJL L BKM M CLN N DMO O ENP P FOQ Q GPR R HQS S IRT T AJS);my (\$you, \$wumpus, \$bat1, \$bat2, \$pit1, \$pit2) = shuffle keys %tunnels;my \$arrows = 5;print "\nTo shoot, enter a 's' and upper case letter of the desired tunnel.To move, just enter the upper case letter of the desired tunnel.\n"; while( 1 )  {  my @adj = split //, my \$adj = \$tunnels{\$you};  print "\nYou are in room \$you and see three tunnels: @adj\n";  \$adj =~ /\$bat1|\$bat2/ and print "You hear a rustling.\n";  \$adj =~ /\$pit1|\$pit2/ and    print "You feel a cold wind blowing from a nearby cavern.\n";  \$adj =~ \$wumpus and print "You smell something terrible nearby.\n";  print "(m)ove or (s)hoot (tunnel) : ";  defined(\$_ = <>) or exit;  if( /s.*([\$adj])/ ) # shoot    {    \$1 eq \$wumpus and exit !print "\nYou killed the Wumpus and won the game.\n";    \$wumpus = substr \$wumpus . \$tunnels{\$wumpus}, rand 4, 1;    \$wumpus eq \$you and die "\nYou were eaten by a Wumpus and lost the game.\n";    --\$arrows or die "\nYou ran out of arrows and lost the game.\n";    }  elsif( /([\$adj])/ ) # move    {    \$you = \$1;    \$wumpus eq \$you and die "\nYou were eaten by a Wumpus and lost the game.\n";    "\$pit1\$pit2" =~ \$you and      die "\nYou fell into a bottomless pit and lost the game.\n";    "\$bat1\$bat2" =~ \$you and ((\$you) = shuffle      grep !/\$you|\$wumpus|\$pit1|\$pit2|\$bat1|\$bat2/, keys %tunnels),      print "\nA giant bat has carried you to room \$you.\n";    }  else { print "I don't understand :(\n"; }  }`

## Prolog

Prolog package available here:

` /** * Simple text based dungeon game in Prolog. * * Warranty & Liability * To the extent permitted by applicable law and unless explicitly * otherwise agreed upon, XLOG Technologies GmbH makes no warranties * regarding the provided information. XLOG Technologies GmbH assumes * no liability that any problems might be solved with the information * provided by XLOG Technologies GmbH. * * Rights & License * All industrial property rights regarding the information - copyright * and patent rights in particular - are the sole property of XLOG * Technologies GmbH. If the company was not the originator of some * excerpts, XLOG Technologies GmbH has at least obtained the right to * reproduce, change and translate the information. * * Reproduction is restricted to the whole unaltered document. Reproduction * of the information is only allowed for non-commercial uses. Selling, * giving away or letting of the execution of the library is prohibited. * The library can be distributed as part of your applications and libraries * for execution provided this comment remains unchanged. * * Restrictions * Only to be distributed with programs that add significant and primary * functionality to the library. Not to be distributed with additional * software intended to replace any components of the library. * * Trademarks * Jekejeke is a registered trademark of XLOG Technologies GmbH. */ /** * Obtained rights, copyright notice of BASIC version found * in The Best of Creative Computing Volume 1 (published 1976) * https://www.atariarchives.org/bcc1/showpage.php?page=247 * and that we translated to Prolog. * * 0010  REM- HUNT THE WUMPUS * 0015  REM:  BY GREGORY YOB * * Game must have been create before, we assume 1972 since * the German Wikipedia mentions this date. The Englis Wikipedia * refers probably to a TI-99/4A version from 1973. */ :- module(wumpus, [wumpus/0]). :- use_module(console).:- use_module(library(advanced/arith)).:- use_module(library(basic/lists)).:- use_module(library(basic/random)). % wumpuswumpus :- preamble,   locate(L),   play(L). % originally: 0350  REM-SET# ARROWS% play(+List)play(L) :-   write('HUNT THE WUMPUS'), nl,   play(L, L, 5). % 0400  REM-MOVE OR SHOOT% play(+List, +List, +Integer)play(M, L, A) :-   location(L),   choose(O),   (  O = 2   -> move(L, H),      check(H, R, F),      B = A   ;  rooms(N),      path(N, [], P),      shoot(P, L, A, R, B, F)),   result(F, M, R, B). % result(+Integer, +List, +List, +Integer)result(0, M, L, A) :- !,   play(M, L, A).result(F, M, _, _) :-   (  F = -1   -> write('HA HA HA - YOU LOSE!'), nl   ;  write('HEE HEE HEE - THE WUMPUS''LL GETCHA NEXT TIME!!'), nl),   write('SAME SET-UP (Y-N)? '), flush_output,   read_line(I),   (  I \== 'Y'   -> locate(L)   ;  L = M),   play(L). % originally: 2500  REM-CHOOSE OPTION% choose(-Integer)choose(O) :- repeat,   write('SHOOT OR MOVE (S-M)? '), flush_output,   read_line(I),   (  'S' = I   -> O = 1   ;  'M' = I   -> O = 2; fail), !. /************************************************************//* Move                                                     *//************************************************************/ % originally: 4000  REM- MOVE ROUTINE% move(+List, -List)move([X|L], [P|L]) :- repeat,   write('WHERE TO? '), flush_output,   read_line(H),   atom_number(H, P),   1 =< P,   P =< 20,   (  edge(X, P) -> true   ;  P = X -> true   ;  write('NOT POSSIBLE - '), fail), !. % originally: 4120  REM-CHECK FOR HAZARDS% check(+List, -List, -Integer)check([X,Y|L], R, F) :-   X = Y, !,   write('...OOPS! BUMPED A WUMPUS!'), nl,   bump([X,Y|L], R, F).check([X,_,Z,T,_,_], _, -1) :-   (  X = Z   ;  X = T), !,   write('YYYIIIIEEEE . . . FELL IN PIT'), nl.check([X,Y,Z,T,U,V], L, F) :-   (  X = U   ;  X = V), !,   write('ZAP--SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!'), nl,   fna(P),   check([P,Y,Z,T,U,V], L, F).check(L, L, 0). % originally: 3370  REM-MOVE WUMPUS ROUTINE% bump(+List, -List, -Integer)bump([X,Y|L], [X,P|L], F) :-   fnc(C),   (  C = 4   -> P = Y   ;  findall(P, edge(Y, P), H),      nth1(C, H, P)),   (  X = P   -> write('TSK TSK TSK- WUMPUS GOT YOU!'), nl,      F = -1   ;  F = 0). /************************************************************//* Shoot                                                    *//************************************************************/ % shoot(+List, +List, +Integer, -List, -Integer, -Integer)shoot(P, [X|L], A, R, B, G) :-   arrow(P, X, [X|L], F),   missed(F, [X|L], A, R, B, G). % missed(+Integer, +List, +Integer, -List, -Integer, -Integer)missed(0, L, A, R, B, F) :- !,   write('MISSED'), nl,   bump(L, R, G),   ammo(G, A, B, F).missed(F, L, A, L, A, F). % originally: 3250  REM-AMMO CHECK% ammo(+Integer, +Integer, -Integer, -Integer)ammo(0, A, B, F) :- !,   B is A-1,   (  B = 0   -> F = -1   ;  F = 0).ammo(F, A, A, F). % originally: 3120  REM-SHOOT ARROW% arrow(+List, +Integer, +List, -Integer)arrow([], _, _, 0).arrow([Y|P], X, L, F) :-   follow(X, Y, Z),   hit(Z, L, P, F). % follow(+Integer, +Integer, -Integer)follow(X, Y, Z) :-   edge(X, Y), !,   Z = Y.follow(X, _, Z) :-   fnb(C),   findall(Z, edge(X, Z), H),   nth1(C, H, Z). % originally: 3290  REM-SEE IF ARROW IS AT L(1) OR L(2)% hit(+Integer, +List, +List, -Integer)hit(Z, [_,Y|_], _, 1) :-   Z = Y, !,   write('AHA! YOU GOT THE WUMPUS!'), nl.hit(Z, [X|_], _, -1) :-   Z = X, !,   write('OUCH! ARROW GOT YOU!'), nl.hit(Z, L, P, F) :-   arrow(P, Z, L, F). % originally: 3020  REM-PATH OF ARROW% rooms(-Integer)rooms(N) :- repeat,   write('NO. OF ROOMS(1-5)? '), flush_output,   read_line(H),   atom_number(H, N),   1 =< N,   N =< 5, !. % path(+Integer, +List, -List)path(0, _, []) :- !.path(N, L, [P|R]) :- repeat,   write('ROOM #? '), flush_output,   read_line(H),   atom_number(H, P),   (  L = [_,Q|_],      Q = P   -> write('ARROWS AREN''T THAT CROOKED - TRY ANOTHER ROOM'), nl, fail; true), !,   M is N-1,   path(M, [P|L], R). /************************************************************//* Dungeon                                                  *//************************************************************/ % originally: 2000  REM-PRINT LOCATION & HAZARD WARNINGS% location(+List)location([X,Y,Z,T,U,V]) :-   (  edge(X, Y)   -> write('I SMELL A WUMPUS!'), nl; true),   (  (  edge(X, Z)      ;  edge(X, T))   -> write('I FEEL A DRAFT'), nl; true),   (  (  edge(X, U)      ;  edge(X, V))   -> write('BATS NEARBY'), nl; true),   write('YOU ARE IN ROOM '),   write(X), nl,   write('TUNNELS LEAD TO'),   (  edge(X, R),      write(' '),      write(R), fail; true), nl. % originally: 0200  REM-LOCATE L ARRAY ITEMS% originally: 0210  REM-1-YOU,2-WUMPUS,3&4-PITS,5&6-BATS% locate(-List)locate(L) :-   length(L, 6), repeat,   maplist(fna, L),   \+ (  append(R, [X|_], L),         member(X, R)), !. % fna(-Integer)fna(X) :-   X is random(20)+1.% fnb(-Integer)fnb(X) :-   X is random(3)+1.% fnc(-Integer)fnc(X) :-   X is random(4)+1. % Originally: 0068  REM- SET UP CAVE (DODECAHEDRAL NODE LIST)% edge(-Integer, -Integer)edge(1, 2).edge(1, 5).edge(1, 8).edge(2, 1).edge(2, 3).edge(2, 10).edge(3, 2).edge(3, 4).edge(3, 12).edge(4, 3).edge(4, 5).edge(4, 14).edge(5, 1).edge(5, 4).edge(5, 6).edge(6, 5).edge(6, 7).edge(6, 15).edge(7, 6).edge(7, 8).edge(7, 17).edge(8, 1).edge(8, 7).edge(8, 9).edge(9, 8).edge(9, 10).edge(9, 18).edge(10, 2).edge(10, 9).edge(10, 11).edge(11, 10).edge(11, 12).edge(11, 19).edge(12, 3).edge(12, 11).edge(12, 13).edge(13, 12).edge(13, 14).edge(13, 20).edge(14, 4).edge(14, 13).edge(14, 15).edge(15, 6).edge(15, 14).edge(15, 16).edge(16, 15).edge(16, 17).edge(16, 20).edge(17, 7).edge(17, 16).edge(17, 18).edge(18, 9).edge(18, 17).edge(18, 19).edge(19, 11).edge(19, 18).edge(19, 20).edge(20, 13).edge(20, 16).edge(20, 19). /************************************************************//* Instructions                                             *//************************************************************/ % Originally: 1000  REM-INSTRUCTIONS% preamblepreamble :-   write('INSTRUCTIONS (Y-N)? '), flush_output,   read_line(I),   (  I \== 'N' -> instructions; true). % instructionsinstructions :-   write('WELCOME TO ''HUNT THE WUMPUS'''), nl,   write('  THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM'), nl,   write('HAS 3 TUNNELS LEADING TO OTHER ROOMS. (LOOK AT A'), nl,   write('DODECAHEDRON TO SEE HOW THIS WORKS-IF YOU DON''T KNOW'), nl,   write('WHAT A DODECAHEDRON IS, ASK SOMEONE)'), nl, nl,   write('     HAZARDS:'), nl,   write(' BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM'), nl,   write('     IF YOU GO THERE, YOU FALL INTO THE PIT (& LOSE!)'), nl,   write(' SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU'), nl,   write('     GO THERE, A BAT GRABS YOU AND TAKES YOU TO SOME OTHER'), nl,   write('     ROOM AT RANDOM. (WHICH MIGHT BE TROUBLESOME)'), nl, nl,   write('     WUMPUS:'), nl,   write(' THE WUMPUS IS NOT BOTHERED BY THE HAZARDS (HE HAS SUCKER'), nl,   write(' FEET AND IS TOO BIG FOR A BAT TO LIFT).  USUALLY'), nl,   write(' HE IS ASLEEP. TWO THINGS WAKE HIM UP: YOUR ENTERING'), nl,   write(' HIS ROOM OR YOUR SHOOTING AN ARROW.'), nl,   write('     IF THE WUMPUS WAKES, HE MOVES (P=.75) ONE ROOM'), nl,   write(' OR STAYS STILL (P=.25). AFTER THAT, IF HE IS WHERE YOU'), nl,   write(' ARE, HE EATS YOU UP (& YOU LOSE!)'), nl, nl,   write('     YOU:'), nl,   write(' EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW'), nl,   write('   MOVING: YOU CAN GO ONE ROOM (THRU ONE TUNNEL)'), nl,   write('   ARROWS: YOU HAVE 5 ARROWS. YOU LOSE WHEN YOU RUN OUT.'), nl,   write('   EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING'), nl,   write('   THE COMPUTER THE ROOM#S YOU WANT THE ARROW TO GO TO.'), nl,   write('   IF THE ARROW CAN''T GO THAT WAY (IE NO TUNNEL) IT MOVES'), nl,   write('   AT RAMDOM TO THE NEXT ROOM.'), nl,   write('     IF THE ARROW HITS THE WUMPUS, YOU WIN.'), nl,   write('     IF THE ARROW HITS YOU, YOU LOSE.'), nl, nl,   write('    WARNINGS:'), nl,   write('     WHEN YOU ARE ONE ROOM AWAY FROM WUMPUS OR HAZARD,'), nl,   write('    THE COMPUTER SAYS:'), nl,   write(' WUMPUS-  ''I SMELL A WUMPUS'''), nl,   write(' BAT   -  ''BATS NEARBY'''), nl,write(' PIT   -  ''I FEEL A DRAFT'''), nl, nl. `

## Python

This implementation of "Hunt the Wumpus" follows is based on the rules of the original game (see discussion page for more information). It uses python 3 syntax and the standard library random.

` import random class WumpusGame(object):  	def __init__(self, edges=[]): 		# Create arbitrary caves from a list of edges (see the end of the script for example).		if edges:			cave = {}			N = max([edges[i][0] for i in range(len(edges))])			for i in range(N):				exits = [edge[1] for edge in edges if edge[0] == i]				cave[i] = exits 		# If no edges are specified, play in the standard cave: a dodecahedron.		else:			cave = {1: [2,3,4], 2: [1,5,6], 3: [1,7,8], 4: [1,9,10], 5:[2,9,11],				6: [2,7,12], 7: [3,6,13], 8: [3,10,14], 9: [4,5,15], 10: [4,8,16], 				11: [5,12,17], 12: [6,11,18], 13: [7,14,18], 14: [8,13,19], 				15: [9,16,17], 16: [10,15,19], 17: [11,20,15], 18: [12,13,20], 				19: [14,16,20], 20: [17,18,19]} 		self.cave = cave 		self.threats = {} 		self.arrows = 5 		self.arrow_travel_distance = 5		# As in the original game. I don't like this choice:											# a bow should not cover a whole cave.		self.player_pos = -1  	"""	HELPER: These methods wrap processes that are useful or called often.	"""  	def get_safe_rooms(self):		""" Returns a list containing all numbers of rooms that			do not contain any threats		"""		return list(set(self.cave.keys()).difference(self.threats.keys()))  	def populate_cave(self):		""" Drop player and threats into random rooms in the cave.		"""		for threat in ['bat', 'bat', 'pit', 'pit', 'wumpus']:			pos = random.choice(self.get_safe_rooms())			self.threats[pos] = threat		self.player_pos = random.choice(self.get_safe_rooms())  	def breadth_first_search(self, source, target, max_depth=5):		""" The game board (whether custom or standard dodecahedron) is an undirected graph. 			The rooms are the vertices and the tunnels are the edges of this graph. To find 			out whether a target room can be reached from a source room using a given amount 			of tunnels, one can do a breadth first search on the underlying undirected graph. 			BFS works like this: start with the source vertex, maybe it is already the target? 			If not, then go a level deeper and find out, if one of the children (also called 			successors) of the source vertex is the wanted target. If not, then for each child, 			go a level deeper and find out if one of the grand-children is the wanted target. 			If not, then for each grand-child go a level deeper and so on.  			The following is a recursive implementation of BFS. You will not find any loops 			(for, while). Instead you manage two lists. The first one ('stack') contains all 			the vertices of the current depth-level (e.g. all grand children). The second 			('visited') contains all vertices that you already checked. Now there are three 			possibilites: Either stack is empty, then all vertices have been checked unsuccessfully;			or the target vertex is a member of the stack, then you are happy; or the target is 			not a member of the stack, but there are still some vertices that you did not visit, 			then you append to the stack, all successors of the members of the stack and the old 			stack now belongs to the visited vertices.		"""		# Set up some initial values.		graph = self.cave		depth = 0 		def search(stack, visited, target, depth):			if stack == []:					# The whole graph was searched, but target was not found.				return False, -1			if target in stack:				return True, depth			visited = visited + stack			stack = list(set([graph[v][i] for v in stack for i in range(len(graph[v]))]).difference(visited))			depth += 1			if depth > max_depth:			# Target is too far away from the source.				return False, depth			else:							# Visit all successors of vertices in the stack.				return search(stack, visited, target, depth) 		return search([source], [], target, depth)  	"""	INPUT / OUTPUT: The player interacts with the game.	"""  	def print_warning(self, threat):		""" Called when entering a new room. Shows threats in adjacent rooms.		"""		if threat == 'bat':			print("You hear a rustling.")		elif threat == 'pit':			print("You feel a cold wind blowing from a nearby cavern.")		elif threat == 'wumpus':			print("You smell something terrible nearby.")  	def get_players_input(self):		""" Queries input until valid input is given.		"""		while 1:								# Query the action. 			inpt = input("Shoot or move (S-M)? ")			try:								# Ensure that the player choses a valid action (shoot or move)				mode = str(inpt).lower()				assert mode in ['s', 'm', 'q']				break			except (ValueError, AssertionError):				print("This is not a valid action: pick 'S' to shoot and 'M' to move.") 		if mode == 'q':							# I added a 'quit-button' for convenience.			return 'q', 0 		while 1:								# Query the target of the action. 			inpt = input("Where to? ")			try:								# Ensure that the chosen target is convertable to an integer.				target = int(inpt)			except ValueError:				print("This is not even a real number.")				continue						# Restart the while loop, to get a valid integer as target. 			if mode == 'm':				try:							# When walking, the target must be adjacent to the current room.					assert target in self.cave[self.player_pos]					break				except AssertionError:					print("You cannot walk that far. Please use one of the tunnels.") 			elif mode == 's':				try:							# When shooting, the target must be reachable within 5 tunnels.					bfs = self.breadth_first_search(self.player_pos, target)					assert bfs[0] == True					break				except AssertionError:					if bfs[1] == -1: 			# The target is outside cave.						print("There is no room with this number in the cave. Your arrow travels randomly.")						target = random.choice(self.cave.keys())					if bfs[1] > self.arrow_travel_distance:				# The target is too far.						print("Arrows aren't that croocked.") 		return mode, target  	"""	CORE / GAME LOGIC	"""  	def enter_room(self, room_number):		""" Controls the process of entering a new room.		"""			print("Entering room {}...".format(room_number))		# Maybe a threat waits in the new room.			if self.threats.get(room_number) == 'bat':			# The bat teleports the player to random empty room			print("You encounter a bat, it transports you to a random empty room.")			new_pos = random.choice(self.get_safe_rooms())			return self.enter_room(new_pos)		elif self.threats.get(room_number) == 'wumpus':			print("Wumpus eats you.")			return -1		elif self.threats.get(room_number) == 'pit':			print("You fall into a pit.")			return -1 		# The room is safe; collect information about adjacent rooms.		for i in self.cave[room_number]:			self.print_warning(self.threats.get(i)) 		# Only if nothing else happens, the player enters the room of his choice.		return room_number  	def shoot_room(self, room_number):		""" Controls the process of shooting in a room.		"""		print("Shooting an arrow into room {}...".format(room_number))		# Fire an arrow and see if something is hit by it.		self.arrows -= 1		threat = self.threats.get(room_number)		if threat in ['bat', 'wumpus']:			del self.threats[room_number]					if threat == 'wumpus':				print("Hurra, you killed the wumpus!")				return -1			elif threat == 'bat':				print("You killed a bat.")		elif threat in ['pit', None]:			print("This arrow is lost.") 		# If this was your last arrow and it did not hit the wumpus...		if self.arrows < 1:		# This (or the updating of self.arrows) seems to be broken...			print("Your quiver is empty.")			return -1 		#  If you shoot into another room, the Wumpus has a 75% of chance of waking up and moving into an adjacent room.		if random.random() < 0.75:			#print("DEBUG: Wumpus moved.")			for room_number, threat in self.threats.items():				if threat == 'wumpus':					wumpus_pos = room_number								new_pos = random.choice(list(set(self.cave[wumpus_pos]).difference(self.threats.keys())))			del self.threats[room_number]			self.threats[new_pos] = 'wumpus'						if new_pos == self.player_pos: # Wumpus entered players room.				print("Wumpus enters your room and eats you!")				return -1 		return self.player_pos  	def gameloop(self): 		print("HUNT THE WUMPUS")		print("===============")		print()		self.populate_cave()		self.enter_room(self.player_pos) 		while 1: 			#print("DEBUG: Your quiver holds {} arrows.".format(self.arrows))						#print("DEBUG: Rooms with no threats are: {}.".format(self.get_safe_rooms()))						#print("DEBUG: Threats are located in the following rooms: {}".format(self.threats)) 			print("You are in room {}.".format(self.player_pos), end=" ")			print("Tunnels lead to:  {0}  {1}  {2}".format(*self.cave[self.player_pos]))  			inpt = self.get_players_input()		# Player choses move or shoot.			print()								# Visual separation of rounds.			if inpt[0] == 'm':					# Move.				target = inpt[1] 				self.player_pos = self.enter_room(target)			elif inpt[0] == 's':				# Shoot.				target = inpt[1]				self.player_pos = self.shoot_room(target)			elif inpt[0] == 'q':				# Quit.				self.player_pos = -1 			if self.player_pos == -1:			# E.g. Deadly threat, quiver empty, etc.				break							# If any of the game loosing conditions are True,												# then player_pos will be -1.  		print()		print("Game over!")	  if __name__ == '__main__':							# Only executed if you start this script as the main script,	# i.e. you enter 'python path/to/wumpus.py' in a terminal.	# Assuming you saved the script in the directory 'path/to' 	# and named it 'wumpus.py'. 	# TODO: In the original game you can replay a dungeon (same positions of you and the threats) 	WG = WumpusGame()	WG.gameloop()  `

Example run (on a windows system):

` D:\Workspace\rosettacode>python wumpus.pyHUNT THE WUMPUS=============== Entering room 7...You smell something terrible nearby.You are in room 7. Tunnels lead to:  3  6  13Shoot or move (S-M)? mWhere to? 3 Entering room 3...Wumpus eats you. Game over! `

To create an example for a valid edge list, navigate to the folder where you saved wumpus.py, open up a python interactive shell and do:

` >>> import wumpus>>> WG = wumpus.WumpusGame()>>> edges = [[i, WG.cave[i][j]] for i in WG.cave.keys() for j in range(len(WG.cave[i]))]>>> print edges[[1,2], [1,3], [1,4], [2,1], [2,5], [2,6], [3,1], ...]  `

## Racket

` #lang racket ; Hunt the Wumpus (require racket/random) (struct game-state (labyrinth                    player-location                    number-of-arrows                    wumpus-location                    bat-locations                    pit-locations) #:mutable #:transparent) ; The labyrinth-data list contains 20 lists that hold the information for; each rooms connections to other rooms in the labyrinth.; e.g. (1 2 5 8) shows that room 1 has connections to rooms 2, 5 and 8. (define labyrinth-data '(                         (1 2 5 8)                         (2 1 3 10)                         (3 2 4 12)                         (4 3 5 14)                         (5 1 4 6)                         (6 5 7 15)                         (7 6 8 17)                         (8 1 7 9)                         (9 8 10 18)                         (10 2 9 11)                         (11 10 12 19)                         (12 3 11 13)                         (13 12 14 20)                         (14 4 13 15)                         (15 6 14 16)                         (16 15 17 20)                         (17 7 16 18)                         (18 9 17 19)                         (19 11 18 20)                         (20 13 16 19))) (define example-game-state (game-state labyrinth-data                                       1                                       5                                       2                                       '(3 4)                                       '(5 6))) (define (new-game-state)  (let ([ngs (game-state labyrinth-data 1 5 1 '(1 1) '(1 1))])    (set-game-state-wumpus-location! ngs (safe-empty-room ngs))    (set-game-state-bat-locations! ngs (list (safe-empty-room ngs)))    (set-game-state-bat-locations! ngs (cons (safe-empty-room ngs)                                             (game-state-bat-locations ngs)))    (set-game-state-pit-locations! ngs (list (safe-empty-room ngs)))    (set-game-state-pit-locations! ngs (cons (safe-empty-room ngs)                                             (game-state-pit-locations ngs)))    ngs)) (define (move-player room current-game-state)  (set-game-state-player-location! current-game-state room)) (define (disturb-wumpus current-game-state)  (if (<= (random) 0.75)      (set-game-state-wumpus-location! current-game-state                                       (room-for-wumpus-move current-game-state))      #f)) (define (room-for-wumpus-move current-game-state)  (let ([choices (append (neighbours                          (game-state-wumpus-location current-game-state)                          current-game-state)                         (list (game-state-wumpus-location current-game-state)))])    (findf (Î» (room) (and (not (pit-room? room current-game-state))                          (not (bat-room? room current-game-state)))) choices))) (define (lost? current-game-state)  (or (= (game-state-player-location current-game-state) (game-state-wumpus-location current-game-state))      (member (game-state-player-location current-game-state)              (game-state-pit-locations current-game-state))      (= 0 (game-state-number-of-arrows current-game-state)))) (define (won? current-game-state)  (= 0 (game-state-wumpus-location current-game-state))) (define (shoot-arrow room current-game-state)  (if (= room (game-state-wumpus-location current-game-state))      (set-game-state-wumpus-location! current-game-state 0)      (disturb-wumpus current-game-state))  (set-game-state-number-of-arrows! current-game-state                                    (- (game-state-number-of-arrows current-game-state) 1))) (define (move-player-with-bats current-game-state)  (set-game-state-player-location! current-game-state (safe-empty-room current-game-state))) (define (safe-empty-room current-game-state)  (let ([room (+ 1 (random 20))])    (if (or (= room (game-state-wumpus-location current-game-state))            (= room (game-state-player-location current-game-state))            (member room (game-state-bat-locations current-game-state))            (member room (game-state-pit-locations current-game-state)))        (safe-empty-room current-game-state)        room))) (define (find-room room-number current-game-state)  (assoc room-number (game-state-labyrinth current-game-state))) (define (neighbours room-number current-game-state)  (rest (find-room room-number current-game-state))) (define (pit-room? room current-game-state)  (member room (game-state-pit-locations current-game-state))) (define (bat-room? room current-game-state)  (member room (game-state-bat-locations current-game-state))) (define (nearby? room-number entity-room-number current-game-state)  (member entity-room-number (neighbours room-number current-game-state))) (define (any-of-in? of-lst in-lst)  (for/or ([item of-lst])    (member item in-lst))) (define (pit-nearby? room current-game-state)  (any-of-in? (neighbours room current-game-state) (game-state-pit-locations current-game-state))) (define (bat-nearby? room current-game-state)  (any-of-in? (neighbours room current-game-state) (game-state-bat-locations current-game-state))) (define (wumpus-nearby? room current-game-state)  (member (game-state-wumpus-location current-game-state) (neighbours room current-game-state))) (define (resolve-command str-list current-game-state)  (let ([command (string-upcase (first str-list))]        [room (string->number (second str-list))])    (if (nearby? (game-state-player-location current-game-state)                 room current-game-state)        (cond [(equal? command "W") (if (bat-room? room current-game-state)                                        (display-bat-attack current-game-state)                                        (move-player room current-game-state))]              [(equal? command "S") (shoot-arrow room current-game-state)]              [else (displayln "Unknown command")])        (displayln "You cannot move or shoot there!")))) (define (display-bat-attack current-game-state)  (move-player-with-bats current-game-state)  (display "Argh! A Giant Bat has carried you to room ")  (displayln (game-state-player-location current-game-state))) (define (display-hazards current-game-state)  (when (wumpus-nearby? (game-state-player-location current-game-state) current-game-state)    (displayln "You smell something nearby."))  (when (bat-nearby? (game-state-player-location current-game-state) current-game-state)    (displayln "You hear a rustling."))  (when (pit-nearby? (game-state-player-location current-game-state) current-game-state)    (displayln "You feel a cold wind blowing from a nearby cavern."))) (define (display-room-numbers lst)  (display (string-join (map number->string lst) ", " #:before-last " or " #:after-last "."))) (define (display-lost-message current-game-state)  (cond [(= (game-state-player-location current-game-state)            (game-state-wumpus-location current-game-state)) (displayln "The Wumpus has eaten you!")]        [(member (game-state-player-location current-game-state)                 (game-state-pit-locations current-game-state)) (displayln "You have fallen down a pit!")]        [(= 0 (game-state-number-of-arrows current-game-state)) (displayln "You have run out of arrows.")]        [else (displayln "Unknown loss")])) (define (display-won-message current-game-state)  (displayln "Congratulations, you have slain the Wumpus!")) (define (display-information current-game-state)  (display "You can (W)alk or (S)hoot to rooms ")  (display-room-numbers (neighbours (game-state-player-location current-game-state) current-game-state))  (newline)  (display "You have ")  (display (game-state-number-of-arrows current-game-state))  (displayln " arrows left.")  (display-hazards current-game-state)) (define (debug-game-state current-game-state)  (display "    Player Location : ")  (displayln (game-state-player-location current-game-state))  (display "    Wumpus Location : ")  (displayln (game-state-wumpus-location current-game-state))  (display "    Bat Locations : ")  (displayln (game-state-bat-locations current-game-state))  (display "    Pit Locations : ")  (displayln (game-state-pit-locations current-game-state))) (define (game-loop current-game-state)  ;(debug-game-state current-game-state)  (display-information current-game-state)  (resolve-command (string-split (read-line)) current-game-state)  (cond [(lost? current-game-state) (display-lost-message current-game-state)]        [(won? current-game-state) (display-won-message current-game-state)]        [else (game-loop current-game-state)])) (define (start-game)  (let ([current-game-state (new-game-state)])    (game-loop current-game-state))) `
` Start the game with (start-game) Then walk to a room with W 2 Or shoot into a room with S 2 `

## Raku

(formerly Perl 6) See Hunt_The_Wumpus/Raku

## Red

` Red [	Title:	 "Hunt the Wumpus"	Author:  "Gregg Irwin"	Version: 1.0.2	Comment: {		2001 Notes:		I found an old version, in C (by Eric Raymond), which was adapted from		an even older version, in BASIC (by Magnus Olsson), that had been found		in a SIMTEL archive. It's got lineage. 		As of 22-Oct-2001, it appears to work, though I haven't traced the		arrow path'ing logic yet nor made it smart. Arrows can go pretty much		anywhere you tell them and, yes, you can shoot yourself as in the		original. 		I tweaked a few strings, but the instructions are almost unscathed. 		Ahhh, it takes me back to my Dad's HP85 with the built-in 5 inch		monochrome screen, tape drive, and thermal printer... 		2016 Notes: This was one of the very first programs I wrote in REBOL.		I could update it, but we all have to start somewhere, and I think 		it has a certain charm. It is neither concise, nor idiomatic Redbol		(a portmanteau of Red and Rebol), but making it so will be a good		exercise for the reader, if they so choose. And if they don't, that's		fine too, because you can write your Red code however you want. 		And for the kids out there, my Dad's HP85 was a beast. He paid a LOT		of money to get the extra 16K RAM module. 32K RAM total. Believe it.		Only 36 years ago.	}	history: {		1.0.0 22-Mar-2001 {Initial Release}		1.0.1 11-Apr-2002 {Fixed bug where the Wumpus might eat you after you shot him.}		1.0.2 25-Jun-2016 {Ported to Red 0.6.1}	}] arrow-count:  0 ; indexes into location blockplayer: 1wumpus: 2pit-1:	3pit-2:	4bats-1: 5bats-2: 6  start-loc: []loc: []winner: nonefinished: false ; The cave is a dodecahedron. Each block is a room containing the; number for the rooms it is connected to.cave: [	[2 5 8]    [1 3 10]  [2 4 12]	[3 5 14]   [1 4 6]	[5 7 15]   [6 8 17]  [1 7 9]	[8 10 18]  [2 9 11]	[10 12 19] [3 11 13] [12 14 20] [4 13 15]  [6 14 16]	[15 17 20] [7 16 18] [9 17 19]	[11 18 20] [13 16 19]] random-room: does [random 20]random-direction: does [random 3] get-num: func [prompt][	if error? try [return to integer! ask prompt] [		return 0	]] print-instructions: does [	print {WELCOME TO 'HUNT THE WUMPUS' (love that all caps retro look) THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM HAS 3 TUNNELS LEADING TOOTHER ROOMS. HAZARDS:  BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM. IF YOU GO THERE,    YOU FALL INTO THE PIT (YOU LOSE!)  SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU GO THERE, A BAT GRABS    YOU AND TAKES YOU TO SOME OTHER ROOM AT RANDOM. (WHICH MAY BE TROUBLESOME) WUMPUS: THE WUMPUS IS NOT BOTHERED BY HAZARDS (HE HAS SUCKER FEET AND IS TOO    BIG FOR A BAT TO LIFT). USUALLY HE IS ASLEEP. TWO THINGS WAKE HIM UP: YOU    SHOOTING AN ARROW OR YOU ENTERING HIS ROOM. IF THE WUMPUS WAKES HE MOVES    ONE ROOM (75% chance) OR STAYS STILL (25% chance). AFTER THAT, IF HE IS    WHERE YOU ARE, HE EATS YOU UP AND YOU LOSE! YOU: EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW.  MOVING: YOU CAN MOVE ONE ROOM (THROUGH ONE TUNNEL).  ARROWS: YOU HAVE 5 ARROWS.  YOU LOSE WHEN YOU RUN OUT.        EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING THE COMPUTER        THE ROOMS YOU WANT THE ARROW TO GO TO. IF THE ARROW CAN'T GO THAT WAY        (I.E. NO TUNNEL) IT MOVES AT RANDOM TO THE NEXT ROOM.        * IF THE ARROW HITS THE WUMPUS, YOU WIN.        * IF THE ARROW HITS YOU, YOU LOSE. WARNINGS: WHEN YOU ARE ONE ROOM AWAY FROM A WUMPUS OR HAZARD, THE COMPUTER SAYS:    WUMPUS:  'YOU SMELL SOMETHING TERRIBLE NEARBY'    BAT   :  'YOU HEAR A RUSTLING'    PIT   :  'YOU FEEL A COLD WIND BLOWING FROM A NEARBY CAVERN'} 	ask "Press <Enter> when you're ready to start the game" ] check-for-hazards: has [i][	print ""	print ["You are in room" loc/:player]	print ["Tunnels lead to" pick cave loc/:player]	; Look at each of the 3 rooms around the player to see if the contain	; the wumpus, a pit, or bats.	repeat i 3 [		room: pick pick cave loc/:player i		if (room = loc/:wumpus) [			print "^-You smell something terrible nearby."		]		if any [(room = loc/:pit-1) (room = loc/:pit-2)] [			print "^-You feel a cold wind blowing from a nearby cavern."		]		if any [(room = loc/:bats-1) (room = loc/:bats-2)] [			print "^-You hear a rustling."		]	]	print ""] move-or-shoot?: has [cmd][	cmd: ask "Shoot or move (S/M)? "	; The default case handles bad inputs and prompts the user again.	switch/default cmd [		"S" ['shoot]		"M" ['move]	][move-or-shoot?]] move-arrow: func [room path /local i rnd-rm][	;print reduce ["move arrow" room tab path]	; FOR DEBUG USE	if not tail? path [		; If they gave us a bogus target room, pick a random one.		either find cave/:room first path [			; Next room in path is valid			check-for-arrow-hit first path			if finished [exit]			; Recursive call			move-arrow first path next path		][			; Pick a random direction			i: random-direction			check-for-arrow-hit rnd-rm: cave/:room/:i			if finished [exit]			; Recursive call			move-arrow rnd-rm next path		]	]] shoot: has [path][	path: load ask "Enter 1 to 5 room numbers for the arrow's path: "	path: compose [(path)]			; ensure it's a block, in case they entered only 1 number	move-arrow loc/:player path	if not finished [		print "^-Your arrow missed"		move-wumpus	]	; See if the Wumpus moved onto the player	if finished [exit] 	arrow-count: arrow-count - 1	if (arrow-count <= 0) [		print "^/You ran out of arrows..."		winner: 'wumpus		finished: true		exit	] 	check-for-hazards] check-for-arrow-hit: func [room][	if (room = loc/:wumpus) [		print "^/You got the Wumpus!"		winner: 'player		finished: true		exit	]	if (room = loc/:player) [		print "^/You shot yourself!"		winner: 'arrow		finished: true		exit	]] ; 75% chance that it will movewumpus-moves?: does [either (random 4) < 4 [true][false]] move-wumpus: does [	if wumpus-moves? [loc/2: pick (pick cave loc/:wumpus) random-direction]	if (loc/:wumpus = loc/:player) [		winner: 'wumpus		finished: true	]] move-player: func [/bat-move new-loc /local new-player-loc][	either bat-move [		loc/1: new-loc	][		new-player-loc: get-num "To which room? "		; Call recursively, then bail, if bad input		if any [(new-player-loc < 1) (new-player-loc > 20)] [			move-player			exit		]		; Call recursively, then bail, if illegal move		if not find pick cave loc/:player new-player-loc [			print "You can't move there, if not you plan to dig a new tunnel."			move-player			exit		]		; It was a legal move, so update the player's location.		change at loc player new-player-loc	] 	if (loc/:player = loc/:wumpus) [		print "Yikes! You bumped the Wumpus!"		move-wumpus		; See if the Wumpus moved onto the player		if finished [exit]	]	if any [(loc/:player = loc/:pit-1) (loc/:player = loc/:pit-2) ] [		print reduce [newline "Aaiiiiieeeee....(you fell in a pit)"]		winner: 'pit		finished: true		exit	]	if any [(loc/:player = loc/:bats-1) (loc/:player = loc/:bats-2) ] [		print "ZAP! Super-Bat snatch! Elsewhereville for you!"		move-player/bat-move random-room		exit	] 	check-for-hazards ] ; This is ugly, but it works for now and avoids setup collisions.; Don't really need items for this, but I'd like to improve it and then I might.init-locations: has [items avail-rooms result offset][	random/seed now/time/precise	items: [player wumpus pit-1 pit-2 bats-1 bats-2]	avail-rooms: copy [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]	result: make block! length? items	repeat i length? items [		; Too dense for one line?		;append result pick avail-rooms offset: random length? avail-rooms		offset: random/secure length? avail-rooms		append result pick avail-rooms offset		remove at avail-rooms offset	]	return result] setup: func [/same-as-last][	; Initialize arrow count.	arrow-count: 5	; If we haven't setup before, or they want the same setup,	; there's no need to initialize.	if any [(not same-as-last) (start-loc = none)] [		; Randomly place bats, pits, wumpus, and player		start-loc: init-locations	]	; Make a working copy of the starting locations.	loc: copy start-loc] do-game: func [/same-as-last][	either same-as-last [		setup/same-as-last	][		setup	]	check-for-hazards	while [not finished][		either move-or-shoot? = 'shoot [shoot][move-player]	]	print switch winner [		wumpus ["<SNARF> The Wumpus got you!!!"]		player ["<BLARP> The Wumpus will get you next time!"]		pit    ["<SPLAT> Better luck next time"]		arrow  ["<GLURG> You really should be more careful"]	]	print ""] start: does [	if (ask "Would you like instructions (Y/N)? ") = "Y" [		print-instructions	]	play: "Y"	same-setup: "N"	while [play = "Y"][		either same-setup = "N" [			do-game		][			do-game/same-as-last		]		play: ask "Play again (Y/N)? "		if play = "Y" [			winner: none			finished: false			same-setup: ask "Same setup (Y/N)? "		]	]	halt] start `

## SenseTalk

` -- HUNT THE WUMPUS--  BY GREGORY YOB-- SenseTalk adaptation by Jonathan Gover answer "INSTRUCTIONS (Y-N)" with "No" or "Yes"if it is "Yes" then showInstructions -- SET UP CAVE (DODECAHEDRAL NODE LIST)set rooms to [	[2,5,8],[1,3,10],[2,4,12],[3,5,14],[1,4,6],	[5,7,15],[6,8,17],[1,7,9],[8,10,18],[2,9,11],	[10,12,19],[3,11,13],[12,14,20],[4,13,15],[6,14,16],	[15,17,20],[7,16,18],[9,17,19],[11,18,20],[13,16,19]] -- LOCATE L ARRAY ITEMSset locations to the randomLocationsset initialLocations to locations repeat	-- SET# ARROWS	set arrowCount to 5 	-- RUN THE GAME	put "HUNT THE WUMPUS" 	repeat		-- HAZARD WARNINGS & LOCATION		locationAndHazardWarnings locations, rooms 		-- MOVE OR SHOOT		answer "SHOOT OR MOVE (S-M)" with "Move" or "Shoot" or "Quit"		if it is "Quit" then exit all 		-- SHOOT		if it is "Shoot" then			shoot reference to locations, rooms, reference to arrowCount			winOrLose the result			if the result isn't empty then exit repeat		end if 		-- MOVE		if it is "Move" then			move reference to locations, rooms			winOrLose the result			if the result isn't empty then exit repeat		end if 	end repeat 	answer "PLAY AGAIN? (Y-N)" with "No" or "Yes"	if it is "No" then exit repeat 	answer "SAME SET-UP (Y-N)" with "No" or "Yes"	if it is "Yes" then		set locations to initialLocations	else		set locations to the randomLocations		set initialLocations to locations	end if end repeat  to handle randomLocations	put 1..20 shuffled into potentialLocations 	set locations to {		player:first item of potentialLocations,		wumpus:second item of potentialLocations,		pits:third to fourth items of potentialLocations,		bats:fifth to sixth items of potentialLocations	}	return locationsend randomLocations  to handle winOrLose result	if result is "lose" then put "HA HA HA - YOU LOSE!"	if result is "win" then put "HEE HEE HEE - THE WUMPUS'LL GETCHA NEXT TIME!!"	return resultend winOrLose  -- INSTRUCTIONSto handle showInstructions	answer {{WELCOME TO 'HUNT THE WUMPUS'  THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOMHAS 3 TUNNELS LEADING TO OTHER ROOMS. (LOOK AT ADODECAHEDRON TO SEE HOW THIS WORKS-IF YOU DON'T KNOWWHAT A DODECAHEDRON IS, ASK SOMEONE)      HAZARDS: BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM     IF YOU GO THERE, YOU FALL INTO THE PIT (& LOSE!) SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU     GO THERE, A BAT GRABS YOU AND TAKES YOU TO SOME OTHER     ROOM AT RANDOM. (WHICH MIGHT BE TROUBLESOME)      WUMPUS: THE WUMPUS IS NOT BOTHERED BY THE HAZARDS (HE HAS SUCKER FEET AND IS TOO BIG FOR A BAT TO LIFT).  USUALLY HE IS ASLEEP. TWO THINGS WAKE HIM UP: YOUR ENTERING HIS ROOM OR YOUR SHOOTING AN ARROW.     IF THE WUMPUS WAKES, HE MOVES (P=.75) ONE ROOM OR STAYS STILL (P=.25). AFTER THAT, IF HE IS WHERE YOU ARE, HE EATS YOU UP (& YOU LOSE!)      YOU: EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW   MOVING: YOU CAN GO ONE ROOM (THRU ONE TUNNEL)   ARROWS: YOU HAVE 5 ARROWS. YOU LOSE WHEN YOU RUN OUT.   EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING   THE COMPUTER THE ROOM#S YOU WANT THE ARROW TO GO TO.   IF THE ARROW CAN'T GO THAT WAY (IE NO TUNNEL) IT MOVES   AT RANDOM TO THE NEXT ROOM.     IF THE ARROW HITS THE WUMPUS, YOU WIN.     IF THE ARROW HITS YOU, YOU LOSE.     WARNINGS:     WHEN YOU ARE ONE ROOM AWAY FROM WUMPUS OR HAZARD,    THE COMPUTER SAYS: WUMPUS-  'I SMELL A WUMPUS' BAT   -  'BATS NEARBY' PIT   -  'I FEEL A DRAFT' }}end showInstructions  -- PRINT LOCATION & HAZARD WARNINGSto handle locationAndHazardWarnings locations, rooms	put empty 	set currentRoomNumber to locations.player	set tunnelsLeadingTo to item currentRoomNumber of rooms 	repeat with each item of tunnelsLeadingTo		if it is locations.wumpus then put "I SMELL A WUMPUS!"		if it is in locations.pits then put "I FEEL A DRAFT"		if it is in locations.bats then put "BATS NEARBY!"	end repeat 	put !"YOU ARE IN ROOM [[currentRoomNumber]]"	put !"TUNNELS LEAD TO [[tunnelsLeadingTo joined by space]]"	put empty end locationAndHazardWarnings  -- ARROW ROUTINEto handle shoot locations, rooms, arrowCount	-- PATH OF ARROW	answer "NO. OF ROOMS(1-5)" from list 1..5	set numberOfRooms to it 	set intendedPath to [] 	repeat until the number of items in intendedPath equals numberOfRooms		answer "ROOM #" from list 1..20		set nextRoom to it 		if the number of items in intendedPath is more than 1			if nextRoom equals the penultimate item in intendedPath				put "ARROWS AREN'T THAT CROOKED - TRY ANOTHER ROOM"				next repeat			end if		end if 		insert nextRoom into intendedPath 	end repeat 	-- SHOOT ARROW	set arrowLocation to locations.player 	repeat with pathIndex from 1 to number of items in intendedPath		set nextRoom to item pathIndex of intendedPath		set tunnelsLeadingTo to item arrowLocation of rooms 		if tunnelsLeadingTo contains nextRoom then			set arrowLocation to nextRoom		else			-- NO TUNNEL FOR ARROW			set arrowLocation to any item of tunnelsLeadingTo		end if 		-- SEE IF ARROW IS AT L(1) OR L(2)		if arrowLocation equals locations.wumpus then			put "AHA! YOU GOT THE WUMPUS!"			return "win"		end if 		if arrowLocation equals locations.player then			put "OUCH! ARROW GOT YOU!"			return "lose"		end if 		put "MISSED" 		-- MOVE WUMPUS		moveWumpus reference to locations, rooms		if the result is "lose" then return "lose" 		-- AMMO CHECK		subtract 1 from arrowCount		if arrowCount is 0 then			put "NO ARROWS LEFT"			return "lose"		end if	end repeat end shoot  -- MOVE WUMPUS ROUTINEto handle moveWumpus locations, rooms	if random of 4 isn't 4 then		set currentRoomNumber to locations.wumpus		set tunnelsLeadingTo to item currentRoomNumber of rooms 		set locations.wumpus to any item of tunnelsLeadingTo	end if 	if locations.player equals locations.wumpus then		put "TSK TSK TSK- WUMPUS GOT YOU!"		return "lose"	end if 	return emptyend moveWumpus  -- MOVE ROUTINEto handle move locations, rooms	set currentRoomNumber to locations.player	set tunnelsLeadingTo to item currentRoomNumber of rooms 	answer "WHERE TO" from list tunnelsLeadingTo	set locations.player to it 	-- CHECK FOR HAZARDS	-- WUMPUS	if locations.player equals locations.wumpus then		put "...OOPS! BUMPED A WUMPUS!" 		-- MOVE WUMPUS		moveWumpus reference to locations, rooms		if the result is "lose" then return "lose"	end if 	-- PIT	if locations.pits contains locations.player then		put "YYYIIIIEEEE . . . FELL IN PIT"		return "lose"	end if 	-- BATS	if locations.bats contains locations.player then		put "ZAP--SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!"		set locations.player to any item of 1..20	end ifend move `

## Shale

` #!/usr/local/bin/shale // This is an implementation of the old game called Hunt the Wumpus.//// You can read about it here: https://en.wikipedia.org/wiki/Hunt_the_Wumpus//// Here's a quick summary://// You are in a maze of 20 rooms, numbered 1 through 20. Each room is connected to// 3 other rooms. There is no light in the maze, and the game will tell you which// rooms are connected to the one you're in. The maze layout and numbering is the// same for every game. At the time of writing, the Wikipedia page above has an// image showing the layout and numbering.//// In the maze is a Wumpus, 2 bottomless pits and 2 super bats. You will die if you// are in the same room as the Wumpus or if you fall into one of the pits.// If you enter a room where a super bat is you will be transported to another// random room.//// You can move about the maze by entering one of the connecting rooms.// If a connecting room contains the Wumpus, a pit or a super bat, the game// will let you know that they are around but not which room they are in.//// To win you need to kill the Wumpus. You have 5 arrows at your disposal that// may be shot through up to 5 connected rooms, and if your arrow passes through// the room containing the Wumpus then it dies and you win. If your arrow// misses it will wake the Wumpus up and it will move randomly through the maze. maths libraryfile librarystring library playerRoom varwumpusRoom varpit1Room varpit2Room varbat1Room varbat2Room vararrows varwumpusIsAwake varshowStats varstatPlayer varstatWumpus varstatPit varstatArrow var haveWon varhaveDied var // Initialises the maze.init dup var {  i dup var 1 =   { i 20 <= } {    0 i.value:: room:: var    1 i.value:: room:: var    2 i.value:: room:: var    i++  } while   0  1:: room::  2 =  1  1:: room::  5 =  2  1:: room::  8 =  0  2:: room::  1 =  1  2:: room::  3 =  2  2:: room:: 10 =  0  3:: room::  2 =  1  3:: room::  4 =  2  3:: room:: 12 =  0  4:: room::  3 =  1  4:: room::  5 =  2  4:: room:: 14 =  0  5:: room::  1 =  1  5:: room::  4 =  2  5:: room::  6 =  0  6:: room::  5 =  1  6:: room::  7 =  2  6:: room:: 15 =  0  7:: room::  6 =  1  7:: room::  8 =  2  7:: room:: 17 =  0  8:: room::  1 =  1  8:: room::  7 =  2  8:: room::  9 =  0  9:: room::  8 =  1  9:: room:: 10 =  2  9:: room:: 18 =  0 10:: room::  2 =  1 10:: room::  9 =  2 10:: room:: 11 =  0 11:: room:: 10 =  1 11:: room:: 12 =  2 11:: room:: 19 =  0 12:: room::  3 =  1 12:: room:: 11 =  2 12:: room:: 13 =  0 13:: room:: 12 =  1 13:: room:: 14 =  2 13:: room:: 20 =  0 14:: room::  4 =  1 14:: room:: 13 =  2 14:: room:: 15 =  0 15:: room::  6 =  1 15:: room:: 14 =  2 15:: room:: 16 =  0 16:: room:: 15 =  1 16:: room:: 17 =  2 16:: room:: 20 =  0 17:: room::  7 =  1 17:: room:: 16 =  2 17:: room:: 18 =  0 18:: room::  9 =  1 18:: room:: 17 =  2 18:: room:: 19 =  0 19:: room:: 11 =  1 19:: room:: 18 =  2 19:: room:: 20 =  0 20:: room:: 13 =  1 20:: room:: 16 =  2 20:: room:: 19 =} = // Couple of funciton to return various random numbers needed// for different tasks.getRandomRoom dup var {  random maths::() 8 >> 20 % 1 +} = getRandomConnectingRoom dup var {  random maths::() 12 >> 3 % swap :: room:: value} = getRandomWumpusMove dup var {  random maths::() 8 >> 4 % 0 >       // 3 in 4 chance the Wumpus moves.} = // Randomise the starting locations.chooseStartingRooms dup var {  playerRoom getRandomRoom() =  wumpusRoom getRandomRoom() =  { wumpusRoom playerRoom == } {    wumpusRoom getRandomRoom() =  } while  pit1Room getRandomRoom() =  pit1Room playerRoom == { pit1Room wumpusRoom == } or {    pit1Room getRandomRoom() =  } ifthen  pit2Room getRandomRoom() =  pit2Room playerRoom == { pit2Room wumpusRoom == { pit2Room pit1Room == } or } or {    pit2Room getRandomRoom() =  } ifthen  bat1Room getRandomRoom() =  bat1Room playerRoom == { bat1Room wumpusRoom == } or {    bat1Room getRandomRoom() =  } ifthen  bat2Room getRandomRoom() =  bat2Room playerRoom == { bat2Room wumpusRoom == { bat2Room bat1Room == } or } or {    bat2Room getRandomRoom() =  } ifthen} = // Details the connected rooms and whether the Wumpus, a pit or a bat is in a connected room.showPlayerRoom dup var {  pitNearby dup var false =  batsNearby dup var false =   2 playerRoom.value:: room:: 1 playerRoom.value:: room:: 0 playerRoom.value:: room:: playerRoom "You are in room %d, with connections to rooms %d, %d and %d\n" printf  0 playerRoom.value:: room:: wumpusRoom == { 1 playerRoom.value:: room:: wumpusRoom == { 2 playerRoom.value:: room:: wumpusRoom == } or } or {    "You smell a dreadful stench!" println  } ifthen  0 playerRoom.value:: room:: pit1Room == { 1 playerRoom.value:: room:: pit1Room == { 2 playerRoom.value:: room:: pit1Room == } or } or {    pitNearby true =  } ifthen  pitNearby not {    0 playerRoom.value:: room:: pit2Room == { 1 playerRoom.value:: room:: pit2Room == { 2 playerRoom.value:: room:: pit2Room == } or } or {      pitNearby true =    } ifthen  } ifthen  pitNearby {    "You feel a draft." println  } ifthen  0 playerRoom.value:: room:: bat1Room == { 1 playerRoom.value:: room:: bat1Room == { 2 playerRoom.value:: room:: bat1Room == } or } or {    batsNearby true =  } ifthen  batsNearby not {    0 playerRoom.value:: room:: bat2Room == { 1 playerRoom.value:: room:: bat2Room == { 2 playerRoom.value:: room:: bat2Room == } or } or {      batsNearby true =    } ifthen  } ifthen  batsNearby {    "There are bats nearby." println  } ifthen  "" println} = getAnswer dup var {  haveAnswer dup var false =   { haveAnswer not } {    stdin file:: fgets file::() {      dup      "xyzzy" equals string::() {        showStats showStats not =        pop      } {        atoi string::()        haveAnswer true =      } if    } {      0 exit    } if  } while} = // Handles the process of moving to a connected room.move dup var {  haveRoom dup var false =  req var   { haveRoom not } {    2 playerRoom.value:: room:: 1 playerRoom.value:: room:: 0 playerRoom.value:: room:: "Move to room (%d, %d or %d): " printf    req getAnswer() =    req 0 playerRoom.value:: room:: == { req 1 playerRoom.value:: room:: == { req 2 playerRoom.value:: room:: == } or } or {      playerRoom req =      haveRoom true =    } {      "That is not a connected room." println    } if  } while  "" println} = // Handles the process of shooting an arrow.shoot dup var {  haveAnswer var  req var  rooms var  lastRoom var  i var  gotKilled var  gotTheWumpus var   "" println  arrows 1 == { "" } { "s" } if arrows "You have %d arrow%s remaining.\n" printf  "How many rooms will your arrow pass through (1 to 5): " print  lastRoom playerRoom =  gotKilled false =  gotTheWumpus false =  haveAnswer false =  { haveAnswer not } {    req getAnswer() =    req 1 >= req 5 <= and {      rooms req =      haveAnswer true =    } {      "You must specify 1, 2, 3, 4 or 5." println    } if  } while   i 1 =  { i rooms <= } {    haveAnswer false =    { haveAnswer not } {      2 lastRoom.value:: room:: 1 lastRoom.value:: room:: 0 lastRoom.value:: room::      i rooms == {        rooms 1 == { "Only room" } { "Last room" } if      } {        i 1 == { "1st room" } ifthen        i 2 == { "2nd room" } ifthen        i 3 == { "3rd room" } ifthen        i 4 == { "4th room" } ifthen      } if      "%s (%d, %d or %d): " printf       req getAnswer() =      req 0 lastRoom.value:: room:: == { req 1 lastRoom.value:: room:: == { req 2 lastRoom.value:: room:: == } or } or {        req playerRoom == {          gotKilled true =        } ifthen        req wumpusRoom == {          gotTheWumpus true =        } ifthen        lastRoom req =        haveAnswer true =      } ifthen    } while     i++  } while  arrows--   "" println  gotKilled {    "You were killed by your own arrow." println    haveDied true =    statArrow++  } {    gotTheWumpus {      "Congratulations, you killed the Wumpus." println      haveWon true =      statPlayer++    } {      arrows 0 == {        "Your arrow missed and you have died because you have no arrows left." println        haveDied true =        statArrow++      } {        wumpusIsAwake {          "Your arrow missed." println        } {          "Your arrow missed and you've woken up the Wumpus." println          wumpusIsAwake true =        } if      } if    } if  } if} = // The player's turn, move or shoot.playerTurn dup var {  turnOver dup var false =  req  var   { turnOver not } {    showPlayerRoom()    "1 - move" println    "2 - shoot" println    "> " print    req getAnswer() =    req 1 == {      move()      turnOver true =    } ifthen    req 2 == {      shoot()      turnOver true =    } ifthen  } while} = // The game's turn, whether to move the Wumpus or not.gameTurn dup var {  wumpusIsAwake {    getRandomWumpusMove() {      wumpusRoom wumpusRoom.value getRandomConnectingRoom() =    } ifthen  } ifthen} = // Check if something bad happened to the player.checkSituationAfterPlayerMove dup var {  playerRoom wumpusRoom == {    "You have died, eaten by the Wumpus." println    haveDied true =    statWumpus++  } {    playerRoom pit1Room == playerRoom pit2Room == or {      "You have died by falling into a pit." println      haveDied true =      statPit++    } ifthen  } if  haveDied not {    playerRoom bat1Room == {      playerRoom getRandomRoom() =      { playerRoom bat1Room == playerRoom bat2Room == or } {        playerRoom getRandomRoom() =      } while      bat1Room getRandomRoom() =      { bat1Room playerRoom == bat1Room bat2Room == or } {        bat1Room getRandomRoom() =      } while      playerRoom "You have been moved to room %d.\n" printf      checkSituationAfterPlayerMove()    } {      playerRoom bat2Room == {        playerRoom getRandomRoom() =        { playerRoom bat1Room == playerRoom bat2Room == or } {          playerRoom getRandomRoom() =        } while        bat2Room getRandomRoom() =        { bat2Room playerRoom == bat2Room bat1Room == or } {          bat2Room getRandomRoom() =        } while        playerRoom "You have been moved to room %d.\n" printf        checkSituationAfterPlayerMove()      } ifthen    } if  } ifthen} = // Check if something bad happened to the player.checkSituationAfterGameMove dup var {  playerRoom wumpusRoom == {    "You have died, eaten by the Wumpus." println    haveDied true =    statWumpus++  } ifthen} = // Take turns between the player and the game.play dup var {  haveWon false =  haveDied false =  wumpusIsAwake false =  arrows 5 =   chooseStartingRooms()  "" println  { haveWon not haveDied not and } {    playerTurn()    checkSituationAfterPlayerMove()    haveWon not haveDied not and {      gameTurn()      checkSituationAfterGameMove()    } ifthen  } while} = toplevel dup var {  haveAnswer var  req var   showStats false =  statPlayer 0 =  statWumpus 0 =  statPit 0 =  statArrow 0 =   { true } {    haveAnswer false =    { haveAnswer not } {      showStats {        statArrow statPit statWumpus statPlayer "\nPlayer %d, Wumpus %d, Pit %d, Arrow %d\n" printf      } ifthen       "" println      "1 - play game" println      "2 - quit" println      "> " print      req getAnswer() =      req 2 == {        0 exit      } ifthen      req 1 == {        haveAnswer true =      } ifthen    } while     play()  } while} = init()toplevel() `

## Swift

Translation of: Go
` import Foundation //All rooms in cavevar cave: [Int:[Int]] = [    1: [2, 3, 4],    2: [1, 5, 6],    3: [1, 7, 8],    4: [1, 9, 10],    5: [2, 9, 11],    6: [2, 7, 12],    7: [3, 6, 13],    8: [3, 10, 14],    9: [4, 5, 15],    10: [4, 8, 16],    11: [5, 12, 17],    12: [6, 11, 18],    13: [7, 14, 18],    14: [8, 13, 19],    15: [9, 16, 17],    16: [10, 15, 19],    17: [11, 20, 15],    18: [12, 13, 20],    19: [14, 16, 20],    20: [17, 18, 19]] // initialize curr room, wumpus's room, bats roomvar player: Int = 0, wumpus: Int = 0, bat1:Int = 0, bat2:Int = 0, pit1:Int = 0, pit2:Int = 0 //number of arrows leftvar arrows = 5 //check if room is emptyfunc isEmpty(r:Int)->Bool {    if r != player &&       r != wumpus &&       r != bat1 &&       r != bat2 &&       r != pit1 &&       r != pit2 {            return true        }        return false} //sense if theres bat/pit/wumpus in adjacent roomsfunc sense(adj: [Int]) {    var bat = false    var pit = false    for ar in adj {        if ar == wumpus {            print("You smell something terrible nearby.")        }        switch ar {        case bat1, bat2:            if !bat {                print("You hear rustling.")                bat = true            }        case pit1, pit2:            if !pit {                print("You feel a cold wind blowing from a nearby cavern.")                pit = true            }        default:            print("")        }    }} //check if there are more than 1 arrow then add plural to arrow messagefunc plural(n: Int)->String {    if n != 1 {        return "s"    }    return ""}  func game() {     //set current room to 1, start the game    player = 1     //wumpus, bats, pits will be in a random room - except start room    wumpus = Int.random(in: 2..<21)    bat1 = Int.random(in: 2..<21)     //bat2 must be in different room to bat1    while true {        bat2 = Int.random(in: 2..<21)        if bat2 != bat1 {            break        }    }     //pit1 and pit2 must be in different rooms from bats and each other    while true {        pit1 = Int.random(in: 2..<21)        if pit1 != bat1 && pit1 != bat2 {            break        }    }    while true {        pit2 = Int.random(in: 0..<21)        if pit2 != bat1 && pit2 != bat2 && pit2 != pit1 {            break        }    }     //player session    while true {        print("\nYou are in room \(player) with \(arrows) arrow\(plural(n: arrows)) left\n")         //list of adjacent rooms        let adj = cave[player]!        print("The adjacent rooms are \(adj)\n")         //check adjacent rooms        sense(adj: adj)         //variable to keep track of next room player gonna choose        var room: Int?        while true {            print("Choose an adjacent room: ")             //validate the room player choose            if let roomInput = Int(readLine()!) {                room = roomInput                if !adj.contains(room!) {                    print("\ninvalid response, try again\n")                    print("The adjacent rooms are \(adj)\n")                } else {                    break                }            } else {                print("\ninvalid response, try again\n")                print("The adjacent rooms are \(adj)\n")            }        }         //initialize variable to store user input/action(shoot or walk)        var action: String = ""         //player action        while true {            print("Walk or shoot w/s: ")            //validate the action player choose            if var reply = readLine() {                reply = reply.lowercased()                if reply.count != 1 || (reply.count == 1 && Array(reply)[0] != "w" && Array(reply)[0] != "s") {                    print("Invalid response, try again")                } else {                    //if valid store the action                    action = Array(arrayLiteral: reply)[0]                    break                }            } else {                print("Invalid response, try again")            }        }         if action == "w" {            //if walk, set current room to selected room            player = room!            switch player {                //if the selected room is wumpus/pit, player lose                case wumpus:                    print("You have been eaten by the wumpus and lost the game")                    return                case pit1, pit2:                    print("You have fallen down a bottomless pit and lost the game!")                    return                //if the room has bat, player got transport to a random empty room                case bat1, bat2:                    while true {                        room = Int.random(in: 2..<21)                        if isEmpty(r: room!) {                            print("A bat has transported you to a random empty room.")                            player = room!                                        break                        }                    }                default:                    break            }        } else {            //if player shoot to wumpus room, player win            if room == wumpus {                print("You have killed the wumpus and won the game!!")                return            } else {                //chance player will miss the room with wumpus, wumpus will move to a different room                let chance = Int.random(in: 0..<4)                if chance > 0 {                    wumpus = cave[wumpus]![Int.random(in: 0..<3)]                    //if the room is the player room, player lost                    if player == wumpus {                        print("You have been eaten by the wumpus and lost the game!")                        return                    }                }            }            //reduce arrow after shoot            arrows-=1            if arrows == 0 {                print("You have run out of arrows and lost the game!")                return            }        }    }}game()  `

## Wren

Translation of: Go
Library: Wren-fmt
Library: Wren-ioutil
Library: Wren-str
`import "random" for Randomimport "/fmt" for Fmtimport "/ioutil" for Inputimport "/str" for Str var cave = {     1: [ 2,  3,  4],  2: [ 1,  5,  6],  3: [ 1,  7,  8],  4: [ 1,  9, 10],       5: [ 2,  9, 11],  6: [ 2,  7, 12],  7: [ 3,  6, 13],  8: [ 3, 10, 14],       9: [ 4,  5, 15], 10: [ 4,  8, 16], 11: [ 5, 12, 17], 12: [ 6, 11, 18],     13: [ 7, 14, 18], 14: [ 8, 13, 19], 15: [ 9, 16, 17], 16: [10, 15, 19],    17: [11, 20, 15], 18: [12, 13, 20], 19: [14, 16, 20], 20: [17, 18, 19]} var playervar wumpusvar batt1var bat2var pit1var pit2var arrows = 5 var isEmpty = Fn.new { |r|    if (r != player && r != wumpus && r != bat1 && r != bat2 && r != pit1 && r != pit2) {        return true    }    return false} var sense = Fn.new { |adj|    var bat = false    var pit = false    for (ar in adj) {        if (ar == wumpus) System.print("You smell something terrible nearby.")        if (ar == bat1 || ar == bat2) {            if (!bat) {                System.print("You hear a rustling.")                bat = true            }        } else if (ar == pit1 || ar == pit2) {            if (!pit) {                System.print("You feel a cold wind blowing from a nearby cavern.")                pit = true            }        }    }    System.print()} var plural = Fn.new { |n| (n != 1) ? "s" : "" } var rand = Random.new()player = 1wumpus = rand.int(2, 21)bat1   = rand.int(2, 21)while (true) {    bat2 = rand.int(2, 21)    if (bat2 != bat1) break}while (true) {    pit1 = rand.int(2, 21)    if (pit1 != bat1 && pit1 != bat2) break}while (true) {    pit2 = rand.int(2, 21)    if (pit2 != bat1 && pit2 != bat2 && pit2 != pit1) break}while (true) {    Fmt.print("\nYou are in room \$d with \$d arrow\$s left", player, arrows, plural.call(arrows))    var adj = cave[player]    System.print("The adjacent rooms are %(adj)")    sense.call(adj)    var room = Input.intOpt("Choose an adjacent room : ", adj)    var action = Str.lower(Input.option("Walk or shoot w/s : ", "wsWS"))    if (action == "w") {        player = room        if (player == wumpus) {            System.print("You have been eaten by the Wumpus and lost the game!")            return        } else if (player == pit1 || player == pit2) {            System.print("You have fallen down a bottomless pit and lost the game!")            return        } else if (player == bat1 || player == bat2) {            while (true) {                room = rand.int(2, 20)                if (isEmpty.call(room)) {                    System.print("A bat has transported you to a random empty room")                    player = room                    break                }            }        }    } else {        if (room == wumpus) {            System.print("You have killed the Wumpus and won the game!!")            return        } else {            var chance = rand.int(4) // 0 to 3            if (chance > 0) {        // 75% probability                wumpus = cave[wumpus][rand.int(3)]                if (player == wumpus) {                    System.print("You have been eaten by the Wumpus and lost the game!")                    return                }            }        }        arrows = arrows - 1        if (arrows == 0) {            System.print("You have run out of arrows and lost the game!")            return        }    }}`