//////////////////////////////////////////////////////////////////////////////
//
// _ _________ _________ _______
// |\ /||\ /|( ( /|\__ __/ \__ __/|\ /|( ____ \
// | ) ( || ) ( || \ ( | ) ( ) ( | ) ( || ( \/
// | (___) || | | || \ | | | | | | | (___) || (__
// | ___ || | | || (\ \) | | | | | | ___ || __)
// | ( ) || | | || | \ | | | | | | ( ) || (
// | ) ( || (___) || ) \ | | | | | | ) ( || (____/\
// |/ \|(_______)|/ )_) )_( )_( |/ \|(_______/
//
// _______ _______ _______
// |\ /||\ /|( )( ____ )|\ /|( ____ \
// | ) ( || ) ( || () () || ( )|| ) ( || ( \/
// | | _ | || | | || || || || (____)|| | | || (_____
// | |( )| || | | || |(_)| || _____)| | | |(_____ )
// | || || || | | || | | || ( | | | | ) |
// | () () || (___) || ) ( || ) | (___) |/\____) |
// (_______)(_______)|/ \||/ (_______)\_______)
//
// Version 1.0
//
// October 13, 2007
//
// COPYRIGHT:
//
// "Hunt the Wumpus" (LSL Port)
// Copyright (C) 2007 Hugsy Penguin
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// ORIGINAL CONCEPT:
//
// By: Gregory Yob circa 1973
// Published By: People's Computer Company
// Published In: newsletter dated November 1973
//
// Republished:
//
// Magazine: Creative Computing
// Issue: September/October 1975
// Article: "Hunt the Wumpus"
// By: Gregory Yob
//
// "The Best of Creative Computing Volume 1"
// Edited by David H. Ahl
// 1976
// ISBN O-916688-01-1
//
/////////////////////////////////////////////////////////////////////////////
 
//---------------------------------------------------------------------------
// Globals
//---------------------------------------------------------------------------
integer gDEBUG = FALSE;
 
list gCave;
integer gLocPlayer;
integer gHoldPlayer;
integer gLocWumpus;
integer gHoldWumpus;
integer gLocPit1;
integer gHoldPit1;
integer gLocPit2;
integer gHoldPit2;
integer gLocBat1;
integer gHoldBat1;
integer gLocBat2;
integer gHoldBat2;
integer gNumArrows;
integer gStatus;
 
//
// Debug method(s)
//
DBGPrintLocs()
{
llSay(0, "gLocPlayer = " + (string)gLocPlayer);
llSay(0, "gLocWumpus = " + (string)gLocWumpus);
llSay(0, "gLocPit1 = " + (string)gLocPit1);
llSay(0, "gLocPit2 = " + (string)gLocPit2);
llSay(0, "gLocBat1 = " + (string)gLocBat1);
llSay(0, "gLocBat2 = " + (string)gLocBat2);
}
 
//
// Initialize the script.
//
Initialize()
{
llSetObjectName("");
 
//setup cave (dodecahedral node list)
gCave = [
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];
 
SetupNewGame(FALSE);
}
 
SetupNewGame(integer restore)
{
gNumArrows = 5;
gStatus = 0;
 
if (restore == TRUE)
{
gLocPlayer = gHoldPlayer;
gLocWumpus = gHoldWumpus;
gLocPit1 = gHoldPit1;
gLocPit2 = gHoldPit2;
gLocBat1 = gHoldBat1;
gLocBat2 = gHoldBat2;
}
else
{
//player location
gLocPlayer = (integer)(llFrand(20) + 1);
 
//wumpus location
integer done = FALSE;
while (!done)
{
gLocWumpus = (integer)(llFrand(20) + 1);
if (gLocWumpus != gLocPlayer)
done = TRUE;
}
 
//pit 1 location
done = FALSE;
while (!done)
{
gLocPit1 = (integer)(llFrand(20) + 1);
if ((gLocPit1 != gLocPlayer) &&
(gLocPit1 != gLocWumpus))
{
done = TRUE;
}
}
 
//pit 2 location
done = FALSE;
while (!done)
{
gLocPit2 = (integer)(llFrand(20) + 1);
if ((gLocPit2 != gLocPlayer) &&
(gLocPit2 != gLocWumpus) &&
(gLocPit2 != gLocPit1))
{
done = TRUE;
}
}
 
//bat 1 location
done = FALSE;
while (!done)
{
gLocBat1 = (integer)(llFrand(20) + 1);
if ((gLocBat1!= gLocPlayer) &&
(gLocBat1!= gLocWumpus) &&
(gLocBat1!= gLocPit1) &&
(gLocBat1!= gLocPit2))
{
done = TRUE;
}
}
 
//bat 2 location
done = FALSE;
while (!done)
{
gLocBat2 = (integer)(llFrand(20) + 1);
if ((gLocBat2!= gLocPlayer) &&
(gLocBat2!= gLocWumpus) &&
(gLocBat2!= gLocPit1) &&
(gLocBat2!= gLocPit2) &&
(gLocBat2!= gLocBat1))
{
done = TRUE;
}
}
 
gHoldPlayer = gLocPlayer;
gHoldWumpus = gLocWumpus;
gHoldPit1 = gLocPit1;
gHoldPit2 = gLocPit2;
gHoldBat1 = gLocBat1;
gHoldBat2 = gLocBat2;
}
}
 
//
// Returns the room based on given values:
//
// x = room number (range: 1-20)
// y = adjacent room index (range: 1-3)
//
integer RoomAt(integer x, integer y)
{
x--;
y--;
integer index = (x * 3) + y;
return llList2Integer(gCave, index);
}
 
//
// Print player location and nearby hazards
//
PrintLocAndHaz()
{
if (gDEBUG == TRUE)
DBGPrintLocs();
 
integer i;
 
//check for wumpus
for (i = 1; i < 4; i++)
{
if (RoomAt(gLocPlayer, i) == gLocWumpus)
{
llSay(0, "I SMELL A WUMPUS!");
}
}
 
//check for pit 1
for (i = 1; i < 4; i++)
{
if (RoomAt(gLocPlayer, i) == gLocPit1)
{
llSay(0, "I FEEL A DRAFT");
}
}
 
//check for pit 2
for (i = 1; i < 4; i++)
{
if (RoomAt(gLocPlayer, i) == gLocPit2)
{
llSay(0, "I FEEL A DRAFT");
}
}
 
//check for bat 1
for (i = 1; i < 4; i++)
{
if (RoomAt(gLocPlayer, i) == gLocBat1)
{
llSay(0, "BATS NEARBY!");
}
}
 
//check for bat 2
for (i = 1; i < 4; i++)
{
if (RoomAt(gLocPlayer, i) == gLocBat2)
{
llSay(0, "BATS NEARBY!");
}
}
 
llSay(0, "YOU ARE IN ROOM " + (string)gLocPlayer);
llSay(0, "TUNNELS LEAD TO " + (string)RoomAt(gLocPlayer, 1)
+ " " + (string)RoomAt(gLocPlayer, 2)
+ " " + (string)RoomAt(gLocPlayer, 3));
 
}
 
integer MoveWumpus()
{
integer dir = (integer)(llFrand(4) + 1);
 
if (dir != 4)
{
gLocWumpus = RoomAt(gLocWumpus, dir);
}
 
if (gLocPlayer == gLocWumpus)
{
llSay(0, "TSK TSK TSK- WUMPUS GOT YOU!");
return -1;
}
 
return 0;
}
 
//---------------------------------------------------------------------------
// Globals for shooting
//---------------------------------------------------------------------------
 
integer gShootingNumRooms;
integer gShootingRoom1;
integer gShootingRoom2;
integer gShootingRoom3;
integer gShootingRoom4;
integer gShootingRoom5;
integer gShootingCurRoom;
 
SetShootingRoom(integer index, integer value)
{
if (index == 1) gShootingRoom1 = value;
if (index == 2) gShootingRoom2 = value;
if (index == 3) gShootingRoom3 = value;
if (index == 4) gShootingRoom4 = value;
if (index == 5) gShootingRoom5 = value;
}
 
integer GetShootingRoom(integer index)
{
if (index == 1) return gShootingRoom1;
if (index == 2) return gShootingRoom2;
if (index == 3) return gShootingRoom3;
if (index == 4) return gShootingRoom4;
if (index == 5) return gShootingRoom5;
return 0;
}
 
ShootArrow()
{
integer loc = gLocPlayer;
integer i;
integer j;
 
for (i = 1; i <= gShootingNumRooms; i++)
{
//determine which room to check next
integer validRoom = FALSE;
for (j = 1; j <= 3; j++)
{
if (RoomAt(loc, j) == GetShootingRoom(i))
{
validRoom = TRUE;
loc = GetShootingRoom(i);
}
}
 
if (!validRoom)
{
loc = RoomAt(loc, (integer)(llFrand(3) + 1));
}
 
//check the room for wumpus or player
if (loc == gLocWumpus)
{
llSay(0, "AHA! YOU GOT THE WUMPUS!");
gStatus = 1;
}
else if (loc == gLocPlayer)
{
llSay(0, "OUCH! ARROW GOT YOU!");
gStatus = -1;
}
 
//return if in win or lose state
if (gStatus != 0)
return;
}
 
llSay(0, "MISSED");
 
//move wumpus
gStatus = MoveWumpus();
if (gStatus != 0)
return;
 
//ammo check
gNumArrows--;
if (gNumArrows == 0)
gStatus = -1;
}
 
//---------------------------------------------------------------------------
// Globals for moving
//---------------------------------------------------------------------------
 
MoveTo(integer loc)
{
gLocPlayer = loc;
 
if (gLocPlayer == gLocWumpus)
{
llSay(0, "... OOPS! BUMPED A WUMPUS!");
gStatus = MoveWumpus();
}
else if ((gLocPlayer == gLocPit1) || (gLocPlayer == gLocPit2))
{
llSay(0, "YYYIIIIEEEE . . . FELL IN PIT");
gStatus = -1;
}
else if ((gLocPlayer == gLocBat1) || (gLocPlayer == gLocBat2))
{
llSay(0, "ZAP--SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!");
MoveTo((integer)(llFrand(20) + 1));
}
}
 
//################################################## ##########################
//
// GAME STATES
//
//################################################## ##########################
 
//----------------------------------------------------------------------------
// state default
//----------------------------------------------------------------------------
default
{
state_entry()
{
Initialize();
state instructions;
}
 
on_rez(integer start_param)
{
Initialize();
state instructions;
}
}
 
//----------------------------------------------------------------------------
// state instructions
//----------------------------------------------------------------------------
state instructions
{
state_entry()
{
llSay(0, "INSTRUCTIONS (Y-N)?");
llListen(0, "", llGetOwner(), "");
}
 
on_rez(integer start_param)
{
state default;
}
 
listen(integer channel, string name, key id, string message)
{
if (llToLower(message) != "n")
{
llSay(0, "WELCOME TO 'HUNT THE WUMPUS'");
llSay(0, " ");
llSay(0, " THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM");
llSay(0, "HAS 3 TUNNELS LEADING TO OTHER ROOMS. (LOOK AT A");
llSay(0, "DODECAHEDRON TO SEE HOW THIS WORKS-IF YOU DON'T KNOW");
llSay(0, "WHAT A DODECAHEDRON IS, ASK SOMEONE)");
llSay(0, " ");
llSay(0, " HAZARDS:");
llSay(0, " BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM");
llSay(0, " IF YOU GO THERE, YOU FALL INTO THE PIT (&LOSE!)");
llSay(0, " SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU");
llSay(0, " GO THERE, A BAT GRABS YOU AND TAKES YOU TO SOME OTHER");
llSay(0, " ROOM AT RANDOM. (WHICH MIGHT BE TROUBLESOME)");
llSay(0, " ");
llSay(0, " WUMPUS:");
llSay(0, " THE WUMPUS IS NOT BOTHERED BY THE HAZARDS (HE HAS SUCKER");
llSay(0, " FEET AND IS TOO BIG FOR A BAT TO LIFT). USUALLY");
llSay(0, " HE IS ASLEEP. TWO THINGS WAKE HIM UP: YOUR ENTERING");
llSay(0, " HIS ROOM OR YOUR SHOOTING AN ARROW.");
llSay(0, " IF THE WUMPUS WAKES, HE MOVES (P=.75) ONE ROOM");
llSay(0, " OR STAYS STILL (P=.25). AFTER THAT, IF HE IS WHERE YOU");
llSay(0, " ARE, HE EATS YOU UP (& YOU LOSE!)");
llSay(0, " ");
llSay(0, " YOU:");
llSay(0, " EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW");
llSay(0, " MOVING: YOU CAN GO ONE ROOM (THRU ONE TUNNEL)");
llSay(0, " ARROWS: YOU HAVE 5 ARROWS. YOU LOSE WHEN YOU RUN OUT.");
llSay(0, " EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING");
llSay(0, " THE COMPUTER THE ROOMS YOU WANT THE ARROW TO GO TO.");
llSay(0, " IF THE ARROW CAN'T GO THAT WAY(IE NO TUNNEL) IT MOVES");
llSay(0, " AT RANDOM TO THE NEXT ROOM.");
llSay(0, " IF THE ARROW HITS THE WUMPUS, YOU WIN.");
llSay(0, " IF THE ARROW HITS YOU, YOU LOSE.");
llSay(0, " ");
llSay(0, " WARNINGS:");
llSay(0, " WHEN YOU ARE ONE ROOM AWAY FROM WUMPUS OR HAZARD,");
llSay(0, " THE COMPUTER SAYS:");
llSay(0, " WUMPUS- 'I SMELL A WUMPUS'");
llSay(0, " BAT - 'BATS NEARBY'");
llSay(0, " PIT - 'I FEEL A DRAFT'");
llSay(0, " ");
}
 
llSay(0, "HUNT THE WUMPUS");
llSay(0, " ");
state run_game;
}
}
 
//----------------------------------------------------------------------------
// state run_game
//----------------------------------------------------------------------------
state run_game
{
state_entry()
{
PrintLocAndHaz();
llSay(0, "SHOOT OR MOVE (S-M)?");
llListen(0, "", llGetOwner(), "");
}
 
on_rez(integer start_param)
{
state default;
}
 
listen(integer channel, string name, key id, string message)
{
if (llToLower(message) == "s")
{
state shooting_num_rooms;
}
else if (llToLower(message) == "m")
{
state moving_where_to;
}
else if (llToLower(message) == "debug")
{
gDEBUG = !gDEBUG;
llSay(0, "DEBUG MODE IS NOW " + (string)gDEBUG);
}
else
{
llSay(0, "SHOOT OR MOVE (S-M)?");
}
}
}
 
state end_game
{
state_entry()
{
if (gStatus == 1)
{
llSay(0, "HEE HEE HEE - THE WUMPUS'LL GETCHA NEXT TIME!!");
}
else if (gStatus == -1)
{
llSay(0, "HA HA HA - YOU LOSE!");
}
 
llSay(0, "SAME SET-UP (Y-N)?");
llListen(0, "", llGetOwner(), "");
}
 
on_rez(integer start_param)
{
state default;
}
 
listen(integer channel, string name, key id, string message)
{
llSay(0, "HUNT THE WUMPUS");
llSay(0, " ");
 
if (llToLower(message) != "y")
{
SetupNewGame(FALSE);
}
else
{
SetupNewGame(TRUE);
}
 
state run_game;
}
}
 
//################################################## ##########################
//
// SHOOTING
//
//################################################## ##########################
 
//----------------------------------------------------------------------------
// state shooting_num_rooms
//----------------------------------------------------------------------------
 
state shooting_num_rooms
{
state_entry()
{
llSay(0, "NO. OF ROOMS(1-5)?");
llListen(0, "", llGetOwner(), "");
}
 
on_rez(integer start_param)
{
state default;
}
 
listen(integer channel, string name, key id, string message)
{
gShootingNumRooms = (integer)message;
 
if ((gShootingNumRooms < 1) || (gShootingNumRooms > 5))
{
llSay(0, "NO. OF ROOMS(1-5)?");
}
else
{
state shooting_get_rooms;
}
}
}
 
//----------------------------------------------------------------------------
// state shooting_get_rooms
//----------------------------------------------------------------------------
 
state shooting_get_rooms
{
state_entry()
{
gShootingCurRoom = 1;
llSay(0, "ROOM #?");
llListen(0, "", llGetOwner(), "");
}
 
on_rez(integer start_param)
{
state default;
}
 
listen(integer channel, string name, key id, string message)
{
integer roomNum = (integer)message;
 
SetShootingRoom(gShootingCurRoom, roomNum);
 
if (gShootingCurRoom == gShootingNumRooms)
{
ShootArrow();
if (gStatus == 0)
{
state run_game;
}
state end_game;
}
 
if (gShootingCurRoom > 2)
{
if (GetShootingRoom(gShootingCurRoom) ==
GetShootingRoom(gShootingCurRoom - 2))
{
llSay(0, "ARROWS AREN'T THAT CROOKED - TRY ANOTHER ROOM");
}
}
 
gShootingCurRoom++;
llSay(0, "ROOM #?");
}
}
 
//################################################## ##########################
//
// MOVING
//
//################################################## ##########################
 
//----------------------------------------------------------------------------
// state moving_where_to
//----------------------------------------------------------------------------
 
state moving_where_to
{
state_entry()
{
llSay(0, "WHERE TO?");
llListen(0, "", llGetOwner(), "");
}
 
on_rez(integer start_param)
{
state default;
}
 
listen(integer channel, string name, key id, string message)
{
integer loc = (integer)message;
 
if ((loc < 1) || (loc > 20))
{
llSay(0, "WHERE TO?");
}
else
{
integer i;
for (i = 1; i <=3; i++)
{
if (RoomAt(gLocPlayer, i) == loc)
{
MoveTo(loc);
if (gStatus == 0)
{
state run_game;
}
state end_game;
}
}
 
llSay(0, "NOT POSSIBLE -WHERE TO?");
}
}
}