C++ - Game of Dungeons and Dragons complete implementation with header files

1.0 Overview In the popular role-playing, the game of Dungeons and Dragons players move from room to room in a dungeon where they encounter creatures, treasure, and various obstacles. The underlying functionality of such a computer game lies in the gaming engine. This Statement of Work presents the requirements for a "Scenario Mapping and Player Movement" class for a gaming engine. 

2.0 Requirements The student shall define, develop, document, prototype, test, and modify as required the software system.

 2.1 Functional Requirements 2.1.1 The software shall be capable of representing the layout for a role-playing game scenario as a graph implemented as an adjacency matrix. The scenario will typically be an inside location such as a dungeon or castle divided into some rooms. For this implementation, it will be assumed that the number of rooms will be 20. 

 2.1.2 The scenario graph shall be implemented as a class called GameGraph (defined in files GameGraph.h andGameGraph.cpp). The GameGraph class shall contain the following private variables. An stream object called m_InFile which shall reference the data file defining the game scenario. A 2D array of chars called m_cAdjMatrix which shall be a 20x20 matrix used to determine the links between rooms in the script. Data stored in the adjacency matrix will not only indicate where there are doors from the current room to other rooms, i.e., links but also will define the direction of the relationship. In other words, the adjacency matrix will be able to store definitions of up to 6 doors and stairways in a room. This means a room can have, up to 4 doors located on the North, South, East, or West walls, as well as stairways, going up or down. An array called m_Rms of 20 Room structures as defined in 2.1.3 below. An int called m_iLocation which shall define the index into the m_Rms array giving the current location of the gaming party. The GameGraph class shall contain the following public functions. GameGraph() and ~GameGraph() - Default constructor and destructor. bool LoadGame(char *fileName) - This feature shall take a single argument which is a character array giving the name of the graph data file. It shall open the file, read all data, and build the graph. bool doCommand(char *cmd) - This function shall take a single argument which is a character array giving a command string the user has input from the keyboard. It shall parse and execute the command. This function always returns false unless the command is QUIT. (Details are given below) void PrintAll() - This function shall print all information in each Room structure and all the links in the graph. This function is to be used primarily during development and testing to make sure all data have been read and stored correctly. The GameGraph class shall contain the following private functions. void getNextLine(char *line, int lineLen) - This utility function reads lines from the graph definition data file. It will be provided by the instructor. void setLink(int roomIdx, int linkIdx, char dCode) - This utility function takes an index of a "link from" Room and a "link to" Room and sets the appropriate code in the AdjMatrix to define a link and its type (North, South, East, West, Up or Down) in the adjacency matrix. void describeRoom(int roomIdx) - This utility function takes an index of a Room in the m_Rms array and prints a complete description of the room, its contents and its exits. See details below.

 2.1.3 Rooms in the scenario shall be represented by a Room structure (defined in a GameGraph.h file). The Roomstructure shall contain the following fields: A character array called m_sRoomName which shall be capable of storing room names of up to 63 characters in length. For example: "Banquet Hall". A character array called m_sRoomDesc which shall be capable of storing room descriptions of up to 127 characters in length. For example: "There is a long oak table filled with plates of food. Wood benches line the walls. Burning torches are mounted on the walls." A character array called m_sItemName which shall be capable of storing the name of a single item of up to 31 characters in length. For example: "Golden sword". A character array called m_sCreatureName which shall be capable of storing the name of a single creature of up to 63 characters in length. For example: "Mountain troll".

 2.1.4 Data defining a gaming scenario shall be read from a data file named gamelayout.txt. A sample data file for development and testing will be provided.

 2.1.5 A command line interface shall be included in the software which meets the following criteria: When the game is started the user shall be placed in the room which was first defined in the data file. When a user enters a room a description of the room shall be given which includes the name of the room, a brief description of the room, the item found in the room, the creature found in the room, and the number of doors and stairways and where they are located. This information will be presented in a narrative style. For example:

You are in the Banquet Hall.
There is a long oak table filled with plates of food. Wood benches line the walls. Burning torches are mounted on the walls.
There is a golden sword in the room.
There is a Mountain troll in the room.
There is a door in the North wall.
There is a door in the South wall.
There is a door in the East wall.
There is a stairway going down. After printing the description of the room as described in the user shall be prompted to enter a command. For example: What do you want to do? The user shall be allowed to enter commands from the keyboard. The command is to be parsed and executed. Commands must meet the following criteria: Valid first words of the command shall be: GO, TAKE, FIGHT and QUIT. If the command is GO then valid second words of the command shall be: NORTH, SOUTH, EAST, WEST, UP, or DOWN. Indicating a desire to go through the north, south, east, or west doors, or up or down a stairway. If the command is TAKE or FIGHT print a message to inform the user that this command has not been implemented yet. If the command is QUIT exit the program. If any other command is issued or a direction other than those listed in section is given then print a message to inform the user that this command is not understood.

 2.1.6 Movement from one room to another, printing of room descriptions, inputing and parsing of commands shall continue until the user enters the command QUIT

 2.1.7 This program must be capable of being tested using a text file of commands and I/O redirection, therefore no other commands requiring input from the keyboard will be allowed except for the single cin.getline(line, 128, '\n'); function call in the "player movement" loop. (Note: You must use this form of the cin stream reference in order to get a full line including spaces. The '\n' is the character to terminate the input. In this case the Enter key.

3.0 Deliverables These products shall be delivered electronically via e-mail as specified below to the instructor.
3.1 Software Design Document -- The student shall provide a software development plan for instructor approval NLT (Not Later Than) Thursday, April 17.
3.2 Software Test Plan -- The student shall provide a test plan for complete verification and validation of the software for instructor approval NLT Thursday, April 17. 
3.3 Gaming Module Source Code File(s) -- The student shall provide source files for a fully tested game program via e-mail NLT Thursday, April 24 (last day of class).

Note: No files from the previous three programming assignments are to be included in this project.

4.0 Period of Performance The period of performance of this assignment is 28 days from the date of assignment. No deliverables will be accepted after the final exam.

Excerpts from 
Software Requirements Specification (SRS)
Programming Assignment 4 2.1 System Organization 2.1.1 All data shall be stored internally as a graph which will be implemented as an Adjacency Matrix.
 2.1.2 The data structure defining each room shall contain the following fields. The data structure 

  1. char m_sRoomName[32]; // Name of the room.

  2. char m_sRoomDesc[128]; // Description of the room.

  3. char m_sItemName[32]; // Name of a single item in the room.

  4. char m_sCreatureName[64]; // Name of a single creature in the room.

 2.1.3 If a valid GO command is given then the software should do the following:

  1. Check the adjacency matrix to determine if there is a door or stairway leading in the direction requested. If not print a message, such as "You can't go in that direction."

  2. If a valid direction is given check the adjacency matrix to locate the room that is linked via this direction and move the player to the appropriate room, give the description of this room, and wait for the user to input the next command.

 2.1.4 The format of the data file shall be as follows:
# Lines beginning with a '#' character will be ignored as comments
# Blank lines will also be ignored
# It is assumed that the file will be valid and contain data on
# 20 rooms for the gaming scenario.
# Data on each room consists of the following on separate lines
# Room name: Maximum of 32 characters (spaces are allowed)
# Room description: Maximum of 128 characters (spaces are allowed)
# Room item: Maximum of 32 characters (spaces are allowed)
# Room creature: Maximum of 64 characters (spaces are allowed)
# The next 6 lines will define links to other rooms given in the
# order North, South, East, West, Up, and Down.
# Each of the 6 lines will contain a number giving the index in the
# array of rooms to which there is a link. If the value is -1 then
# there is no link in that direction.
# In the example below, in the Entrance Hall (room index 0) there is a
# door to the north leading to room 1, one to the south leading to
# room 5, no door east or west, a stairway going up to room 14, but
# no stairway going down.
Entrance Hall
Tapestries hang on the walls. A chandelier hangs from the ceiling.
Leather bag
Troll guard
# etc. for the remaining rooms
 2.1.5 The class definition (header) file for the game class shall be the following:
// File: GameGraph.h
// Purpose: Header file for a D&D game class
// Programming Language: C++
// Author: Dr. Rick Coleman
#include <iostream
#include <fstream
#include <string.h
#include <stdlib.h

using namespace std;

#define NUMROOMS 20

struct Room
char m_sRoomName[64];
char m_sRoomDesc[128];
char m_sItemName[32];
char m_sCreatureName[64];

class GameGraph
ifstream m_InFile; // File to read from
char m_cAdjMatrix[NUMROOMS][NUMROOMS];
Room m_Rms[NUMROOMS];
int m_iLocation; // Index of current room location
GameGraph(); // Class constructor
~GameGraph(); // Class destructor
bool LoadGame(char *filename); // Read game file, build scenario
// and describe first room.
bool doCommand(char *cmd); // Execute a command
void PrintAll();
void getNextLine(char *line, int lineLen);
void setLink(int roomIdx, int linkIdx, char dCode);
void describeRoom(int roomIdx);


Sample Files Included in the Downloadable Zip File

  1. Snippets.txt -- Contains several code samples and functions you can use.

    • Function: bool GameGraph::LoadGame(char *filename) -- This snippet is an outline of how to read the gamelayout.dat file and parse it. This does not include code on how to insert the data that is read into the graph data structures.

    • Function: int GetNextLine(char *line, int lineLen) -- Pass in a pointer to a character array, which must be at least 128 characters in length, and the total length of the line which can be read into the array (127 for a 128 character arrayh). The function reads the next line from the data file into the array line. It skips any blank lines or comment lines (those starting with '#'). It also removes the newline character from the end of the line. The function returns TRUE if a successful read was completed or FALSE if the end of file was reached.

  2. gamelayout.txt -- A sample game layout data file. Note that this file contains comment lines. See description of the function GetNextLine() above that can read the lines and skip the comments.

  3. cmd.txt -- A sample command script similar to the one that will be used to test your program. To use this file copy it into the same directory as your compiled executable then from the command line issue the commandprog4 < cmdscript.txt where prog4 is the name of your executable. 
    If you run the sample executable with this script the last four responses to "What do you want to do?" will be (1) FIGHT not implemented yet, (2) I don't know how to TRY, (3) "You can't move that way from here.", and (4) "Fare well adventurer." in reply to the QUIT command.

  4. GameMain.cpp -- A file with main which you can use for the final running of your game. Note: This file doesNOT contain all the automatic testing code which you must add for use during development.

  5. GameGraph.h -- Header file for the GameGraph class.

  6. Prog4.txt -- A demonstration of the programming assignment. This is actually an executable file with the .exe extension changed to .txt to get around some firewalls. To run the program change the .txt back to .exe. Place this in the same directory as the gamelayout.dat file and run it.

Graph RepresentationIn this programming assignment you will implement the graph as an adjacency matrix (see your lecture notes for details). One problem you will encounter is that in addition to keeping all of the links from a room to other rooms, you must also keep which door or stairway links to a specific room. For example: Given that a room has doors on the North, and East walls, and a stairway leading down, you must not only have a way of indicating links from this room to three others, but also which room the North and East doors, and the stairway link to. Some possible ways of doing this are given below. 

Coding Data into the Adjacency MatrixIn an adjacency matrix one way of storing the information on which door/stairway links to a specific room would be to assign values to each cell in the matrix to indicate the door for this link. For example: '\0' = no link, 'N' = link via North door, 'S' = link via South door, 'E' = link via East door, 'W' = link via West door, 'U' = link via Stairway up, 'D' = link via Stairway down.
The example below shows one row out of the 20x20 adjacency matrix. In this example the adjacency matrix is implemented as a 2D array of chars. The links from the room represented by this row indicates a door to the North('N') into room 1, a door to the East('E') into room 8, a stairway up('U') into room 14, and a stairway down('D') into room 16. 

File I/OTo open the data file use the following lines of code in the GameGraph::LoadGame() function. This will safely open the data file whose name is stored in a character array called filename and passed into the function as the only argument. The ifstream reference m_InFile is part of the GameGraph member variables. A more complete outline of the LoadGame() function can be found in the snippets.txt file in the downloadable zip file. 

m_InFile.open(filename, ifstream::in);
// m_InFile.is_open() returns false if the file could not be found or
// if for some other reason the open failed.
return false;

The following function can be used to read lines from the opened file. It takes two arguments: a character array and the length of the array. The array should be at least 128 characters long. It will return the next line read from the file skipping any comment lines (those starting with '#') and blank lines. If line is returned empty then the end of the file has been reached. This function is included in the snippets.txt file that is included in the downloadable zip file.

// GetNextLine()
// Read the next line from the file.
void GameGraph::getNextLine(char *line, int lineLen)
int done = false;

m_InFile.getline(line, lineLen);

if(m_InFile.good()) // If a line was successfully read
if(strlen(line) == 0) // Skip any blank lines
else if(line[0] == '#') // Skip any comment lines
else done = true; // Got a valid data line so return
// with this line
strcpy(line, "");
} // end while
I/O RedirectionThis program will be graded by compiling your source files with a driver file containing main(). It will be very similar to the sample driver file provided. Your program will then be tested with I/O redirection using this driver and a test gamelayout.txt file. The way this is done is that the instructor will prepare a text file containing a list of commands (see the example below) and run your program, from a command line, using the following command:

yourprogramname < cmd.txt

What will happen is that each time the driver program comes to the input line to ask the user to enter a command at the keyboard the operating system will read a line from the text file instead of from the keyboard. This will allow the rapid, thorough testing and grading of each program. The file contains commands that will test moving to every room in the "dungeon" and test for attempts to move in directions in which there is not a door. It also tests for commands such as TAKE and FIGHT that will not be implemented yet and non-existant commands. Note: this sample list of commands is NOT the one that the instructor will use to test your program.

Sample Commands File

Using sscanf()The function sscanf() found in the header file stdlib.h can be used to parse the command lines entered by the user. Suppose the user has entered a command at the keyboard and you have stored it in a character array called command. Suppose also that there are two character arrays called cmd1 and cmd2. To copy the first word out of command intocmd1 use this command:

sscanf(command, "%s", cmd1);

You can now test cmd1 using strcmp() found in string.h to determine what the command is. If it is a command for which there is a second word (example: GO) then you can read both words using this command:

sscanf(command, "%s %s", cmd1, cmd2);

Now you can check cmd2 to determine the rest of the command which must then be executed. Note: You cannot assume that every command will have two words. The QUIT command is only one word. You will get an error if you try to read the one-word command using sscanf(command, "%s %s", cmd1, cmd2);

Making commands all capsYou cannot depend on the user always entering commands in all capitol letters. Since strcmp() is case sensitive you want to be able to convert all commands entered to all caps. The following function will do that. It takes a single argument, a character array. You need to include ctype.h in order to have access to the toupper() function.

// makeUpper()
// Converts input line to all upper case
void makeUpper(char *line)
char *temp;

temp = line;
while(*temp != '\0')
*temp = toupper(*temp);

Just for FunIf you enjoy writing game playing programs this assignment will get you started. After completing it you might want to expand it. Here are some things to think about:

  1. How would you modify the data structure defining each room (node in the graph) to allow adding additional special items (like a "jeweled sword") to a room?

  2. How would you modify the data structure defining each room (node in the graph) to allow adding more special creatures (like a "basilisk") to a room?

  3. How would you add a data structure to define an adventuring character. In D&D style the character would have to have a name, race (human, dwarf, elf, etc.), alignment (good, evil, or neutral) scores for strength, constitution, charisma, etc., weapons, equipment, experience points, and other items?

  4. How would you program the execution of commands like TAKE SWORD, or FIGHT TROLL?

Do not add any of these modifications to the program you turn in or it may not compile with the instructor's test
program. As a result you will get no credit for this assignment.
Powered by