Hunt the Wumpus: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
(35 intermediate revisions by 19 users not shown)
Line 1:
{{task|Games}}
{{Clarify_task}}
Create a simple implementation of the classic textual game [http[w://en.wikipedia.org/wiki/Hunt_the_WumpusHunt the Wumpus|Hunt Thethe Wumpus]].
 
The rules are:
Line 35:
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.
 
=={{header|Ada}}==
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'''
<syntaxhighlight lang="ada">package Wumpus is
procedure Start_Game;
end Wumpus;
</syntaxhighlight>
'''Wumpus package body'''
<syntaxhighlight lang="ada">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;
</syntaxhighlight>
'''Main procedure'''
<syntaxhighlight lang="ada">
with Wumpus; use Wumpus;
 
procedure Main is
begin
Start_Game;
end Main;
</syntaxhighlight>
 
=={{header|BASIC}}==
<syntaxhighlight lang="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): NEXT
30 INPUT "Enter a number";X: X=RND(-ABS(X))
40 PRINT: PRINT "*** HUNT THE WUMPUS ***"
50 PRINT "-----------------------": PRINT
60 FOR I=0 TO 1: GOSUB 500: P(I)=X: GOSUB 500: B(I)=X: NEXT
70 GOSUB 500: W=X: GOSUB 500: P=X
80 A=5
90 IF A=0 THEN 340
100 IF P=W THEN 410
110 IF P=B(0) OR P=B(1) THEN 360
120 IF P=P(0) OR P=P(1) THEN 390
130 PRINT: FOR I=0 TO 2
140 IF R(P,I)=W THEN PRINT "You smell something terrible nearby."
150 FOR J=0 TO 1
160 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,I
190 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: PRINT
220 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 260
240 IF I$="Q" OR I$="q" THEN END
250 PRINT "Sorry?": GOTO 220
260 INPUT "Which room";X: PRINT
270 IF X=R(P,0) OR X=R(P,1) OR X=R(P,2) THEN IF S THEN 290 ELSE P=X: GOTO 90
280 PRINT "Cannot get there from here.": GOTO 260
290 IF X=W THEN PRINT "Congratulations! You shot the wumpus!": GOTO 440
300 PRINT "You missed.": A=A-1: IF RND(1)<.25 THEN 90
310 PRINT "The wumpus wakes from his slumber."
320 X=RND(1)*3: IF R(R(W,X),3) THEN 320
330 R(W,3)=0: W=R(W,X): R(W,3)=1: GOTO 90
340 PRINT "As you grasp at your empty quiver, ";
350 PRINT "you hear a large beast approaching...": GOTO 410
360 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 90
390 PRINT "The ground gives way beneath your feet."
400 PRINT "You fall into a deep abyss.": GOTO 430
410 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 60
460 IF I$<>"N" AND I$<>"n" THEN PRINT "Sorry?": GOTO 440
470 END
500 X=RND(1)*20: IF R(X,3)=0 THEN R(X,3)=1: RETURN ELSE 500
510 DATA 1,4,7, 0,2,9, 1,3,11, 2,4,13, 0,3,5
520 DATA 4,6,14, 5,7,16, 0,6,8, 7,9,17, 1,8,10
530 DATA 9,11,18, 2,10,12, 11,13,19, 3,12,14, 5,13,15
540 DATA 14,16,19, 6,15,17, 8,16,18, 10,17,19, 12,15,18</syntaxhighlight>
 
=={{header|APL}}==
See [[Hunt_The_Wumpus/APL]]
 
=={{header|AutoHotkey}}==
See [[Hunt_The_Wumpus/AutoHotkey]]
 
=={{header|C sharp|C#}}==
See [[Hunt_The_Wumpus/CSharp]].
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">
// constant value 2d array to represent the dodecahedron
// room structure
const 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 constructor
WumpusGame::WumpusGame() {
numRooms = 20;
}
 
// This function prints the instructions for the game
// to the console
void 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 wumpus
void 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 0
void 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 0
void WumpusGame::PlaceWumpus() {
srand (time(NULL));
int randomRoom = rand() % 20 + 1;
wumpusRoom = randomRoom;
wumpusStart = wumpusRoom;
}
 
// place the player in room 0
void 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 description
void 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 position
void WumpusGame::MoveStartledWumpus(int roomNum){
srand (time(NULL));
int rando = rand() % 3;
if(rando != 3)
wumpusRoom = adjacentRooms[roomNum][rando];
}
 
// This restarts the map from the begiinning
void 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 loop
void 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();
}
 
</syntaxhighlight>
 
=={{header|Common Lisp}}==
 
<syntaxhighlight lang="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)
</syntaxhighlight>
 
=={{header|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
<syntaxhighlight lang="gnu make">
# gnu make
 
COMMON := -Wall -g -fPIC -fopenmp
override FFLAGS += ${COMMON} -ffree-form -fall-intrinsics -fimplicit-none
 
%: %.F08
gfortran -std=f2008 $(FFLAGS) $< -o $@
 
%.o: %.F08
gfortran -std=f2008 -c $(FFLAGS) $< -o $@
 
%: %.f08
gfortran -std=f2008 $(FFLAGS) $< -o $@
 
%.o: %.f08
gfortran -std=f2008 -c $(FFLAGS) $< -o $@
</syntaxhighlight>
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:
<syntaxhighlight lang="f08">
! 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
</syntaxhighlight>
short sample run
<pre>
$ ./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.
</pre>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="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,17
data 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,14
data 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), targ
dim as ubyte player = int(rnd*20)+1, wump, bat1, bat2, pit1, pit2, d6, epi
dim as ubyte arrows = 5
dim as string choice
 
for i = 1 to 20 'set up rooms
for j = 1 to 3
read tunnel(i,j)
next j
next 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 j
next i
 
'place wumpus, bats, and pits
do
wump = int(rnd*20)+1
loop until wump <> player
do
pit1 = int(rnd*20)+1
loop until pit1 <> player
do
pit2 = int(rnd*20)+1
loop until pit2 <> player andalso pit2 <> pit1
do
bat1 = int(rnd*20)+1
loop until bat1 <> player andalso bat1 <> pit1 andalso bat1 <> pit2
do
bat2 = int(rnd*20)+1
loop 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 select
loop until arrows = 0
print "You have run out of arrows!"
defeat:
print "You lose! Better luck next time."
end
victory:
print "You have slain the Wumpus!"
print "You have won!"
end</syntaxhighlight>
 
=={{header|Go}}==
Line 52 ⟶ 1,927:
 
4. If the Wumpus wakes up and moves to an 'adjacent' room, it means a room adjacent to the Wumpus not necessarily the player.
<langsyntaxhighlight lang="go">package main
 
import (
Line 214 ⟶ 2,089:
}
}
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
 
<syntaxhighlight lang="haskell">import System.Random
import System.IO
import Data.List
import Data.Char
import Control.Monad
 
-- Rooms
cave :: [[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 :: Int
caveSize = length cave
 
-- Game state
data GameState = GameState {
wumpus :: Int,
player :: Int,
arrows :: Int,
pits :: [Int],
bats :: [Int]
}
 
-- Print the state of the game
instance 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 state
initGame :: StdGen -> GameState
initGame 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 -> GameState
moveWumpus 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 room
movePlayer :: GameState -> StdGen -> GameState
movePlayer s g = s {player = (cave !! player s) !! (fst $ randomR (0,2) g)}
 
-- Move or shoot
data Action = Move | Shoot | Quit deriving Show
inputAction :: IO Action
inputAction = 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 room
inputDestination :: Int -> IO Int
inputDestination 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 no
inputYesNo :: IO Bool
inputYesNo = 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 player
data PlayerState = NoArrows | Bat | Pit | Wumpus | Alive deriving Show
playerState :: GameState -> PlayerState
playerState 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 loop
data GameResult = Win | Lose | Stop deriving Show
game :: GameState -> IO GameResult
game 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 wumpus
shoot :: GameState -> Int -> IO GameResult
shoot 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 game
playGame :: 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</syntaxhighlight>
 
=={{header|IS-BASIC}}==
<langsyntaxhighlight ISlang="is-BASICbasic">100 PROGRAM "Wumpus.bas"
110 RANDOMIZE
120 NUMERIC RO(1 TO 20,1 TO 3),LO(1 TO 20),WPOS
Line 290 ⟶ 2,333:
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,11
830 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</langsyntaxhighlight>
 
=={{header|Java}}==
Line 297 ⟶ 2,340:
=={{header|Javascript}}==
See [[Hunt_The_Wumpus/Javascript]].
 
 
=={{header|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.
<langsyntaxhighlight lang="julia">const starttxt = """
 
ATTENTION ALL WUMPUS LOVERS!!!
Line 491 ⟶ 2,533:
end
end
</syntaxhighlight>
</lang>
 
=={{header|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;
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module WumpusGame {
Print "Game: Hunt The Wumpus"
Line 599 ⟶ 2,641:
WumpusGame
 
</syntaxhighlight>
</lang>
 
=={{header|Perl 6MiniScript}}==
<syntaxhighlight lang="miniscript">exits = [[1,4,7], [0,2,9], [1,3,11], [2,4,13], [0,3,5],
See [[Hunt_The_Wumpus/Perl_6]]
[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] * 20
emptyRoom = function()
while true
room = floor(rnd * 20)
if not hazard[room] then return room
end while
end function
for i in range(1, 2)
hazard[emptyRoom] = "bat"
hazard[emptyRoom] = "pit"
end for
hazard[emptyRoom] = "wumpus"
 
print "*** HUNT THE WUMPUS ***"
print "-----------------------"
curRoom = emptyRoom
arrows = 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 while
end while</syntaxhighlight>
 
=={{header|Nim}}==
{{trans|Go}}
<syntaxhighlight lang="nim">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()</syntaxhighlight>
 
{{out}}
<pre>You are in room 1 with 5 arrows left
The adjacent rooms are 2, 3, 4
You hear a rustling.
 
Choose an adjacent room: 2
Walk or shoot (w/s): w
 
You are in room 2 with 5 arrows left
The adjacent rooms are 1, 5, 6
 
Choose an adjacent room: 5
Walk or shoot (w/s): w
 
You are in room 5 with 5 arrows left
The adjacent rooms are 2, 9, 11
 
Choose an adjacent room: 9
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.
 
Choose an adjacent room: 15
Walk or shoot (w/s): s
You have killed the Wumpus and won the game!!</pre>
 
=={{header|Perl}}==
Besides running in a terminal, it also can run under xinetd.
<syntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict; # see https://rosettacode.org/wiki/Hunt_the_Wumpus
use 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"; }
}</syntaxhighlight>
 
=={{header|Phix}}==
Line 613 ⟶ 2,945:
https://github.com/jburse/jekejeke-samples/raw/master/pack/games/wumpus-1.0.0.zip
 
<langsyntaxhighlight lang="prolog">
/**
* Simple text based dungeon game in Prolog.
Line 988 ⟶ 3,320:
write(' BAT - ''BATS NEARBY'''), nl,
write(' PIT - ''I FEEL A DRAFT'''), nl, nl.
</syntaxhighlight>
</lang>
 
=={{header|Python}}==
Line 994 ⟶ 3,326:
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.
 
<langsyntaxhighlight lang="python">
import random
 
Line 1,271 ⟶ 3,603:
WG.gameloop()
 
</syntaxhighlight>
</lang>
 
Example run (on a windows system):
 
<langsyntaxhighlight lang="cmd">
D:\Workspace\rosettacode>python wumpus.py
HUNT THE WUMPUS
Line 1,290 ⟶ 3,622:
 
Game over!
</syntaxhighlight>
</lang>
 
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:
 
<langsyntaxhighlight lang="cmd">
>>> import wumpus
>>> WG = wumpus.WumpusGame()
Line 1,300 ⟶ 3,632:
>>> print edges
[[1,2], [1,3], [1,4], [2,1], [2,5], [2,6], [3,1], ...]
</syntaxhighlight>
</lang>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="Quackery"> [ table
[ 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 ] ] is adjacent ( n --> [ )
 
[ stack ] is player ( --> s )
[ stack ] is arrows ( --> s )
[ stack ] is wumpus ( --> s )
[ stack ] is bat1 ( --> s )
[ stack ] is bat2 ( --> s )
[ stack ] is pit1 ( --> s )
[ stack ] is pit2 ( --> s )
 
[ over find swap found ] is has ( [ n --> b )
 
[ dup dup size random peek join ] is addrand ( [ --> [ )
 
[ trim reverse trim reverse
$->n not if [ drop -1 ] ] is validate ( $ --> n )
 
[ say "A giant bat transports you to chamber "
20 random dup echo say "." cr
player replace
20 random swap replace ] is relocate ( s --> )
 
[ player share
dup bat1 share = iff
[ drop bat1 relocate ] again
dup bat2 share = iff
[ drop bat2 relocate ] again
dup pit1 share =
over pit2 share = or iff
[ say "You fell into a bottomless pit."
drop false ]
done
dup wumpus share = iff
[ say "The Wumpus eats you." drop false ]
done
say "You are in chamber " dup echo say "." cr
say "Adjacent chambers are: "
adjacent dup witheach
[ echo i 0 = iff [ say "." cr ]
else
[ say ", "
i 1 = if [ say "and " ] ] ]
say "You have " arrows share echo say " arrows." cr
dup wumpus share has if
[ say "You smell something terrible nearby." cr ]
dup bat1 share has
over bat2 share has or if
[ say "You hear a rustling." cr ]
dup pit1 share has
swap pit2 share has or if
[ say "You feel a cold wind "
say "blowing from a nearby chamber." cr ]
true ] is report ( --> b )
 
[ $ "Move to which chamber? " input validate
player share adjacent
dup addrand unrot find
peek player put true ] is move ( --> b )
 
[ true
$ "Shoot into which chambers? " input nest$
dup [] = if [ drop ' [ [ -1 ] ] ]
player share swap witheach
[ $->n not if [ drop -1 ]
swap adjacent
dup addrand unrot find peek
say "The arrow enters chamber "
dup echo say "." cr
dup player share = iff
[ say "You shot yourself." cr
dip not conclude ]
done
dup wumpus share = iff
[ say "You shot the Wumpus." cr
dip not conclude ]
done ]
drop dup while
say "You did not hit anything." cr
4 random 0 != if
[ wumpus take adjacent
3 random peek wumpus put ]
-1 arrows tally
arrows share 0 = if
[ say "You have run out of arrows." cr not ] ] is shoot ( --> b )
 
[ $ "Move or shoot? " input space join
0 peek upper dup char M = iff [ drop move ] done
char S = iff shoot done
again ] is action ( b --> b )
 
[ cr
say "Your mission is to anaesthetise an ailing "
say "Wumpus so that it can be healed." cr
say "It is in a dodecahedral labyrinth "
say "that is fraught with dangers." cr
say "The labyrinth has 20 chambers numbered 0 to "
say "19 which are connected by tunnels." cr cr
say "- The Wumpus will eat you if it sees you." cr
say "- Two of the chambers are bottomless pits." cr
say "- There are two giant bats that will "
say "transport you to a random chamber." cr cr
say "You can smell the Wumpus from an adjoining "
say "chamber. It smells terrible." cr
say "When you are in a chamber next to a bottomless "
say "pit you can feel a cold wind." cr
say "You can hear the giant bats rustle from a "
say "chamber away." cr cr
say "You are equipped with five progammable arrows." cr
say "They can be programmed with up to five "
say "adjoining chambers." cr
say "If a destination is invalid the arrow will move "
say "to a random adjoining chamber." cr cr
say "Be careful! Do not shoot yourself. Wumpus "
say "anasthetic is lethal to humans." cr
say "If you miss the Wumpus it will probably wake "
say "and move to an adjoining chamber." cr cr ] is rules ( --> )
 
[ say "Hunt the Wumpus, the Quackery cut." cr cr
randomise
5 arrows put
[] 20 times [ i join ] shuffle
' [ player wumpus bat1 bat2 pit1 pit2 ]
witheach [ dip behead put ]
drop
$ "Would you like to see the rules? " input
space join 0 peek upper char Y = if rules
[ report while
action while
cr again ]
' [ player arrows wumpus bat1 bat2 pit1 pit2 ]
witheach release ] is play ( --> )
 
play</syntaxhighlight>
 
{{out}}
 
Sample game.
 
<pre>Hunt the Wumpus, the Quackery cut.
 
Would you like to see the rules? y
 
Your mission is to anaesthetise an ailing Wumpus so that it can be healed.
It is in a dodecahedral labyrinth that is fraught with dangers.
The labyrinth has 20 chambers numbered 0 to 19 which are connected by tunnels.
 
- The Wumpus will eat you if it sees you.
- Two of the chambers are bottomless pits.
- There are two giant bats that will transport you to a random chamber.
 
You can smell the Wumpus from an adjoining chamber. It smells terrible.
When you are in a chamber next to a bottomless pit you can feel a cold wind.
You can hear the giant bats rustle from a chamber away.
 
You are equipped with five progammable arrows.
They can be programmed with up to five adjoining chambers.
If a destination is invalid the arrow will move to a random adjoining chamber.
 
Be careful! Do not shoot yourself. Wumpus anasthetic is lethal to humans.
If you miss the Wumpus it will probably wake and move to an adjoining chamber.
 
You are in chamber 13.
Adjacent chambers are: 3, 12, and 14.
You have 5 arrows.
You feel a cold wind blowing from a nearby chamber.
Move or shoot? m
Move to which chamber? 12
 
You are in chamber 12.
Adjacent chambers are: 11, 13, and 19.
You have 5 arrows.
You hear a rustling.
Move or shoot? m
Move to which chamber? 19
 
You are in chamber 19.
Adjacent chambers are: 12, 15, and 18.
You have 5 arrows.
Move or shoot? m
Move to which chamber? 12
 
You are in chamber 12.
Adjacent chambers are: 11, 13, and 19.
You have 5 arrows.
You hear a rustling.
Move or shoot? m
Move to which chamber? 11
 
A giant bat transports you to chamber 18.
You are in chamber 18.
Adjacent chambers are: 10, 17, and 19.
You have 5 arrows.
Move or shoot? s
Shoot into which chambers? 10 18 17 8 0
The arrow enters chamber 10.
The arrow enters chamber 18.
You shot yourself.
</pre>
 
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 1,505 ⟶ 4,042:
(let ([current-game-state (new-game-state)])
(game-loop current-game-state)))
</syntaxhighlight>
</lang>
 
<langsyntaxhighlight lang="cmd">
Start the game with
 
Line 1,519 ⟶ 4,056:
 
S 2
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
See [[Hunt the Wumpus/Raku]]
 
=={{header|Red}}==
<syntaxhighlight lang="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 block
player: 1
wumpus: 2
pit-1: 3
pit-2: 4
bats-1: 5
bats-2: 6
 
 
start-loc: []
loc: []
winner: none
finished: 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 TO
OTHER 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 move
wumpus-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
</syntaxhighlight>
 
=={{header|Ruby}}==
Line 1,526 ⟶ 4,394:
=={{header|Rust}}==
See [[Hunt_The_Wumpus/Rust]].
 
=={{header|SenseTalk}}==
<syntaxhighlight lang="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 ITEMS
set locations to the randomLocations
set 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 locations
end 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 result
end winOrLose
 
 
-- INSTRUCTIONS
to handle showInstructions
answer {{
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'
 
}}
end showInstructions
 
 
-- PRINT LOCATION & HAZARD WARNINGS
to 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 ROUTINE
to 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 ROUTINE
to 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 empty
end moveWumpus
 
 
-- MOVE ROUTINE
to 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 if
end move
</syntaxhighlight>
 
=={{Header|Shale}}==
<syntaxhighlight lang="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 library
file library
string library
 
playerRoom var
wumpusRoom var
pit1Room var
pit2Room var
bat1Room var
bat2Room var
arrows var
wumpusIsAwake var
showStats var
statPlayer var
statWumpus var
statPit var
statArrow var
 
haveWon var
haveDied 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()
</syntaxhighlight>
 
=={{header|SparForte}}==
As a structured script.
<syntaxhighlight lang="ada">#!/usr/local/bin/spar
-- HUNT THE WUMPUS
 
pragma annotate( summary, "wumpus" );
pragma annotate( description, "Hunt the Wumpus" );
pragma annotate( description, "Originally for the PDP-8." );
pragma annotate( description, "The Timeless cave-crawling classic based on GW-BASIC source" );
pragma annotate( description, "www.ifarchive.org. Modified for SparForte by Ken O. Burtch." );
pragma annotate( description, "For sound effects, run as superuser" );
pragma annotate( author, "Ken O. Burtch" );
pragma license( unrestricted );
 
pragma ada_95; -- strict programming practices
pragma restriction( no_external_commands ); -- O/S independent
 
procedure wumpus is
 
type player_status is ( alive, won, lost );
status : player_status := alive; -- playing, winner, loser (was "f")
 
t_delim : constant character := ",";
tunnels : array(1..20) of string; -- adjacent room list
 
arrows : integer; -- number of arrows (was "a")
i : string; -- user input
player_room : positive; -- player room (was "l")
k : natural;
arrow_path : array(1..5) of positive; -- list of rooms for arrow (was "p")
 
type room_contents is ( player, wumpus, pit1, pit2, bats1, bats2 );
type room_list is array( player..bats2 ) of positive;
room : room_list; -- room contents (was "l()")
original_room : room_list; -- initial contents (was "m()")
 
good : boolean; -- for searches
soundfx : boolean := false;
 
begin
 
put_line( "HUNT THE WUMPUS" );
 
put( "SOUND EFFECTS (Y-N)? " );
i := get_line;
if i = "Y" or i = "y" then
soundfx := true;
end if;
 
put( "INSTRUCTIONS (Y-N)? " );
i := get_line;
if i = "Y" or i = "y" then
put_line( "WELCOME TO 'HUNT THE WUMPUS'" );
put_line( " THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM" );
put_line( "HAS 3 TUNNELS LEADING TO OTHER ROOMS. (LOOK AT A" );
put_line( "DODECAHEDRON TO SEE HOW THIS WORKS-IF YOU DON'T KNOW" );
put_line( "WHAT A DODECAHEDRON IS, ASK SOMEONE)" );
new_line;
put_line( " HAZARDS:" );
put_line( " BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM" );
put_line( " IF YOU GO THERE, YOU FALL INTO THE PIT (& LOSE!)" );
put_line( " SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU" );
put_line( " GO THERE, A BAT GRABS YOU AND TAKES YOU TO SOME OTHER" );
put_line( " ROOM AT RANDOM. (WHICH MAY BE TROUBLESOME)" );
new_line;
put_line( " WUMPUS:" );
put_line( " THE WUMPUS IS NOT BOTHERED BY HAZARDS (HE HAS SUCKER" );
put_line( " FEET AND IS TOO BIG FOR A BAT TO LIFT). USUALLY" );
put_line( " HE IS ASLEEP. TWO THINGS WAKE HIM UP: YOU SHOOTING AN" );
put_line( " ARROW OR YOU ENTERING HIS ROOM." );
put_line( " IF THE WUMPUS WAKES HE MOVES (P=.75) ONE ROOM" );
put_line( " OR STAYS STILL (P=.25). AFTER THAT, IF HE IS WHERE YOU" );
put_line( " ARE, HE EATS YOU UP AND YOU LOSE!" );
new_line;
put_line( "HIT RETURN TO CONTINUE" );
i := get_line;
put_line( " YOU:" );
put_line( " EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW" );
put_line( " MOVING: YOU CAN MOVE ONE ROOM (THRU ONE TUNNEL)" );
put_line( " ARROWS: YOU HAVE 5 ARROWS. YOU LOSE WHEN YOU RUN OUT" );
put_line( " EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING" );
put_line( " THE COMPUTER THE ROOM#S YOU WANT THE ARROW TO GO TO." );
put_line( " IF THE ARROW CAN'T GO THAT WAY (IF NO TUNNEL) IT MOVES" );
put_line( " AT RANDOM TO THE NEXT ROOM." );
put_line( " IF THE ARROW HITS THE WUMPUS, YOU WIN." );
put_line( " IF THE ARROW HITS YOU, YOU LOSE." );
put_line( "HIT RETURN TO CONTINUE" );
i := get_line;
put_line( " WARNINGS:" );
put_line( " WHEN YOU ARE ONE ROOM AWAY FROM A WUMPUS OR HAZARD," );
put_line( " THE COMPUTER SAYS:" );
put_line( " WUMPUS: 'I SMELL A WUMPUS'" );
put_line( " BAT : 'BATS NEARBY'" );
put_line( " PIT : 'I FEEL A DRAFT'" );
end if;
 
-- *** SET UP CAVE (DODECAHEDRAL NODE LIST) ***
-- dim tunnels(20,3) but SparForte has no true 2-d arrays. So we'll fake-it using
-- 1-D arrays and text fields
 
tunnels(1) := "2,5,8";
tunnels(2) := "1,3,10";
tunnels(3) := "2,4,12";
tunnels(4) := "3,5,14";
tunnels(5) := "1,4,6";
tunnels(6) := "5,7,15";
tunnels(7) := "6,8,17";
tunnels(8) := "1,7,9";
tunnels(9) := "8,10,18";
tunnels(10) := "2,9,11";
tunnels(11) := "10,12,19";
tunnels(12) := "3,11,13";
tunnels(13) := "12,14,20";
tunnels(14) := "4,13,15";
tunnels(15) := "6,14,16";
tunnels(16) := "15,17,20";
tunnels(17) := "7,16,18";
tunnels(18) := "9,17,19";
tunnels(19) := "11,18,20";
tunnels(20) := "13,16,19";
 
-- *** LOCATE L ARRAY ITEMS ***
-- *** 1-YOU, 2-WUMPUS, 3&4-PITS, 5&6-BATS ***
 
loop
good := true;
for j in player..bats2 loop
room(j) := numerics.rnd(20);
original_room(j) := room(j);
end loop;
 
-- *** CHECK FOR CROSSOVERS (IE la(1)=la(2), ETC) ***
 
for j in player..bats2 loop
for k in player..bats2 loop
if j /= k then
if room(j) = room(k) then
good := false;
end if;
end if;
end loop;
end loop;
exit when good;
end loop;
 
-- *** SET NO. OF ARROWS ***
 
arrows := 5;
player_room := room(player);
 
-- *** RUN THE GAME ***
 
-- *** PRINT LOCATION & HAZARD WARNINGS ***
 
loop
 
new_line;
put_line( "YOU ARE IN ROOM " & strings.image( room(player) ) );
good := false; -- don't play bats twice
for j in wumpus..bats2 loop
for k in 1..3 loop
if numerics.value( strings.field( tunnels(room(player)), k, t_delim ) ) = room(j) then
case j is
when wumpus => put_line( "I SMELL A WUMPUS!" );
when pit1 => put_line( "I FEEL A DRAFT" );
when pit2 => put_line( "I FEEL A DRAFT" );
when bats1 => put_line( "BATS NEARBY!" );
if not good and soundfx then
sound.play( "./bats.wav" );
good := true;
end if;
when bats2 => put_line( "BATS NEARBY!" );
if not good and soundfx then
sound.play( "./bats.wav" );
good := true;
end if;
when others => put_line( "<<unexpected case j value>>" );
end case;
end if;
end loop;
end loop;
 
put_line( "TUNNELS LEAD TO " &
strings.field( tunnels(player_room), 1, t_delim) & " " &
strings.field( tunnels(player_room), 2, t_delim) & " " &
strings.field( tunnels(player_room), 3, t_delim) );
new_line;
 
-- Main Loop
-- *** MOVE OR SHOOT ***
 
loop
put( "SHOOT OR MOVE (S-M)" );
i := get_line;
if i = "S" or i = "s" then
i := "1";
exit;
elsif i = "M" or i = "m" then
i := "2";
exit;
end if;
end loop;
 
if i = "1" then
 
-- *** ARROW ROUTINE ***
 
declare
arrow_path_length : integer; -- was "j9"
begin
-- *** PATH OF ARROW ***
status := alive;
loop
put( "NO. OF ROOMS (1-5)" );
arrow_path_length := numerics.value( get_line );
exit when arrow_path_length >= 1 and arrow_path_length <= 5;
end loop;
 
for k in 1..arrow_path_length loop
loop
put( "ROOM #" );
arrow_path(k) := numerics.value( get_line );
exit when k <= 2;
exit when arrow_path(k) /= arrow_path(k-2);
put_line( "ARROWS AREN'T THAT CROOKED - TRY ANOTHER ROOM" );
end loop;
end loop;
 
-- *** SHOOT ARROW ***
 
good := false;
player_room := room(player);
for k in 1..arrow_path_length loop
for k1 in 1..3 loop
if numerics.value( strings.field( tunnels(player_room), k1, t_delim)) = arrow_path(k) then
good := true;
player_room := arrow_path(k);
if soundfx then
sound.play( "./arrow.wav" );
end if;
if player_room = room(wumpus) then
put_line( "AHA! YOU GOT THE WUMPUS!" );
status := won;
elsif player_room = room(player) then
put_line( "OUCH! ARROW GOT YOU!" );
if soundfx then
sound.play( "./scream.wav" );
end if;
status := lost;
end if;
end if;
end loop; -- k1
 
-- *** NO TUNNEL FOR ARROW ***
-- pick random direction
 
if not good then
player_room := numerics.value( strings.field( tunnels(player_room), numerics.rnd(3), t_delim ) );
 
if player_room = room(wumpus) then
put_line( "AHA! YOU GOT THE WUMPUS!" );
status := won;
elsif player_room = room(player) then
put_line( "OUCH! ARROW GOT YOU!" );
if soundfx then
sound.play( "./scream.wav" );
end if;
status := lost;
end if;
end if;
end loop; -- k
end; -- shoot declarations
 
player_room := room(player); -- player_room now player again
if status = alive then
put_line( "MISSED" );
 
-- MOVE THE WUMPUS
 
k := natural( numerics.rnd(4) );
if k /= 4 then
room(wumpus) := numerics.value( strings.field( tunnels(room(wumpus)), k, t_delim) );
if player_room = room(wumpus) then
put_line( "TSK TSK TSK - WUMPUS GOT YOU!" );
if soundfx then
sound.play( "./scream.wav" );
end if;
status := lost;
end if;
end if;
 
arrows := arrows-1;
if arrows < 1 then
put_line( "THE HUNT IS OVER. THAT WAS YOUR LAST ARROW" );
status := lost;
end if;
end if;
 
elsif i = "2" then -- move player
 
-- *** MOVE ROUTINE ***
status := alive;
loop
loop
put( "WHERE TO?" );
player_room := numerics.value( get_line );
exit when player_room >= 1 and player_room <= 20;
end loop;
-- *** CHECK IF LEGAL MOVE ***
 
if player_room = room(player) then
good := true;
else
good := false;
for k in 1..3 loop
if numerics.value( strings.field( tunnels(room(player)), k, t_delim) ) = player_room then
good := true;
end if;
end loop;
end if;
if good then
if soundfx then
sound.play( "./run.wav" );
end if;
loop
room(player) := player_room;
if player_room = room(wumpus) then
put_line( "... OOPS! BUMPED A WUMPUS!" );
k := natural( numerics.rnd(4) );
if k /= 4 then
room(wumpus) := numerics.value( strings.field( tunnels(room(wumpus)), k, t_delim) );
if player_room = room(wumpus) then
put_line( "TSK TSK TSK - WUMPUS GOT YOU!" );
if soundfx then
sound.play( "./run.wav" );
end if;
status := lost;
end if;
end if;
exit;
elsif player_room = room(pit1) or player_room = room(pit2) then
put_line( "YYYYIIIIEEEE . . . FELL IN PIT" );
if soundfx then
sound.play( "./pit.wav" );
end if;
status := lost;
exit;
elsif player_room = room(bats1) or player_room = room(bats2) then
put_line( "ZAP--SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!" );
if soundfx then
sound.play( "./bats.wav" );
end if;
player_room := numerics.rnd(20);
else
exit;
end if;
end loop; -- bat loop
exit;
else
put( "NOT POSSIBLE -" );
end if;
end loop; -- good move loop
 
end if; -- if move or shoot
 
if status /= alive then
if status = lost then
-- *** LOSE ***
put_line( "HA HA HA - YOU LOSE!" );
else
-- *** WIN ***
put_line( "HEE HEE HEE - THE WUMPUS'LL GET YOU NEXT TIME!!" );
if soundfx then
sound.play( "./clap.wav" );
end if;
end if;
for j in player..bats2 loop
room(j) := original_room(j);
end loop;
return; -- restart not done
-- restart not done
--put( "SAME SETUP (Y-N)" );
--i := get_line;
--365 if (i$ <> "Y") and (i$ <> "y") then 170
end if;
end loop; -- main loop
 
end wumpus;
</syntaxhighlight>
 
=={{header|Swift}}==
{{trans|Go}}
<syntaxhighlight lang="swift">
import Foundation
 
//All rooms in cave
var 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 room
var player: Int = 0, wumpus: Int = 0, bat1:Int = 0, bat2:Int = 0, pit1:Int = 0, pit2:Int = 0
 
//number of arrows left
var arrows = 5
 
//check if room is empty
func 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 rooms
func 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 message
func 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()
 
</syntaxhighlight>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-fmt}}
{{libheader|Wren-ioutil}}
{{libheader|Wren-str}}
<syntaxhighlight lang="wren">import "random" for Random
import "./fmt" for Fmt
import "./ioutil" for Input
import "./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 player
var wumpus
var batt1
var bat2
var pit1
var pit2
var 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 = 1
wumpus = 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
}
}
}</syntaxhighlight>
9,476

edits