CSCI 200 - Spring 2023
Foundational Programming Concepts & Design

A2 - Watch the Wumpus

→This assignment is due by Friday, February 17, 2023, 11:59 PM.←
→ As with all assignments, this must be an individual effort and cannot be pair programmed. Any debugging assistance must follow the course collaboration policy and be cited in the comment header block for the assignment.←
→ Do not forget to complete the following labs with this set: L2A, L2B
→ Do not forget to complete zyBooks Assignment 2 for this set.←

· Instructions · Rubric ·Submission ·

For this assignment you will process the game history for a simulated game of Hunt the Wumpus. Your program will read in the contents of a custom game file and then write out a game log that displays the sequence of events from the game.


Hunt the Wumpus


In the game, the Hero is trying to hunt the Wumpus in a dark cave and shoot it with one of his crooked arrows. Every turn the Hero and Wumpus move. If the Hero and Wumpus end in the same location, then the Hero shoots the Wumpus and the game ends with the Hero winning. Beware! There is also a pit hiding in the cave. If either player falls into the pit, then the game ends as well. If after all moves the Wumpus still lives, then the Hero loses the game.

(Note: This is mostly how the game is played. For our purposes the gameplay has been slightly modified and simplified.)


Wumpus Game History (.wgh) File Format


A sample wgh file is shown below as viewed in a text editor:

5 5
W 4 4
H 1 3
P 2 2
10
W N
H E
W W
H N
W W
H W
W S
H S
W E
H E

The file is comprised of three sections:

  1. The cave size
  2. The object placements
  3. The move sequence

The first line contains the width and height of the cave. Both of these values will be integers. We can think of the cave as a grid with the southwest corner denoted by the coordinate (1, 1) and the northeast corner denoted by the coordinate (width, height). Note: These values will be within the range 1 ≤ w, h, ≤ 100.

The next three lines contain the starting locations of the Hero (H), Wumpus (W), and Pit (P). These lines can be in any order. After the character denoting which object is being placed, the integer (x, y) starting coordinate follows. Note: It is possible the character is something other than H, W, or P. It will be guaranteed that the (x, y) coordinate is within the range (1, 1) ≤ (w, h).

The remaining lines comprise the move sequence. The first line of this sections is an integer corresponding to the number of moves made. There will then follow an equal number of lines. The first character on the line denotes who is moving, the (H)ero or the (W)umpus. The next character then denotes which cardinal direction they are moving: (N)orth, (E)ast, (S)outh, or (W)est. Note: It is possible either character on the line may not be one of the expected values.

Several sample wgh files are provided with the starter pack for you to test with. You are encouraged to create your own Wumpus Game History files as well!


Instructions


For this assignment, we will write a program to read in a wgh file, process it, and then output a new log file. A starter code pack has been provided. Download and extract the source code. The source code package contains several items:

The contents of main.cpp are shown below:

/* CSCI 200: Assignment 2: A2 - Watch the Wumpus
 *
 * Author: Dr. Jeffrey Paone
 *
 * Starting template to process a Wumpus Game History (.wgh) file and
 * output the corresponding game log.
 *
 * DO NOT EDIT THIS FILE
 */

#include "wumpus_functions.h"

#include <fstream>
#include <iostream>
#include <string>
using namespace std;

int main() {
    const string WUMPUS_FILE_NAME = enter_wumpus_file();
    const string GAME_LOG_FILE_NAME = enter_game_log_file();

    ifstream wumpusFileIn;
    ofstream gameLogOut;

    if( !open_files(wumpusFileIn, gameLogOut, WUMPUS_FILE_NAME, GAME_LOG_FILE_NAME) ) {
        cerr << "Error opening files" << endl;
        return -1;
    }

    int caveWidth, caveHeight;
    read_world_header(wumpusFileIn, caveWidth, caveHeight);

    int wumpusX = -1, wumpusY = -1;
    int heroX = -1, heroY = -1;
    int pitX = -1, pitY = -1;
    if( !read_object_header(wumpusFileIn,
                            wumpusX, wumpusY,
                            heroX, heroY,
                            pitX, pitY) ) {
        cerr << "Not all objects placed in world" << endl;
        return -2;
    }

    int numMoves;
    read_number_moves(wumpusFileIn, numMoves);

    const bool PLAY_AS_HERO = choose_player();

    play_game(wumpusFileIn, gameLogOut,
              caveWidth, caveHeight,
              numMoves,
              wumpusX, wumpusY,
              heroX, heroY,
              pitX, pitY,
              PLAY_AS_HERO);

    return 0;
}

Our program now reads as a set of steps to perform. The steps are described below and then the function interface to implement these steps follow afterwards.


Program Flow


The execution follows as below.

Begin by prompting the user for which file they wish to read from.

Enter wumpus file to read from: 

Then prompt the user for which file they wish to write to.

Enter game log file to write to: 

Once we have two file names, open the corresponding input and output files. If either file cannot be opened, kindly alert the user and gracefully end the program. This should be testable if you attempt to read from private.wgh.

Now we're ready to start reading in the file and read the data!

We'll need to read the first two values (two integers) to know the size about our cave.

Next the object header (hero, wumpus, pit placement) needs to be read in. There will always be three lines in this section. If after reading the three lines one or more of the three objects have not been placed, then we'll need to alert the user the game is not properly setup and gracefully end the program.

Once we have the three objects placed, we'll ready how many turns we need to simulate.

In order to print the game log from the correct point of view, ask the user if they wish to play as the Hero or the Wumpus.

Who do you wish to play as?
        H - Hero
        W - Wumpus
Character: 

Be sure to validate that the user enters only H or W. If anything else is entered, then print Invalid choice, please select again. and reprompt the user.

Regardless of the user choice, its time to simulate the game. For each move, first determine who is moving - the Hero or the Wumpus. If the character is anything other than H or W, then ignore the rest of the line. Once we know which direction the Hero or Wumpus is moving, update their position accordingly:

If the Hero or Wumpus is at the edge of the cave, then do not let them move that direction. Print a message in the format of

C cannot move D.

Where C is Hero or Wumpus and D is the direction being moved.

Then after every move, print the current location in the format of

C is at (X, Y).

Where C is Hero or Wumpus and X, Y is current location.

If after any move the Hero or Wumpus falls into the pit (is at the same location as the pit), then display who fell in the pit and who wins the game.

If after any move the Hero and Wumpus are at the same location, then display the Hero kills the Wumpus and the Hero wins the game.

For all messages, replace Hero or Wumpus with You based on the role the user has chosen to play as. Therefore, possible messages to print are of the form:

The Hero cannot move D.
The Wumpus cannot move D.
You cannot move D.

The Hero is at (X, Y).
The Wumpus is at (X, Y).
You are at (X, Y).

You have killed the Wumpus.  You win!
You have been killed by the Hero.  You lose.

The Hero has fallen in the pit.  You win!
The Wumpus has fallen in the pit.  You win!
You have fallen in the pit.  You lose.

You have evaded the Hero.  You win!
The Wumpus has evaded you.  You lose.

All messages will be logged to the output file and every message must match the corresponding template exactly as appropriate. See the solutions/ folder in the starter pack for expected output.


Code Structure & Functions


We will want to implement this program in a procedural style using functions. These functions will be declared in a separate wumpus_functions.h file with their implementations defined in a corresponding wumpus_functions.cpp file. Create, and use, the following functions:

    • Name: enter_wumpus_file()
    • Input: None
    • Output: string
    • Description: Prompts the user for the .wgh file to open.

    • Name: enter_game_log_file()
    • Input: None
    • Output: string
    • Description: Prompts the user for the .log file to open.

    • Name: open_files()
    • Input: an ifstream object to open, an ofstream object to open, a string corresponding to the file to read from, a string corresponding to the file to write to
    • Output: true if both files successfully opened, false otherwise
    • Description: Opens the corresponding files for reading and writing based on the file names provided. Verifies that both files successfully opened, returning true if so. Otherwise, if either file failed to open, returns false. (Hint: this can be tested by trying to open the private test file which doesn't exist in the starter pack.)

    • Name: read_world_header()
    • Input: an ifstream object to read from, integers corresponding to the width & height passed by reference
    • Output: None
    • Description: Reads the cave size information of the file (the first two values). Upon completion, the parameters corresponding to the width & height will match the values read from the file.

    • Name: read_object_header()
    • Input: an ifstream object to read from, six integers corresponding to the (X, Y) location of the wumpus, hero, and pit respectively passed by reference
    • Output: true if all three objects are placed within the cave, false otherwise
    • Description: Reads the object header information of the file (the next six values). Upon completion, the parameters corresponding to the (X, Y) location of each object will correspond to the values read from the file.

    • Name: read_number_moves()
    • Input: an ifstream object to read from, an integer corresponding to the number of moves that follow passed by reference
    • Output: None
    • Description: Reads the number of moves information of the file (the next values). Upon completion, the parameter corresponding to the number of moves will match the value read from the file.

    • Name: choose_player()
    • Input: None
    • Output: true if the user wishes to be the Hero, false otherwise
    • Description: Prompts the user until they enter H to be the Hero or W to be the Wumpus.

    • Name: play_game()
    • Input: an ifstream object to read from, an ofstream object to write to, nine integers corresponding to (1 & 2) the cave size (3) the number of moves (4 & 5) the wumpus location (6 & 7) the hero location (8 & 9) the pit location, and a boolean if the user is the hero
    • Output: None
    • Description: Simulates the game play as laid out in the input file and writes the game log to the output file.


Requirements


For this assignment, the output written to the game log must match the format specified exactly.

Be sure to mark parameters that do not change in the scope of the function constant as appropriate.


Hints


Take note that the read/eval/print steps all take place within the game loop (giving us our REPL). These steps also largely correlate to the functions we are writing. Implement and test your functions one at a time.

Due to the procedural style, your main.cpp is nothing more than creating a few variables and then calling the functions in the appropriate order. All the specifics and details are abstracted away to wumpus_functions.cpp.


Best Practices To Follow



Grading Rubric


Your submission will be graded according to the following rubric.

PointsRequirement Description
10 All labs completed and submitted
L2A, L2B
24 Each function input/output correct as specified and performs correct task meeting the functional requirements.
4 Function files structured appropriately.
1 Public input test files generate correct results.
2 Private input test file generates correct results.
5 Best practices are followed:
  • +5 Code is easily readable, follows best practices, well structured
  • +4 Code is easy to follow, only a few small violations of best practices
  • +3 No egregiously bad practices
  • +2 Lots of violations of best practices
  • +1 Little effort to follow best practices
  • +0 No effort to follow best practices
46 Total Points

→This assignment is due by Friday, February 17, 2023, 11:59 PM.←
→ As with all assignments, this must be an individual effort and cannot be pair programmed. Any debugging assistance must follow the course collaboration policy and be cited in the comment header block for the assignment.←
→ Do not forget to complete the following labs with this set: L2A, L2B
→ Do not forget to complete zyBooks Assignment 2 for this set.←


Submission


Always, always, ALWAYS update the header comments at the top of your main.cpp file. And if you ever get stuck, remember that there is LOTS of help available.

It is critical that you follow these steps when submitting homework.

If you do not follow these instructions, your assignment will receive a major deduction. Why all the fuss? Because we have several hundred of these assignments to grade, and we use computer tools to automate as much of the process as possible. If you deviate from these instructions, our grading tools will not work.


Submission Instructions



Here are step-by-step instructions for submitting your homework properly:

  1. Make sure you have the appropriate comment header block at the top of every source code file for this set. The header block should include the following information at a minimum.
    /* CSCI 200: Assignment 2: A2 - Watch the Wumpus
     *  * Author: XXXX (INSERT_NAME) * Resources used (Office Hours, Tutoring, Other Students, etc & in what capacity):  * // list here any outside assistance you used/received while following the * // CS@Mines Collaboration Policy and the Mines Academic Code of Honor *  * XXXXXXXX (MORE_COMPLETE_DESCRIPTION_HERE)  */
    Be sure to fill in the appropriate information, including:
    • Assignment number
    • Assignment title
    • Your name
    • If you received any type of assistance (office hours - whose, tutoring - when), then list where/what/who gave you the assistance and describe the assistance received
    • A description of the assignment task and what the code in this file accomplishes.

    Additionally, update the Makefile for A2 to generate a target executable named A2.

  2. File and folder names are extremely important in this process. Please double-check carefully, to ensure things are named correctly.
    1. The top-level folder of your project must be named Set2
    2. Inside Set2, create 3 sub-folders that are required for this Set. The name of each sub-folder is defined in that Set (e.g. L2A, L2B, and A2).
    3. Copy your files into the subdirectories ofSet2 (steps 2-3), zip this Set2 folder (steps 4-5), and then submit the zipped file (steps 6-11) to Canvas.
    4. For example, when you zip/submit Set2, there will be 3 sub-folders called L2A, L2B, and A2 inside the Set2 folder, and each of these sub-folders will have the associated files.

  3. Using Windows Explorer (not to be confused with Internet Explorer), find the files named wumpus_functions.h, wumpus_functions.cpp.

    STOP: Are you really sure you are viewing the correct assignment's folder?

  4. Now, for A2, right click on wumpus_functions.h, wumpus_functions.cpp to copy the files. Then, return to the Set2/A2 folder and right click to paste the files. In other words, put a copy of your homework's wumpus_functions.h, wumpus_functions.cpp source code into the Set2/A2 folder.

    Follow the same steps for each lab to put a copy of each lab's deliverable into the Set2/L2 folders. Do this process for Set2/L2A (main.cpp, Makefile), Set2/L2B (color_conversion.h, color_conversion.cpp, main.cpp, Makefile).

    STOP: Are you sure your Set2 folder now has all your code to submit?

    The structure of the submission is as follows:
    • Set2/
      • A2/
        • wumpus_functions.h
        • wumpus_functions.cpp
      • L2A/
        • main.cpp
        • Makefile
      • L2B/
        • color_conversion.h
        • color_conversion.cpp
        • main.cpp
        • Makefile

  5. Now, right-click on the "Set2" folder.
    1. In the pop-up menu that opens, move the mouse "Send to..." and expand the sub-menu.
    2. In the sub-menu that opens, select "Compressed (zipped) folder".

    STOP: Are you really sure you are zipping a Set2 folder with sub-folders that each contain a main.cpp file in it?

  6. After the previous step, you should now see a "Set2.zip" file.

  7. Now visit the Canvas page for this course and click the "Assignments" button in the sidebar.

  8. Find Set2, click on it, find the "Submit Assignment" area, and then click the "Choose File" button.

  9. Find the "Set2.zip" file created earlier and click the "Open" button.

    STOP: Are you really sure you are selecting the right homework assignment? Are you double-sure?

  10. WAIT! There's one more super-important step. Click on the blue "Submit Assignment" button to submit your homework.

  11. No, really, make sure you click the "Submit Assignment" button to actually submit your homework. Clicking the "Choose File" button in the previous step kind of makes it feel like you're done, but you must click the Submit button as well! And you must allow the file time to upload before you turn off your computer!

  12. Canvas should say "Submitted!". Click "Submission Details" and you can download the zip file you just submitted. In other words, verify you submitted what you think you submitted!

In summary, you must zip the "Set2" folder and only the "Set2" folder, this zip folder must have several sub-folders, you must name all these folders correctly, you must submit the correct zip file for this homework, and you must click the "Submit Assignment" button. Not doing these steps is like bringing your homework to class but forgetting to hand it in. No concessions will be made for incorrectly submitted work. If you incorrectly submit your homework, we will not be able to give you full credit. And that makes us unhappy.


→This assignment is due by Friday, February 17, 2023, 11:59 PM.←
→ As with all assignments, this must be an individual effort and cannot be pair programmed. Any debugging assistance must follow the course collaboration policy and be cited in the comment header block for the assignment.←
→ Do not forget to complete the following labs with this set: L2A, L2B
→ Do not forget to complete zyBooks Assignment 2 for this set.←