Hunt the Wumpus Code

Original Wumpus artwork
I had a great time coding Hunt the Wumpus. Like most programming challenges, it was fun, exciting, and frustrating all at once. Some code ran beautifully the first time. Other code contained silly mistakes that bogged me down. And solutions unveiled themselves magically like a sugar cube dissolving in water.

My solution, which you can view on GitHub in its entirety, runs at just under 400 lines of code. A lot of the code is commentary and documentation, which I find necessary for a large project. No way I’m keeping all those details in my head!

I use two defined constants:

#define ROOMS 20
#define SIZE 32

ROOMS sets the size of the labyrinth, SIZE is used for text input.

I also created two sets of enumerated constants:

enum { FALSE, TRUE };

The first set is used for the labyrinth[] array and the second for various Booleans throughout the code.

Here are the functions as they appear in the code, top-down. I wrote these in the order in which they appear:

void prep_room( int laby[], int c, int pp )

This function populates a room in the labyrinth (argument laby[]) with a BAT, PIT, or WUMPUS, represented by argument c. Argument pp represents the player’s position. The goal is to set an item into to an empty chamber. This function is called to initialize the labyrinth array, but also to move a BAT or the WUMPUS as required.

char getinput(void)

This function processes input, eating a line from the stream and returning only the first character. The ? character (for the Help command) is filtered out, otherwise the character returned is converted to uppercase.

int player_alive(int laby[],int pp)

Here the player’s position (pp) is tested in the array (laby[]) to determine whether the WUMPUS or a PIT is stumbled upon. If so, the function returns FALSE; the player is no longer alive.

void shot_missed(int laby[],int pp)

When an arrow is fired and it doesn’t hit the wumpus, there is a 75-percent chance the wumpus moves. This function handles the situation, setting the wumpus in a new, random room — or not.

int arrow_loose(int laby[], int pp, char direction)

This function is rather complex, prompting the player to shoot an arrow into one of the rooms, Left, Right, or Back. It handles the situation if the arrow misses and deals with bad input. If the shot does miss, the shot_missed() function is called. If the arrow hits, the function returns TRUE, which is processed as a victory in the main() function.

int bat_move(int laby[],int pp)

When the player moves into a room with a bat, his position is relocated. This function moves the player into an unoccupied room, but also moves the bat into an unoccupied room.

int main()

Beyond the items mentioned in last week’s Lesson, the main() function handles the player’s condition, player.alive, as well as player.won and player.arrows. The status of these items determines when the endless while loop breaks and the game is over.

After the loop, messages are output depending on whether the player won or has died. (Running out of arrows is equivalent to dying.)

Due to the addicting nature of programming, it’s difficult to let a large project go. My implementation of Hunt the Wumpus is no exception. I’d enjoy adding more flowery language to describe the maze, but I sought to code the game as close to the original as I could, based on the data I gathered elsewhere. Big projects are fun, and one of the joys of programming is the satisfaction you receive when the task is complete.

Leave a Reply