代写 data structure algorithm game html software #include “basicdungeon.h”

#include “basicdungeon.h”

using namespace core::dungeon;

/* ——————————————————————————
* BasicDungeon member implementations
* —————————————————————————–*/

BasicDungeon::BasicDungeon()
{

}

/* ——————————————————————————
* RockChamber member implementations
* —————————————————————————–*/

RockChamber::RockChamber()
{

}

/* ——————————————————————————
* QuartzChamber member implementations
* —————————————————————————–*/

QuartzChamber::QuartzChamber()
{

}

/* ——————————————————————————
* BasicWall member implementations
* —————————————————————————–*/

RockWall::RockWall()
{

}
#include “character.h”

using core::Character;

Character::Character(const std::string &name)
: _name{name}
{

}

const std::string& Character::name() const {
return _name;
}

std::ostream& operator<<(std::ostream &stream, const Character &character) { stream << character.name(); return stream; } #include "commondungeon.h" using namespace core::dungeon; OpenDoorway::OpenDoorway() { } #include "creatures.h" using namespace core::creatures; /* ------------------------------------------------------------------------------ * Creature member implementations * -----------------------------------------------------------------------------*/ Creature::Creature(const std::string &name) : _name{name} { } const std::string& Creature::name() const { return _name; } #include "csvfile.h" using namespace data; CsvFile::CsvFile(std::istream &input) { // TODO: implement the constructor } int CsvFile::numberOfColumns() const { // TODO: implement this method. See header for description. return -10; } int CsvFile::numberOfRows() const { // TODO: implement this method. See header for description. return -10; } std::string CsvFile::at(int row, int column) const { // TODO: implement this method. See header for description. return "not yet implemented"; } std::string CsvFile::headerAt(int column) const { // TODO: implement this method. See header for description. return "not yet implemented"; } int CsvFile::columnIndexOf(const std::string &columnName) const { // TODO: implement this method. See header for description. return -10; } #include "door.h" using namespace core::dungeon; Door::Door() { } #include "dungeon.h" using namespace core::dungeon; Dungeon::Dungeon() : _rooms{} { } // DO NOT modify implementation below this comment std::shared_ptr Dungeon::retrieveRoom(int id) {
auto roomIterator = _rooms.find(id);
if (roomIterator != _rooms.end()) {
return roomIterator->second;
}
return std::shared_ptr{nullptr};
}

bool Dungeon::addRoom(std::shared_ptr newRoom) {
if (!_rooms.count(newRoom->id())) {
_rooms[newRoom->id()] = newRoom;
return true;
}
return false;
}
#include “game.h”
#include “testingsettings.h”
#include

using namespace core;

// TODO: Add additional implementation here

// Do not change/remove the initialisation of _randomGenerator and _realDistribution, otherwise change as needed.
Game::Game()
: _randomGenerator{uint32_t(time(nullptr))}, _realDistribution{0.0, 1.0}
{

}

// DO NOT modify implementation below this comment

int Game::randomIntBetweenInc(int min, int max) {
#if INPUT_SCRIPT
return min; // for consistency when using the input script
#else
if (min == max) return max;
if (max < min) std::swap(min, max); int diff{max + 1 - min}; return int(_randomGenerator() % unsigned(diff)) + min; #endif } int Game::randomIntBetweenEx(int min, int max) { #if INPUT_SCRIPT return max - 1; // for consistency when using the input script #else if (min == max) return max; // technically invalid for an exclusive range if (max < min) std::swap(min, max); int diff{max - min}; return int(_randomGenerator() % unsigned(diff)) + min; #endif } double Game::randomDouble() { #if INPUT_SCRIPT return 1.0; // for consistency when using the input script. #else return _realDistribution(_randomGenerator); #endif } #include "magicaldungeon.h" using namespace core::dungeon; /* ------------------------------------------------------------------------------ * MagicalDungeon member implementations * -----------------------------------------------------------------------------*/ MagicalDungeon::MagicalDungeon() { } /* ------------------------------------------------------------------------------ * EnchantedLibrary member implementations * -----------------------------------------------------------------------------*/ EnchantedLibrary::EnchantedLibrary() { } /* ------------------------------------------------------------------------------ * AlchemistsLaboratory member implementations * -----------------------------------------------------------------------------*/ AlchemistsLaboratory::AlchemistsLaboratory() { } /* ------------------------------------------------------------------------------ * MagicWall member implementations * -----------------------------------------------------------------------------*/ MagicWall::MagicWall() { } #include "menuinterface.h" #include
#include

#include “testingsettings.h”

#define AUTHOR “
#define TITLE “

#if INPUT_SCRIPT
#define SCRIPT_PATH “../assignment1-dungeon_crawler/input_script.txt”
#define OUT_FILE_PATH “../assignment1-dungeon_crawler/output_gen.txt”
#endif

/* ——————————————————————————
* NOTE: DO NOT edit this file other than providing your name and game title to the
* `AUTHOR` and `TITLE` macros, respectively.
* Enable testing mode and set options in the testingsettings.h file.
* It may be necessary to change the path to the input script, depending on your
* configuration: see SCRIPT_PATH macro definition above.
* —————————————————————————–*/

/**
* @mainpage
*
* There are three forms of the main function in this file so that it can run in
* three modes: normal, input script, and testing. This is done using conditional
* compilation and is configured through `testingsettings.h`.
*
* In normal mode, the MenuInterface will be run and attached to standard in and
* standard out.
*
* In input script mode, the Menu Interface will be run and attached to a file
* for input and (optionally) a file for output. This will be used as a quick test
* of the general functionality of your implementation. You can use it yourself
* to test as you go to ensure that your implementation conforms to the expected
* commands.
*
* In testing mode, a simple unit testing suite will be executed. A small example
* has been provided, but you are encouraged to implement tests as you go to
* ensure the parts of your implementation are working. This saves time as it makes
* it easier to track down errors for “submodules” this way, rather than having to
* test everything through the menu-driven interface constantly.
*/

using core::MenuInterface;

#if not TESTING

#if not INPUT_SCRIPT

/**
* @brief main Simple main function that runs the MenuInterface until quit.
* @return exit code, 0 is success
*/
int main()
{
MenuInterface m{std::cout, std::cin};

m.displayWelcome(AUTHOR, TITLE);
m.run();

return 0;
}

#else
#include
#include

/**
* @brief main Simple main function runs game using the input script.
* @return
*/
int main()
{
// Using QDir to provide sensible error useful error message
// if the script file cannot be found.
QDir path{SCRIPT_PATH};
std::fstream in{path.absolutePath().toStdString()};
if (in.fail()) {
std::cout << "Unable to find file: " << path.absolutePath().toStdString() << std::endl << "Current path: " << QDir::currentPath().toStdString() << std::endl; return 1; } #if OUTPUT_SCRIPT QDir outPath{OUT_FILE_PATH}; std::ofstream out{outPath.absolutePath().toStdString()}; if (out.fail()) { std::cout << "Unable to open out file: " << outPath.absolutePath().toStdString() << std::endl << "Current path: " << QDir::currentPath().toStdString() << std::endl; return 1; } #else std::ostream& out = std::cout; #endif MenuInterface m{out, in}; m.displayWelcome(AUTHOR, TITLE); m.run(); return 0; } #endif #else #include "testing.h" /** * @brief main run testing code. * @return */ int main() { Testing test{}; std::cout << "Running tests ..." << std::endl; test.runTests(); // Modify which tests are run in the implementation of runTests() test.printTestResults(std::cout); return 0; } #endif #include "menuinterface.h" #include

using namespace core;

MenuInterface::MenuInterface(std::ostream &display, std::istream &input)
: _display{display}, _input{input}, _currentMenu{Menu::Main} {
}

void MenuInterface::displayWelcome(const std::string &author, const std::string &title) const {
std::string welcomeText{“Welcome to ” + title};
std::string authorText{“Developed by ” + author};
std::string comp3023{“COMP 3023 Software Development with C++”};

unsigned int columns{static_cast(std::max(welcomeText.size(), std::max(authorText.size(), comp3023.size())))};

_display << centre(columns, welcomeText.size()) << welcomeText << std::endl << centre(columns, authorText.size()) << authorText << std::endl << centre(columns, comp3023.size()) << comp3023 << std::endl; } void MenuInterface::run() { displayMenu(); while (processSelection(getCharacterInput()) && _input) { displayMenu(); } } void MenuInterface::displayMenu() const { waitUntillNewline(); switch (_currentMenu) { case Menu::Main: displayMainMenu(); break; case Menu::CharacterDetails: characterDetailsMenu(); break; case Menu::DungeonSelect: dungeonTypeMenu(); break; case Menu::Action: actionMenu(); break; case Menu::Combat: combatMenu(); break; } } bool MenuInterface::processSelection(char selection) { if (!_input) return false; // graceful exit when input ends switch (_currentMenu) { case Menu::Main: return processMainMenu(tolower(selection)); case Menu::CharacterDetails: processCharacterDetails(tolower(selection)); break; case Menu::DungeonSelect: processDungeonType(tolower(selection)); break; case Menu::Action: processAction(tolower(selection)); break; case Menu::Combat: processCombatAction(tolower(selection)); } return true; } char MenuInterface::getCharacterInput() const { char input; _input >> input;
_input.ignore(std::numeric_limits::max(), ‘\n’);
echo(input); // for when running the input script
return input;
}

int MenuInterface::getIntInput() const {
int input;
_input >> input;
_input.ignore(std::numeric_limits::max(), ‘\n’);

while (!_input) {
_input.clear();
warnSelectionInvalid(char(_input.peek()));
_input.ignore(std::numeric_limits::max(), ‘\n’);

_input >> input;
_input.ignore(std::numeric_limits::max(), ‘\n’);
}

echo(input); // for when running the input script

return input;
}

void MenuInterface::warnSelectionInvalid(char selection) const {
_display << "Sorry, \'" << selection << "\' is not a valid option, please try again." << std::endl; } void MenuInterface::setMenu(Menu newMenu) { _currentMenu = newMenu; } void MenuInterface::displayMainMenu() const { _display << "What would you like to do?" << std::endl; _display << " (p)lay the game" << std::endl; _display << " (c)haracter details" << std::endl; _display << " (q)uit" << std::endl; } bool MenuInterface::processMainMenu(char selection) { switch (selection) { case 'p': playGame(); break; case 'c': switchToCharacterMenu(); break; case 'q': return quitGame(); default: warnSelectionInvalid(selection); } return true; } void MenuInterface::playGame() { // TODO: implement this member function. } void MenuInterface::createCharacter() { // TODO: implement this member function. } void MenuInterface::dungeonTypeMenu() const { // TODO: implement this member function. _display << "TODO: any key will return to main menu" << std::endl; } void MenuInterface::processDungeonType(char selection) { // TODO: implement this member function. setMenu(Menu::Main); } void MenuInterface::switchToCharacterMenu() { // TODO: implement this member function setMenu(Menu::CharacterDetails); } bool MenuInterface::quitGame() const { // TODO: complete implementation return !confirm("Are you sure you want to quit?"); } void MenuInterface::characterDetailsMenu() const { // TODO: implement this member function. _display << "TODO: any key will return to main menu" << std::endl; } void MenuInterface::processCharacterDetails(char selection) { // TODO: implement this member function. setMenu(Menu::Main); } void MenuInterface::displayWeaponDetails() { // TODO: implement this member function } void MenuInterface::actionMenu() const { // TODO: implement this member function. _display << "TODO: any key will return to main menu" << std::endl; } void MenuInterface::processAction(char selection) { // TODO: implement this member function. setMenu(Menu::Main); } void MenuInterface::combatMenu() const { // TODO: implement this member function. _display << "TODO: any key will return to main menu" << std::endl; } void MenuInterface::processCombatAction(char selection) { // TODO: implement this member function. setMenu(Menu::Main); } void MenuInterface::doNavigate() { // TODO: implement this member function } void MenuInterface::pickupWeapon() { // TODO: implement this member function } void MenuInterface::compareWeapons() { // TODO: implement this member function } void MenuInterface::doAttack() { // TODO: implement this member function } void MenuInterface::useSpecialAbility() { // TODO: implement this member function } void MenuInterface::leaveDungeon() { // TODO: implement this member function } bool MenuInterface::confirm(const std::string &confirmationPrompt) const { // TODO: implement this member function. // Do not forget to validate the user's confirmation selection return true; } #include "room.h" using namespace core::dungeon; Room::Room(int id) : _id{id} { } int Room::id() { return _id; } #include "testing.h" #include "basicdungeon.h" #include "character.h" #include "commondungeon.h" #include "creatures.h" #include "csvfile.h" #include "door.h" #include "dungeon.h" #include "game.h" #include "weapons.h" #include "magicaldungeon.h" #include "room.h" #include "wall.h" #include
#include
#include
#include #include
#include

/*
* IMPLEMENT your tests in this file as required.
*
* You may need to edit the original test implementations as you implement your design.
* The original test implementations are just simple examples that do not necessarily
* reflect the final application.
*/

using namespace core;
using namespace data;
using namespace dungeon;
using namespace creatures;
using std::cout;
using std::endl;
using std::setw;

void Testing::runTests() {
cout << std::left << std::setfill('.'); csvFileTestSuite(); // Runs all of the CsvFile tests cout << setw(72) << "Character class tests " << testCharacter() << endl; cout << setw(72) << "Creature class tests " << testCreature() << endl; cout << setw(72) << "Door class tests " << testDoor() << endl; cout << setw(72) << "Dungeon class tests " << testDungeon() << endl; cout << setw(72) << "Game class tests " << testGame() << endl; cout << setw(72) << "Weapon class tests " << testWeapon() << endl; cout << setw(72) << "Room class tests " << testRoom() << endl; cout << setw(72) << "Wall class tests " << testWall() << endl; } // This is an example of a simple way of performing your tests. // It is incomplete, so you will need to extend it if you intend to continue with it. std::string Testing::testCharacter() { _failure = false; // ensure this is at the beggining of each test std::string name{"Character Name"}; Character c{name}; equal(name, c.name(), “Character .name() does not match constructor value”);

// TODO: complete the testing of the Character class

return passFailText();
}

std::string Testing::testCreature() {
_failure = false; // ensure this is at the beggining of each test

std::string name{“Creature Name”};

Creature c{name};

equal(name, c.name(), “Creature .name() does not match constructor value”);

// TODO: complete the testing of the Creature class(es): can be removed

return passFailText();
}
std::string Testing::testDoor() {
_failure = false; // ensure this is at the beggining of each test

// TODO: complete the testing of the Door class(es): can be removed

// return passFailText();
return “Skipped”;
}
std::string Testing::testDungeon() {
_failure = false; // ensure this is at the beggining of each test

int roomId{1};
std::shared_ptr room{std::make_shared(roomId)};

Dungeon dungeon{};

dungeon.addRoom(room);
equal(room, dungeon.retrieveRoom(roomId), “Dungeon .add/.retrieveRoom() failure, does not return room that was added”);

// TODO: complete the testing of the Dungeon class(es): can be removed

// return passFailText();
return “Skipped”;
}

std::string Testing::testGame() {
_failure = false;

Game game{};

// TODO: implement the testing of the Game class

// The following tests the random number generation.
int value{game.randomIntBetweenInc(5, 0)};
greaterThan(-1, value, “Swapping the min and max (incl.) did not work. Got negative value.”);
lessThan(6, value, “Swapping the min and max (incl.) did not work. value out of range.”);

value = game.randomIntBetweenEx(5, 0);
greaterThan(-1, value, “Swapping the min and max (excl.) did not work. Got negative value.”);
lessThan(5, value, “Swapping the min and max (excl.) did not work. value out of range.”);

for (int i{0}; i < 1000; ++i) { // Not really a good test for this, but just in case. int value = game.randomIntBetweenInc(2, 5); greaterThan(1, value, "Game .randomIntBetweenInc somehow generated a value out of range"); lessThan(6, value, "Game .randomIntBetweenInc somehow generated a value out of range"); } for (int i{0}; i < 1000; ++i) { // Not really a good test for this, but just in case. int value = game.randomIntBetweenEx(2, 5); greaterThan(1, value, "Game .randomIntBetweenEx somehow generated a value out of range"); lessThan(5, value, "Game .randomIntBetweenEx somehow generated a value out of range"); } for (int i{0}; i < 1000; ++i) { // Not really a good test for this, but just in case. double value = game.randomDouble(); double tinyValueBelow1{std::nextafter(0.0, std::numeric_limits::min())};
greaterThan(tinyValueBelow1, value, “Game .randomDouble somehow generated a value out of range”);
lessThan(1.0, value, “Game .randomDouble somehow generated a value out of range”);
}

return passFailText();
}

std::string Testing::testWeapon() {
_failure = false; // ensure this is at the beggining of each test

// TODO: complete the testing of the Item class(es): can be removed

// return passFailText();
return “Skipped”;
}

std::string Testing::testRoom() {
_failure = false;

int roomId{1};

Room room{roomId};

equal(roomId, room.id(), “Room .id() does not match constructor value”);

// TODO: complete the testing of the Character class

return passFailText();
}

std::string Testing::testWall() {
_failure = false; // ensure this is at the beggining of each test

// TODO: complete the testing of the Wall class(es): can be removed

// return passFailText();
return “Skipped”;
}

// TODO: implement the rest of your tests here

// CsvFile tests: Do NOT modify! (except in the following suggestion)
// It is recommended that you perform the following:
// – Comment out all but the first test.
// – Once the first test passes, activate the second while leaving the first
// test active.
// – Once the second test passes, move to the third test, etc.
// Doing it this way will incrementally build up the functionality of your
// CsvFile class while ensuring all of the previous tests still pass as you
// make changes to your implementation.
void Testing::csvFileTestSuite()
{
cout << setw(72) << "CsvFile: Test Empty CSV file " << testLoadFailureForEmptyCsvFile() << endl; cout << setw(72) << "CsvFile: Test CSV file with Header but no rows " << testLoadSuccessForHeaderButNoDataCsvFile() << endl; cout << setw(72) << "CsvFile: Test Out of Range Returns Empty string " << testOutOfRangeReturnsEmptyString() << endl; cout << setw(72) << "CsvFile: Test Correct Header Fields read in " << testHeaderFieldsCorrectlyRead() << endl; cout << setw(72) << "CsvFile: Test Correct Row data read in and accessible " << testCommaSeparatedRowDataAccessible() << endl; cout << setw(72) << "CsvFile: Test Multi-Row CSV data is accessible " << testMultipleRowsOfData() << endl; cout << setw(72) << "CsvFile: Test Load failure for differing number of columns " << testLoadFailureOnRowWithDifferingNumberOfColumns() << endl; cout << setw(72) << "CsvFile: Test preservation of whitespace in fields " << testPreservationOfWhitespaceInFields() << endl; cout << setw(72) << "CsvFile: Test line endings of last line " << testLineEndingOnLastLine() << endl; cout << setw(72) << "CsvFile: Test double quoted fields (no internal quotes) " << testDoubleQuotedFields() << endl; cout << setw(72) << "CsvFile: Test double quoted fields (mixed some quoted,some not) " << testDoubleQuotedFieldsMixedWithUnquoted() << endl; cout << setw(72) << "CsvFile: Test replace of '\\n' with newline character in quoted fields " << testReplacementOfBlackslashNInQuotedFieldsWithNewline() << endl; cout << setw(72) << "CsvFile: Test double quotes within fields " << testDoubleQuotesWithinFields() << endl; cout << setw(72) << "CsvFile: Test putting it all together, load sample creature file " << testReadingCsvDataFromFile() << endl; } std::string Testing::testLoadFailureForEmptyCsvFile() { std::stringstream data{""}; CsvFile csvFile{data}; equal(-1, csvFile.numberOfRows(), "numberOfRows() must indicate load failure for empty input data"); equal(-1, csvFile.numberOfColumns(), "numberOfColumns() must indicate load failure for empty input data"); equal(“”, csvFile.at(1, 1), “at(int,int) must return empty string for empty input data”);
equal(“”, csvFile.headerAt(1), “headerAt(int) must return empty string for empty input data”);
equal(-1, csvFile.columnIndexOf(“Name”), “columnIndexOf(string) must return -1 for empty input data”);

return passFailText();
}

std::string Testing::testLoadSuccessForHeaderButNoDataCsvFile()
{
std::stringstream data{“Header”};
CsvFile csvFile{data};

equal(0, csvFile.numberOfRows(), “numberOfRows() must indicate the number of rows in the data for successful load”);
equal(1, csvFile.numberOfColumns(), “numberOfColumns() must indicate the number of columns for successful load”);
equal(“”, csvFile.at(1, 1), “at(int,int) must return empty string for empty no rows (out of range)”);
equal(“Header”, csvFile.headerAt(1), “headerAt(int) must return the column name for successful load”);
equal(1, csvFile.columnIndexOf(“Header”), “columnIndexOf(string) must return index for for successful load”);

return passFailText();
}

std::string Testing::testOutOfRangeReturnsEmptyString()
{
std::stringstream data{R”:(Header1,Header2
Cell 1,Cell 2
):”};
CsvFile csvFile{data};

equal(“”, csvFile.headerAt(3), “headerAt() must return empty string when index out of range”);
equal(“”, csvFile.headerAt(0), “headerAt() must return empty string when index out of range (zero is out of range)”);
equal(“”, csvFile.at(2,1), “at() must return empty string when row index out of range”);
equal(“”, csvFile.at(0,1), “at() must return empty string when row index out of range (zero is out of range)”);
equal(“”, csvFile.at(1,3), “at() must return empty string when column index out of range”);
equal(“”, csvFile.at(1,0), “at() must return empty string when column index out of range (zero is out of range)”);

return passFailText();
}

std::string Testing::testHeaderFieldsCorrectlyRead()
{
std::stringstream data{R”:(Header1,Header2,Header3):”};
CsvFile csvFile{data};

equal(0, csvFile.numberOfRows(), “numberOfRows() must indicate zero, as only the header is present”);
equal(3, csvFile.numberOfColumns(), “numberOfColumns() must indicate 3 columns for the three header fields”);
equal(“Header1”, csvFile.headerAt(1), “headerAt(1) must return the first header field”);
equal(“Header2”, csvFile.headerAt(2), “headerAt(2) must return the second header field”);
equal(“Header3”, csvFile.headerAt(3), “headerAt(3) must return the third header field”);

return passFailText();
}

std::string Testing::testCommaSeparatedRowDataAccessible()
{
std::stringstream data{R”:(Header1,Header2,Header3
Field1,Field2,Field3):”};
CsvFile csvFile{data};

equal(1, csvFile.numberOfRows(), “numberOfRows() must indicate 1, as the header + 1 row is present”);
equal(3, csvFile.numberOfColumns(), “numberOfColumns() must indicate 3 columns for the three fields”);
equal(“Field1”, csvFile.at(1,1), “at(1,1) must return the first field of the first row”);
equal(“Field2”, csvFile.at(1,2), “at(1,2) must return the second field of the first row”);
equal(“Field3”, csvFile.at(1,3), “at(1,3) must return the third field of the first row”);

return passFailText();
}

std::string Testing::testMultipleRowsOfData()
{
std::stringstream data{R”:(Header1,Header2,Header3
Row1Field1,Row1Field2,Row1Field3
Row2Field1,Row2Field2,Row2Field3
Row3Field1,Row3Field2,Row3Field3):”};
CsvFile csvFile{data};

equal(3, csvFile.numberOfRows(), “numberOfRows() must indicate 3, as the header + 3 rows are present”);
equal(3, csvFile.numberOfColumns(), “numberOfColumns() must indicate 3 columns for the three fields”);

equal(“Row1Field1”, csvFile.at(1,1), “at(1,1) must return the first field of the first row”);
equal(“Row1Field2”, csvFile.at(1,2), “at(1,2) must return the second field of the first row”);
equal(“Row1Field3”, csvFile.at(1,3), “at(1,3) must return the third field of the first row”);

equal(“Row2Field1”, csvFile.at(2,1), “at(2,1) must return the first field of the second row”);
equal(“Row2Field2”, csvFile.at(2,2), “at(2,2) must return the second field of the second row”);
equal(“Row2Field3”, csvFile.at(2,3), “at(2,3) must return the third field of the second row”);

equal(“Row3Field1”, csvFile.at(3,1), “at(3,1) must return the first field of the third row”);
equal(“Row3Field2”, csvFile.at(3,2), “at(3,2) must return the second field of the third row”);
equal(“Row3Field3”, csvFile.at(3,3), “at(3,3) must return the third field of the third row”);

return passFailText();
}

std::string Testing::testLoadFailureOnRowWithDifferingNumberOfColumns()
{
std::stringstream dataExtraColumnInRow{R”:(Header1,Header2
Field1,Field2,Field3Error):”};
CsvFile csvFile{dataExtraColumnInRow};

equal(-1, csvFile.numberOfRows(), “numberOfRows() must indicate load failure for row with extra column”);
equal(-1, csvFile.numberOfColumns(), “numberOfColumns() must indicate load failure for row with extra column”);

std::stringstream dataMissingColumnInRow{R”:(Header1,Header2
Field1):”};
csvFile = CsvFile{dataMissingColumnInRow};

equal(-1, csvFile.numberOfRows(), “numberOfRows() must indicate load failure for row with missing column”);
equal(-1, csvFile.numberOfColumns(), “numberOfColumns() must indicate load failure for row with missing column”);

return passFailText();
}

std::string Testing::testPreservationOfWhitespaceInFields()
{
std::stringstream data{” Header1, Header2,Header3 ,Header 4, Header 5 ,Header6 \n”
” Field1, Field2,Field3 ,Field 4, Field 5 ,Field6 “};
CsvFile csvFile{data};

equal(1, csvFile.numberOfRows(), “numberOfRows() must be 1 for whitespace test”);
equal(6, csvFile.numberOfColumns(), “numberOfColumns() must be 6 for whitespace test”);

equal(” Header1″, csvFile.headerAt(1), “headerAt(1) must preserve whitespace at line beginning”);
equal(” Header2″, csvFile.headerAt(2), “headerAt(2) must preserve whitespace after comma”);
equal(“Header3 “, csvFile.headerAt(3), “headerAt(3) must preserve whitespace before comma”);
equal(“Header 4”, csvFile.headerAt(4), “headerAt(4) must preserve internal whitespace”);
equal(” Header 5 “, csvFile.headerAt(5), “headerAt(5) must preserve all whitespace”);
equal(“Header6 “, csvFile.headerAt(6), “headerAt(6) must preserve whitespace at line end”);

equal(” Field1″, csvFile.at(1,1), “at(1, 1) must preserve whitespace at line beginning”);
equal(” Field2″, csvFile.at(1,2), “at(1, 2) must preserve whitespace after comma”);
equal(“Field3 “, csvFile.at(1, 3), “at(1, 3) must preserve whitespace before comma”);
equal(“Field 4”, csvFile.at(1, 4), “at(1, 4) must preserve internal whitespace”);
equal(” Field 5 “, csvFile.at(1, 5), “at(1, 5) must preserve all whitespace”);
equal(“Field6 “, csvFile.at(1,6), “at(1, 6) must preserve whitespace at line end”);

return passFailText();
}

std::string Testing::testLineEndingOnLastLine()
{
std::stringstream data{R”:(Header1
Field1):”};
CsvFile csvFile{data};

equal(1, csvFile.numberOfRows(), “numberOfRows() must be 1 for line ending test, without extra CRLF”);
equal(1, csvFile.numberOfColumns(), “numberOfColumns() must be 1 for line ending test, without extra CRLF”);

data = std::stringstream{R”:(Header1
Field1
):”};
csvFile = CsvFile{data};

equal(1, csvFile.numberOfRows(), “numberOfRows() must be 1 for line ending test, WITH extra CRLF”);
equal(1, csvFile.numberOfColumns(), “numberOfColumns() must be 1 for line ending test, WITH extra CRLF”);

return passFailText();
}

std::string Testing::testDoubleQuotedFields()
{
std::stringstream data{R”:(“Header,1″,”Header,2″,”Header,3″,” Header 4 ”
“Field,1″,”Field,2″,”Field,3″,” Field 4 “):”};
CsvFile csvFile{data};

equal(1, csvFile.numberOfRows(), “numberOfRows() must indicate 1, as the header + 1 row is present (double quote test)”);
equal(4, csvFile.numberOfColumns(), “numberOfColumns() must indicate 4 columns for the four fields (double quote test)”);

equal(“Header,1”, csvFile.headerAt(1), “headerAt(1) must return the first header without quotes”);
equal(“Header,2”, csvFile.headerAt(2), “headerAt(2) must return the second header without quotes”);
equal(“Header,3”, csvFile.headerAt(3), “headerAt(3) must return the third header without quotes”);
equal(” Header 4 “, csvFile.headerAt(4), “headerAt(4) must return the fourth header without quotes, preserving whitespace”);

equal(“Field,1”, csvFile.at(1,1), “at(1,1) must return the first field without quotes”);
equal(“Field,2”, csvFile.at(1,2), “at(1,2) must return the second field without quotes”);
equal(“Field,3”, csvFile.at(1,3), “at(1,3) must return the third field without quotes”);
equal(” Field 4 “, csvFile.at(1,4), “at(1,4) must return the fourth field without quotes, preserving whitespace”);

data = std::stringstream{R”:( “Header1”
“Field1″):”};
csvFile = CsvFile{data};

equal(-1, csvFile.numberOfRows(), “numberOfRows() must indicate load failure for whitespace outside double quotes (before quote)”);
equal(-1, csvFile.numberOfColumns(), “numberOfColumns() must indicate load failure for whitespace outside double quotes (before quote)”);

data = std::stringstream{R”:(“Header1” ,Header2
“Field1″ ,Field2):”};
csvFile = CsvFile{data};

equal(-1, csvFile.numberOfRows(), “numberOfRows() must indicate load failure for whitespace outside double quotes (after quote)”);
equal(-1, csvFile.numberOfColumns(), “numberOfColumns() must indicate load failure for whitespace outside double quotes (after quote)”);

return passFailText();
}

std::string Testing::testDoubleQuotedFieldsMixedWithUnquoted()
{
std::stringstream data{R”:(“Header,1″,Header2,”Header,3”,Header4
“Field,1″,Field2,”Field,3″,Field4):”};
CsvFile csvFile{data};

equal(1, csvFile.numberOfRows(), “numberOfRows() must indicate 1, as the header + 1 row is present (mixed test)”);
equal(4, csvFile.numberOfColumns(), “numberOfColumns() must indicate 4 columns for the three fields (mixed test)”);

equal(“Header,1”, csvFile.headerAt(1), “headerAt(1) must return the first header without quotes (mixed test)”);
equal(“Header2”, csvFile.headerAt(2), “headerAt(2) must return the second header without quotes (mixed test)”);
equal(“Header,3”, csvFile.headerAt(3), “headerAt(3) must return the third header without quotes (mixed test)”);
equal(“Header4”, csvFile.headerAt(4), “headerAt(4) must return the fourth header without quotes (mixed test)”);

equal(“Field,1”, csvFile.at(1,1), “at(1,1) must return the first field without quotes (mixed test)”);
equal(“Field2”, csvFile.at(1,2), “at(1,2) must return the second field without quotes (mixed test)”);
equal(“Field,3”, csvFile.at(1,3), “at(1,3) must return the third field without quotes (mixed test)”);
equal(“Field4”, csvFile.at(1,4), “at(1,4) must return the fourth field without quotes (mixed test)”);

return passFailText();
}

std::string Testing::testReplacementOfBlackslashNInQuotedFieldsWithNewline()
{
std::stringstream data{R”:(“Header\n1″,”He\nader\n2”,Header\n3
“Field\n1″,”Fi\neld\n2″,Field\n3):”};
CsvFile csvFile{data};

equal(“Header\n1”, csvFile.headerAt(1), “headerAt(1) must return the first header with ‘\\n’ replaced with newline”);
equal(“He\nader\n2”, csvFile.headerAt(2), “headerAt(2) must return the second header with ‘\\n’ replaced with newline”);
equal(“Header\\n3”, csvFile.headerAt(3), “headerAt(3) must return the thord header WITHOUT ‘\\n’ replaced with newline, since it is unquoted”);

equal(“Field\n1”, csvFile.at(1,1), “at(1,1) must return the first field with ‘\\n’ replaced with newline”);
equal(“Fi\neld\n2”, csvFile.at(1,2), “at(1,2) must return the second field with ‘\\n’ replaced with newline”);
equal(“Field\\n3”, csvFile.at(1,3), “at(1,3) must return the third field WITHOUT ‘\\n’ replaced with newline, since it is unquoted”);

return passFailText();
}

std::string Testing::testDoubleQuotesWithinFields()
{
std::stringstream data{R”:(“Header””1”
“Field””1″):”};
CsvFile csvFile{data};

equal(1, csvFile.numberOfRows(), “numberOfRows() must indicate 1, as the header + 1 row is present (double quote test)”);
equal(1, csvFile.numberOfColumns(), “numberOfColumns() must indicate 4 columns for the three fields (double quote test)”);

equal(“Header\”1”, csvFile.headerAt(1), “headerAt(1) must return the first header with internal quotes maintained, no outer quotes”);
equal(“Field\”1”, csvFile.at(1,1), “at(1,1) must return the first field with internal quotes maintained, no outer quotes”);

data = std::stringstream{R”:(“Header””,””1″
“Field””,””1″):”};
csvFile = CsvFile{data};

equal(1, csvFile.numberOfRows(), “numberOfRows() must indicate 1, as the header + 1 row is present (double quote test with comma)”);
equal(1, csvFile.numberOfColumns(), “numberOfColumns() must indicate 4 columns for the three fields (double quote test with comma)”);

equal(“Header\”,\”1″, csvFile.headerAt(1), “headerAt(1) must return the first header with internal quotes maintained, no outer quotes, and internal commas preserved”);
equal(“Field\”,\”1″, csvFile.at(1,1), “at(1,1) must return the first field with internal quotes maintained, no outer quotes, and internal commas preserved”);

return passFailText();
}

std::string Testing::testReadingCsvDataFromFile()
{
std::ifstream dataFile{“creature_types_sample.csv”};
CsvFile csvFile{dataFile};
dataFile.close(); // Ensure you close the file stream after loading the data

equal(3, csvFile.numberOfRows(), “numberOfRows() the example file contains three rows”);
equal(8, csvFile.numberOfColumns(), “numberOfColumns() the example file contains 8 columns”);

equal(“Maximum Health”, csvFile.headerAt(1), “First column of creature file must be Maximum Health”);
equal(“Name”, csvFile.headerAt(2), “Second column of creature file must be Name”);
equal(“Description”, csvFile.headerAt(3), “Third column of creature file must be Description”);
equal(“Strength”, csvFile.headerAt(4), “Fourth column of creature file must be Strength”);
equal(“Dexterity”, csvFile.headerAt(5), “Fifth column of creature file must be Dexterity”);
equal(“Wisdom”, csvFile.headerAt(6), “Sixth column of creature file must be Wisdom”);
equal(“Weapon”, csvFile.headerAt(7), “Seventh column of creature file must be Weapon”);
equal(“Dungeon Type”, csvFile.headerAt(8), “Eighth column of creature file must be Dungeon Type”);

equal(“20”, csvFile.at(1,1), “First creature must have 20 Maximum Health”);
equal(“Goblin”, csvFile.at(1,2), “First creature must be named Goblin”);
equal(“a small nimble creature who favours the short sword”, csvFile.at(1,3), “First creature has the wrong Description”);
equal(“2”, csvFile.at(1,4), “First creature must have 2 Strength”);
equal(“4”, csvFile.at(1,5), “First creature must have 4 Dexterity”);
equal(“1”, csvFile.at(1,6), “First creature must have 1 Wisdom”);
equal(“ShortSword”, csvFile.at(1,7), “First creature must have a ShortSword Weopn”);
equal(“All”, csvFile.at(1,8), “First creature must have be for All Dungeon Type”);

equal(“30”, csvFile.at(2,1), “Second creature must have 20 Maximum Health”);
equal(“Werewolf”, csvFile.at(2,2), “Second creature must be named Werewolf”);
equal(“glowing red eyes peer our from behind a long nose and sharp teeth”, csvFile.at(2,3), “Second creature has the wrong Description”);
equal(“5”, csvFile.at(2,4), “Second creature must have 5 Strength”);
equal(“2”, csvFile.at(2,5), “Second creature must have 2 Dexterity”);
equal(“1”, csvFile.at(2,6), “Second creature must have 1 Wisdom”);
equal(“Fists”, csvFile.at(2,7), “Second creature must have a Fists Weapon”);
equal(“BasicDungeon”, csvFile.at(2,8), “Second creature must have be for Basic Dungeon Type”);

equal(“20”, csvFile.at(3,1), “Third creature must have 20 Maximum Health”);
equal(“Evil Wizard”, csvFile.at(3,2), “Third creature must be named Evil Wizard”);
equal(“cackling over an old tome, this wizard seems insanely evil;\n or maybe just insane? it is hard to tell”, csvFile.at(3,3), “Third creature has the wrong Description”);
equal(“1”, csvFile.at(3,4), “Third creature must have 1 Strength”);
equal(“2”, csvFile.at(3,5), “Third creature must have 2 Dexterity”);
equal(“5”, csvFile.at(3,6), “Third creature must have 5 Wisdom”);
equal(“WizardsStaff”, csvFile.at(3,7), “Third creature must have a WizardsStaff”);
equal(“MagicalDungeon”, csvFile.at(3,8), “Third creature must have be for Magical Dungeon Type”);

return passFailText();
}
#include “wall.h”

using namespace core::dungeon;

Wall::Wall()
{

}
#include “game.h”
#include “weapons.h”
#include
#include

using namespace core::weapons;

/* ——————————————————————————
* Weapon member implementations
* —————————————————————————–*/

Weapon::Weapon()
{

}

Fists::Fists()
{

}

Boomerang::Boomerang()
{

}

ShortSword::ShortSword()
{

}

BattleAxe::BattleAxe()
{

}

WizardsStaff::WizardsStaff()
{

}

MagicWand::MagicWand()
{

}

/* ——————————————————————————
* Enchantment member implementations
* —————————————————————————–*/

Enchantment::Enchantment()
{

}

FlameEnchantment::FlameEnchantment()
{

}

ElectricityEnchantment::ElectricityEnchantment()
{

}

HealingEnchantment::HealingEnchantment()
{

}

VampirismEnchantment::VampirismEnchantment()
{

}
#ifndef BASICDUNGEON_H
#define BASICDUNGEON_H
#include “commondungeon.h”

namespace core {
namespace dungeon {

// TODO: define component classes spcific to the BasicDungeon type

/**
* @brief TODO The BasicDungeon class
*/
class BasicDungeon
{
public:
BasicDungeon();
};

/**
* @brief TODO The RockChamber class
*/
class RockChamber
{
public:
RockChamber();
};

/**
* @brief TODO The QuartzChamber class
*/
class QuartzChamber
{
public:
QuartzChamber();
};

/**
* @brief TODO The BasicWall class
*/
class RockWall
{
public:
RockWall();
};

} // namespace dungeon
} // namespace core

#endif // BASICDUNGEON_H
#ifndef CHARACTER_H
#define CHARACTER_H
#include

namespace core {

// TODO: define Character class.
// There is some example code in here, but it can be modified if desired.

/**
* @brief TODO The Complete the Character class, following is just a small example
*/
class Character
{
public:
Character(const std::string &name);

const std::string& name() const;

private:
std::string _name;
};

} // namespace core

std::ostream& operator<<(std::ostream &stream, const core::Character &character); #endif // CHARACTER_H #ifndef COMMONDUNGEON_H #define COMMONDUNGEON_H #include "dungeon.h" #include "room.h" #include "wall.h" #include "door.h" namespace core { namespace dungeon { // TODO: define concrete components classes common to all dungeon types /** * @brief TODO The OpenDoorway class */ class OpenDoorway { public: OpenDoorway(); }; } // namespace dungeon } // namespace core #endif // COMMONDUNGEON_H #ifndef CREATURE_H #define CREATURE_H #include

namespace core {
namespace creatures {

// TODO: define Creature class and the its concrete subclasses.
// There is some example code in here, but it can be modified if desired.

/**
* @brief TODO The Creature class
*/
class Creature
{
public:
Creature(const std::string &name);

const std::string& name() const;

private:
std::string _name;
};

} // namespace creatures
} // namespace core

#endif // CREATURE_H
#ifndef CSVFILE_H
#define CSVFILE_H

#include
#include

namespace data {

/**
* @brief The CsvFile class reads CSV data from a stream and makes it
* available to the application on a read-only basis.
*
* CSV Files contain tabular data in rows and columns according to the
* format defined by RFC 4180 [https://tools.ietf.org/html/rfc4180].
* (Ignore the requirement for fields contianign CRLF. We can assume
* that there are no CRLF in the input files.)
*
* The data is accessed through a simple inteface using row and column
* indices, both of which start at 1 (not zero). The interface also
* provides access to the header data, i.e., the column names.
*
* The CSV data is loaded in the constructor, from an input stream.
* This allows the data to be read from file or any other source connected
* to a stream.
*
* You will need to implement this class according to the provided interface.
* There is a set of tests provided in ‘testing.cpp’ for you to check that
* your implementation conforms. Be sure to enable testing in ‘testingsettings.h’
* to run the test suite and check your implementation.
*/
class CsvFile
{
public:
/**
* @brief CsvFile constructor, initialises internal data structures
* with CSV content from the input stream.
*
* Assumes the first row is a header row. If the input contains no
* content, the CsvFile is considered to have failed to load.
*
* @param input the stream from which to read the data
*/
CsvFile(std::istream &input);

/**
* @brief numberOfColumns Returns the number of columns in the CSV file,
* or -1 if the data failed to load.
*
* @return number of columns or -1
*/
int numberOfColumns() const;

/**
* @brief numberOfRows returns the number of rows in the CSV file,
* or -1 if the data failed to load.
*
* The header row is NOT included in the count of rows.
*
* @return number of rows or -1
*/
int numberOfRows() const;

/**
* @brief at Returns the content of the cell at the given row, column.
*
* Row indices start at 1, column indices start at 1.
* Returns an empty string if the CSV file failed to load or if row/column
* is out of range.
*
* @param row the row from which to retrieve the data
* @param column the column from whcih to retrieve the data
* @return the cell data at row, column
*/
std::string at(int row, int column) const;

/**
* @brief headerAt Returns the column name at the given index.
*
* Column indices start at 1.
* Returns an empty string if the CSV file failed to load or if column
* is out of range.
*
* @param column the index of the column
* @return the column name
*/
std::string headerAt(int column) const;

/**
* @brief columnIndexOf Returns the column index for the given column name.
*
* Returns -1 if the CSV file faild to load.
* Column indices start at 1.
*
* @param columnName the name of the column
* @return the index of the named column, or -1
*/
int columnIndexOf(const std::string &columnName) const;
};

} // namespace data

#endif // CSVFILE_H
#ifndef DOOR_H
#define DOOR_H

namespace core {
namespace dungeon {

/**
* @brief TODO The Door class
*/
class Door
{
public:
Door();
};

} // namespace dungeon
} // namespace core

#endif // DOOR_H
#ifndef DUNGEON_H
#define DUNGEON_H
#include “room.h”
#include

#include

namespace core {
namespace dungeon {

/*———————————————————————————–
* NOTE: to students – DO NOT modify or remove EXISTING members of this class.
* You will need to ADD methods to this class to implement the gameplay requirements.
*———————————————————————————–*/

/**
* @brief TODO The Dungeon class
*/
class Dungeon
{
public:
Dungeon();
virtual ~Dungeon() = default;

private:
int _anotherMember; //!< replace this with something real /*----------------------------------------------------------------------------------- * Original members below here, do not modify or remove them. *-----------------------------------------------------------------------------------*/ public: /** * @brief retrieveRoom Retrieve the room with the specified id. * @param id the room id to search for * @return a shared pointer to the Room or the nullptr if the no such Room exists */ std::shared_ptr retrieveRoom(int id);

/**
* @brief addRoom Adds the new room to the dungeon.
* @param newRoom the room to add
* @return true if the room was added, false if a room with the same id was already present
*/
bool addRoom(std::shared_ptr newRoom);

private:
std::map> _rooms; //!< stores the rooms of the Dungeon }; } // namespace dungeon } // namespace core #endif // DUNGEON_H #ifndef GAME_H #define GAME_H #include #include
#include
#include
#include
#include “character.h”
#include “dungeon.h”

namespace core {

/*———————————————————————————–
* NOTE: DO NOT modify or remove ALREADY IMPLEMENTED members of this class.
* You will need to COMPLETE the implementations of the suggested skeleton functions
* and/or ADD methods to this class to implement the gameplay requirements.
*
* To complete the implementations of the suggested functions you will need to
* fix their return types and/or parameters.
*
* The incomplete functions are just suggestions and you are free to implement your
* own as you see fit. Remember, though, the responsibility of the Game class is to
* maintain and update the game state, so any member functions you implement must be
* in fulfillment of that responsibility.
*———————————————————————————–*/

/**
* @brief TODO The Game class
*/
class Game
{
public:

// TODO implement the Game class

Game(); ///< You may need to change the parameters, accessibility, etc. of this. /** * @brief player Retrieves the player's Character, if any. */ void player() const; /** * @brief setPlayer Sets the current player character for the game. */ void setPlayer(); /** * @brief dungeon Returns the current dungeon level, if any. */ void dungeon() const; /** * @brief createDungeon Initiates the creation of a new dungeon level. * Any previous dungeon level is destroyed. */ void createDungeon(); /** * @brief start Initialises the game to the starting state, i.e., * the character has just entered the first room of the dungeon. */ void enterDungeon(); /** * @brief currentRoom Answers the current room the player's character is in. * @return the Room the player is in */ void currentRoom() const; /** * @brief navigate Move the player's character to a neighbouring * Room of the current room. */ void navigate(); /** * @brief navigateBack Move the character to the previous room. */ bool navigateBack(); /** * @brief exitLevel update the game state with successful completion * of the current level. */ void exitLevel(); /** * @brief exitDungeon update the game to the state where the character * has completely left the dungeon, ready for a completely new dungeon * to be created. */ void exitDungeon(); /** * @brief doActionRound Performs a player action (weapon attack, item use, * or special ability), including a responding attack by a creature if one is present. */ void doActionRound(); // Functions with provided implementations are declared below, DO NOT MODIFY /** * @brief randomIntBetween Returns a random integer between the provided min and max * values (inclusive). If max is smaller than low, the values are flipped to be safe. * * This function is a helper for randomly determining which types of room, item, * creature, etc., are present in a dungeon as well as determining damage values. * * @param min the low value * @param max the high value * @return the randomly generated integer */ int randomIntBetweenInc(int min, int max); /** * @brief randomIntBetweenEx Returns a random integer between the provided min and max * values (exclusive). If max is smaller than low, the values are flipped to be safe. * * This function is a helper for randomly determining which types of room, item, * creature, etc., are present in a dungeon as well as determining damage values. * * @param min the low value * @param max the high value * @return the randomly generated integer */ int randomIntBetweenEx(int min, int max); /** * @brief randomDouble Returns a random double in the range 0.0 - 1.0 * * This function is a helper for determining whether an attack is dodged, * as the dodge chance is a percentage. * * @return the randomly generated double */ double randomDouble(); private: std::mt19937 _randomGenerator; //!< Mersenne Twister random number generator seeded by current time std::uniform_real_distribution _realDistribution; //!< For random numbers between 0.0 & 1.0 }; } // namespace core #endif // GAME_H #ifndef MAGICALDUNGEON_H #define MAGICALDUNGEON_H #include "commondungeon.h" namespace core { namespace dungeon { // TODO: define component classes spcific to the MagicalDungeon type /** * @brief TODO The MagicalDungeon class */ class MagicalDungeon { public: MagicalDungeon(); }; /** * @brief TODO The EnchantedLibrary class */ class EnchantedLibrary { public: EnchantedLibrary(); }; /** * @brief TODO The AlchemistsLaboratory class */ class AlchemistsLaboratory { public: AlchemistsLaboratory(); }; /** * @brief TODO The MagicWall class */ class MagicWall { public: MagicWall(); }; } // namespace dungeon } // namespace core #endif // MAGICALDUNGEON_H #ifndef MENUINTERFACE_H #define MENUINTERFACE_H #include
#include
#include #include “testingsettings.h”

namespace core {

/**
* @brief The MenuInterface class encapsulates all user interaction with the game.
*
* It maintains a basic event loop that:
* 1) Displays the *current* menu
* 2) Waits for user input
* 3) Processes the user input
*
* Menus are implemented as pairs of functions:
* display…Menu()
* process…Selection(char selection)
* The former displays the possible selections to the user, while the latter
* processes the user input specific to that menu.
*
* There are already some helper functions implemented (or provided as skeletons)
* for warning the user of invalid input, confirming a user’s choice, pausing
* until the user hits [Enter] on the keyboard.
*
* There are also a couple of implemented functions that should not be touched
* as they are used for testing or in the core loop.
*
* NOTE: The base functionality has been implemented along with an example menu
* transition. The remainder of the suggested skeleton functions will need to
* be implemented (including return types and/or parameters) or replaced with
* your own. You do not have to use the provided structure, although it may
* simplify things for you if you do.
*/
class MenuInterface {
public:
MenuInterface(std::ostream &display, std::istream &input);
/**
* @brief displayWelcome display an intial welcome message including the
* student’s name and game title.
*
* Note: set the author name and game title using the macro definitions in main.cpp
*
* @param author the name of the student
* @param title the name of the game
*/
void displayWelcome(const std::string &author, const std::string &title) const;

/**
* @brief run Executes the main event loop
*/
void run();

private:
/**
* @brief The Menu enum identifies the menus the interface can display/process.
*/
enum class Menu { Main, DungeonSelect, CharacterDetails, Action, Combat };

std::ostream &_display; ///< the stream to pass all display output to std::istream &_input; ///< the stream to read all input from Menu _currentMenu; ///< keeps track of the current menu being displayed/processed /** * @brief displayMenu write the current menu to the display device */ void displayMenu() const; /** * @brief processSelection process the selection for the current menu. * @param selection the single character selection. * @return true to continue the program, false to quit. */ bool processSelection(char selection); /** * @brief getCharacterInput get a single character input from the input device * and clear the buffer until the next newline character. * @return the character input. */ char getCharacterInput() const; /** * @brief getIntInput get a single integer from the input device and clear the * buffer until the next newline character. Will reprompt if retrieving an * integer fails. * @return the integer input */ int getIntInput() const; /** * @brief warnSelectionInvalid Warns the user of an invalid menu selection * @param selection the character that was selected */ void warnSelectionInvalid(char selection) const; /** * @brief setMenu switches the menu interface state to the specified menu. * @param newMenu the menu to be displayed */ void setMenu(Menu newMenu); /** * @brief displayMainMenu write the main menu to the display device. */ void displayMainMenu() const; /** * @brief processMainMenuSelection process the selection for the main menu. * @param selection the single character selection * @return true to continue the program, false to quit. */ bool processMainMenu(char selection); /** * @brief playGame display and process the play game task. */ void playGame(); /** * @brief createCharacter display and process the create character task. */ void createCharacter(); /** * @brief dungeonTypeMenu display the select dungeon type task. */ void dungeonTypeMenu() const; /** * @brief processDungeonType process the select dungeon type task. * @param selection the single character selection */ void processDungeonType(char selection); /** * @brief switchToCharacterDetails If a Character is available, transition to the * character details menu, otherwise dislay an error and return to the previous menu. */ void switchToCharacterMenu(); /** * @brief quitGame displays the number of levels completed, if possible, before * prompting the user to confirm their intention to quit. */ bool quitGame() const; /** * @brief characterDetails display the character details task. */ void characterDetailsMenu() const; /** * @brief processCharacterDetails process the character details task. * @param selection the single character selection */ void processCharacterDetails(char selection); /** * @brief displayWeaponDetails Output the detailed weapon info to the user */ void displayWeaponDetails(); /** * @brief actionMenu display main action task choices. */ void actionMenu() const; /** * @brief processAction process the main action task. * @param selection the single character selection */ void processAction(char selection); /** * @brief combatMenu display combat action task choices. */ void combatMenu() const; /** * @brief processCombatAction process the combat action task. * @param selection the single character selection */ void processCombatAction(char selection); /** * @brief doNavigate Navigates the player's character according to their input. */ void doNavigate(); /** * @brief pickupWeapon Pick-up the weapon in the room, if any, and assign it * to the player. Prompts for user confirmation if the player already has an weapon. */ void pickupWeapon(); /** * @brief compareWeapons Display the player's current weapon and the weapon in the room if any. */ void compareWeapons(); /** * @brief doAttack Have the player perform the attack action */ void doAttack(); /** * @brief useSpecialAbility Have the player use its special ability/attack. */ void useSpecialAbility(); /** * @brief endGame Returns to the main menu, ending the current game/run through the dungeon. */ void leaveDungeon(); /** * @brief confirm display and process the confirmation of an action. * @param confirmationPrompt the string to use as the prompt for confirmation * @return true if use confirms yes, false otherwise */ bool confirm(const std::string &confirmationPrompt) const; // The functions below should not be modified. /** * @brief waitUntillNewline Helper function, pauses until the user hits [Enter] */ void waitUntillNewline() const { _display << std::endl << "*Press any key to continue*" << std::endl; #if not INPUT_SCRIPT _input.ignore(std::numeric_limits::max(), ‘\n’);
#endif
}

/**
* @brief echo Echoes the selection to the display. Used when running the input script.
* @param selection the single character selection
*/
template
inline void echo(T selection) const {
#if INPUT_SCRIPT
_display << selection << std::endl; #else selection = selection; // just to eliminate the warning #endif } struct _Centrew { int _width; }; ///< struct to hold the field width /** * @brief centre a basic stream manipulator type function that helps to centre a line of text * @param columns the number of columns * @param lineLength the number of characters in the line being centred * @return a _Setw struct to be used to configure the stream */ inline _Centrew centre(unsigned int columns, unsigned int lineLength) const { if (lineLength > columns) return _Centrew{0};
return _Centrew{static_cast((columns – lineLength) / 2 + lineLength)};
}

/**
* @brief operator << sets the field width of the stream based on the given centering specifier */ inline friend std::ostream& operator<<(std::ostream &stream, const _Centrew &rhs) { return stream << std::setw(rhs._width); } }; } // namespace core #endif // MENUINTERFACE_H #ifndef ROOM_H #define ROOM_H namespace core { namespace dungeon { /** * @brief TODO The Room class */ class Room { public: Room(int id); /** * @brief id Returns the unique integer id of the Room. * @return the unique id */ int id(); private: int _id; }; } // namespace dungeon } // namespace core #endif // ROOM_H #ifndef TESTING_H #define TESTING_H #include
#include
#include

/*
* NOTE: You MAY EDIT this file to perform testing as you progress through the assignment.
* Be sure to edit the implementation in testing.cpp as well.
*
* You may need to edit the original tests implementation as you implement your design.
* The original test implementations are just simple examples that do not necessarily
* reflect the final application.
*/

/**
* @brief The Testing class is a simple example of performing unit tests.
* You can modify as required to support the testing of your assignment.
*
* Tests should cover correct operation of your classes including (but not
* limited to): constructors, destructors, accessors, mutators, and public members.
*
* An incomplete example has been provided for you.
*/
class Testing
{
private:
// Declare functions for your own tests here.
// Be sure to update the implementation of runTests() to call the new tests.
// Each test function must return an std::string and should return passFailText()
// Refer to the provided examples.

// Example test function for the Character class
std::string testCharacter();
std::string testCreature();
std::string testDoor();
std::string testDungeon();
std::string testGame();
std::string testWeapon();
std::string testRoom();
std::string testWall();

// TODO: add functions for your own tests here

// Test functions for the CsvFile class.
// Do not modify! They are here for you to check your implementation for conformance.
// Your CsvFile implementation will be automatically tested against the same test
// suite but using different data.
void csvFileTestSuite();
std::string testLoadFailureForEmptyCsvFile();
std::string testLoadSuccessForHeaderButNoDataCsvFile();
std::string testOutOfRangeReturnsEmptyString();
std::string testHeaderFieldsCorrectlyRead();
std::string testCommaSeparatedRowDataAccessible();
std::string testMultipleRowsOfData();
std::string testLoadFailureOnRowWithDifferingNumberOfColumns();
std::string testPreservationOfWhitespaceInFields();
std::string testLineEndingOnLastLine();
std::string testDoubleQuotedFields();
std::string testDoubleQuotedFieldsMixedWithUnquoted();
std::string testReplacementOfBlackslashNInQuotedFieldsWithNewline();
std::string testDoubleQuotesWithinFields();
std::string testReadingCsvDataFromFile(); // once the rest of the tests pass, so should this one

public:
/**
* @brief Testing default constructor to safely initialise the internal state.
*
* It is implemented in the header to keep the source file clean. That is,
* ‘testing.cpp’ will contain only the implementations of your test functions.
*/
Testing(): _failureCount{0}, _assertionCount{0}, _failure{false}, _failMessages{} {
// No other setup required.
}
~Testing() = default;

/**
* @brief runTests the entry point for running one or more tests.
*
* Be sure to update its implementation each time you add a new test.
*/
void runTests();

/**
* @brief printFailures outputs the collected failure messages to the given stream
* @param ostream
*/
void printTestResults(std::ostream &ostream);

private:
unsigned int _failureCount; ///< count of all failures that have occurred unsigned int _assertionCount; ///< tally of the number of assertions made bool _failure; ///< boolean indicating failure state of current test std::stringstream _failMessages; ///< stream to collect failure messages during testing /* ------------------------------------------------------------------------------ * The following are helper functions that operate a little like common * Unit Testing frameworks. You do not need to understand their implementations, * but hopefully you will by the end of the course. * -----------------------------------------------------------------------------*/ /** * @brief equals Test support function, compares the expected and actual values, if they * are not equal to one another, puts the Testing object into the failure * state and appends failMessage to the output to be reported later. * * @param expected the expected value * @param actual the actual value * @param failMessage the message to display if the test fails */ template
void equal(const T &expected, const T &actual, const std::string &failMessage) {
++_assertionCount;
if (expected != actual) {
++_failureCount;
_failure = true;
_failMessages << failMessage << " [expected: " << expected << " actual: " << actual << "]" << std::endl; } } /** * @brief equals Test support function, compares the expected and actual values, if they * are equal to one another, puts the Testing object into the failure * state and appends failMessage to the output to be reported later. * * @param expected the expected value * @param actual the actual value * @param failMessage the message to display if the test fails */ template
void notEqual(const T &expected, const T &actual, const std::string &failMessage) {
++_assertionCount;
if (expected == actual) {
++_failureCount;
_failure = true;
_failMessages << failMessage << " [value: " << expected << "]" << std::endl; } } /** * @brief lessThan Test support function, compares the expected and actual values, * if they actual is greater than or equal to expected, puts the Testing object into the failure * state and appends failMessage to the output to be reported later. * * @param expected the expected value * @param actual the actual value * @param failMessage the message to display if the test fails */ template
void lessThan(const T &expected, const T &actual, const std::string &failMessage) {
++_assertionCount;
if (actual >= expected) {
++_failureCount;
_failure = true;
_failMessages << failMessage << " [expected less than: " << expected << " actual: " << actual << "]" << std::endl; } } /** * @brief greaterThan Test support function, compares the expected and actual values, * if they actual is less than or equal to expected, puts the Testing object into the failure * state and appends failMessage to the output to be reported later. * * @param expected the expected value * @param actual the actual value * @param failMessage the message to display if the test fails */ template
void greaterThan(const T &expected, const T &actual, const std::string &failMessage) {
++_assertionCount;
if (actual <= expected) { ++_failureCount; _failure = true; _failMessages << failMessage << " [expected greater than: " << expected << " actual: " << actual << "]" << std::endl; } } /** * @brief instanceOf Test support function, checks if the value of the given pointer * is of the template type T. If not, the Testing object is put into the fail state * and the failure message is appended. * * @param value the shared pointer to check the type * @param failMessage */ template
void instanceOf(const std::shared_ptr &value, const std::string &failMessage) {
++_assertionCount;
if (!std::dynamic_pointer_cast(value)) {
++_failureCount;
_failure = true;
_failMessages << failMessage << std::endl; } } /** * @brief passFailText convenience function to return the "Passed" or "Failed" strings. * @return "Pass" or "Fail" */ inline std::string passFailText() { bool failed = _failure; _failure = false; // reset state for next test return failed ? "Failed" : "Passed"; } }; inline void Testing::printTestResults(std::ostream &ostream) { ostream << std::endl; ostream << _assertionCount << " tests executed; " << _assertionCount - _failureCount << " tests passed; " << _failureCount << " failures" << std::endl; if (_failMessages.rdbuf()->in_avail()) {
ostream << "Failures:" << std::endl; ostream << _failMessages.str() << std::endl; } else { ostream << "All tests passed!" << std::endl; } } template<>
inline void Testing::equal(const std::string &expected, const std::string &actual, const std::string &failMessage) {
++_assertionCount;
if (expected != actual) {
++_failureCount;
_failure = true;
_failMessages << failMessage << " [expected: " << '\'' << expected << '\'' << " actual: " << '\'' << actual << '\'' << "]" << std::endl; } } #endif // TESTING_H #ifndef TESTINGSETTINGS_H #define TESTINGSETTINGS_H /* Edit this file to enable and disable tests. */ // When switching modes, it is best to do a 'clean' or, // equivalently, a 'rebuild'. // You can do this by right-clicking on project folder // and selecting 'clean' or 'rebuild' as desired. // Set this to 1 to run the testing, 0 to run normal mode. #define TESTING 1 // Set this to 1 to run the game using the input script // In order to work, the provided input script relies on // the generation of goblins as the only creature and // either the potion or acid flask items as items. #define INPUT_SCRIPT 0 // If this is 1, the output generated from the INPUT_SCRIPT // will be stored directly in file rather than output to // the console. // Only has an effect of INPUT_SCRIPT is 1 #define OUTPUT_SCRIPT 0 #endif // TESTINGSETTINGS_H #ifndef WALL_H #define WALL_H namespace core { namespace dungeon { /** * @brief TODO The Wall class */ class Wall { public: Wall(); }; } // namespace dungeon } // namespace core #endif // WALL_H #ifndef WEAPONS_H #define WEAPONS_H namespace core { namespace weapons { /** * @brief TODO The Weapon class */ class Weapon { public: Weapon(); }; /** * @brief TODO The Fists class */ class Fists : public Weapon { public: Fists(); }; /** * @brief TODO The Boomerang class */ class Boomerang : public Weapon { public: Boomerang(); }; /** * @brief TODO The ShortSword class */ class ShortSword : public Weapon { public: ShortSword(); }; /** * @brief TODO The BattleAxe class */ class BattleAxe : public Weapon { public: BattleAxe(); }; /** * @brief TODO The WizardsStaff class */ class WizardsStaff : public Weapon { public: WizardsStaff(); }; /** * @brief TODO The MagicWand class */ class MagicWand : public Weapon { public: MagicWand(); }; /** * @brief TODO The Enchantment class */ class Enchantment { public: Enchantment(); }; /** * @brief TODO The FlameEnchantment class */ class FlameEnchantment : public Enchantment { public: FlameEnchantment(); }; /** * @brief TODO The ElectricityEnchantment class */ class ElectricityEnchantment : public Enchantment { public: ElectricityEnchantment(); }; /** * @brief TODO The HealingEnchantment class */ class HealingEnchantment : public Enchantment { public: HealingEnchantment(); }; /** * @brief TODO The VampirismEnchantment class */ class VampirismEnchantment : public Enchantment { public: VampirismEnchantment(); }; } // namespace items } // namespace core #endif // WEAPONS_H