Hunt the Wumpus: Difference between revisions

m
m (→‎{{header|Raku}}: capitalization match)
m (→‎{{header|Wren}}: Minor tidy)
(3 intermediate revisions by 3 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 3,633:
[[1,2], [1,3], [1,4], [2,1], [2,5], [2,6], [3,1], ...]
</syntaxhighlight>
 
=={{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}}==
Line 4,914 ⟶ 5,120:
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>
 
Line 5,140 ⟶ 5,737:
{{libheader|Wren-ioutil}}
{{libheader|Wren-str}}
<syntaxhighlight lang="ecmascriptwren">import "random" for Random
import "./fmt" for Fmt
import "./ioutil" for Input
import "./str" for Str
 
var cave = {
9,476

edits