Click here to Skip to main content
15,888,461 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am currently making a text-based game. In this game, the character has to move around between rooms. Each room as a "roomAddress" or "roomId". Currently, I am trying to make the options for a level. Then, when an option is made, the character moves or does something like pick up an item.

Right now, I have the base for moving between rooms set up. I also have created 2 room IDs: "Introduction" and "StartingRoom_1_f_1". However, when trying to move from "Introduction" to "StartingRoom_1_f_1", I get an error message ( NOT a compileation error, a self-made error handling message). This message reads:
cout << "Next room not defined for the chosen option." << endl;

Note: I'm not entirely sure what all needs to be included, so I wil try to keep it short, but it may not work right away. Please tell me if this is so.

main.cpp:
C++
#include "StarterIncludeFile.hpp" //Assume that all needed includes are here. So if there is an include you need, it's wrapped in here
#include "entities.hpp"
#include "levels.hpp"
#include "outputHandling.hpp"
#include "playLevels.hpp"
#include "inputHandling.hpp"

int main() {
    createValidInput();
    Player player = createPlayer();
    vector<item> itemsInInventory = player.itemsInInventory;
    initializeLevelInfo();
    playGame();
    return 0;
}



levels.hpp:
C++
vector<string> createOptions(string roomId, string progression);
string createDescription(string roomId, string progression);
vector<item> itemsOnFloor;

// Define a struct to hold level information
struct LevelInfo {
    std::string description;
    std::vector<std::string> options;
};

// Define a map to hold level information based on roomId and progression
std::unordered_map<std::string, std::unordered_map<std::string, LevelInfo>> levelInfo;

// Define a map to hold transitions between rooms based on choices
unordered_map<string, unordered_map<string, string>> transitions;

// Function to initialize level information
void initializeLevelInfo() {
    // Define descriptions and options for each level
    levelInfo["Introduction"]["beginning"] = {
        "In the vast expanse of the cosmos, humanity teeters on the edge of insignificance, our existence but a fleeting whisper in the echoing\nchambers of eternity.\n"
        "We scurry about like ants beneath the gaze of titanic beings, ancient gods who regard us with indifferent eyes, if they regard us at\nall.\n"
        "In this realm where mortal coils and consciousness unravel, we are but morsels of flesh adrift in a sea of shadows.\n\n"
        "Our cities, our achievements, our very essence, pale against the backdrop of cosmic indifference.\n"
        "Yet amidst the darkness, whispers linger of forgotten truths, of entities that loom beyond the veil of comprehension.\n"
        "Their presence whispers through the rustling leaves, their footsteps echoing in the silence of the night.\n\n"
        "There are those who speak of a shepherd, a figure shrouded in myths and legends, whose gaze transcends the boundaries of mortality.\n"
        "They say he walks among us, his presence a beacon of hope amidst the encroaching darkness.\n"
        "But beware, for even the shepherd's light may cast long shadows, and salvation may come at a price too terrible to comprehend.\n\n"
        "As you venture forth into this realm of uncertainty, remember the fragility of human life, the insignificance of our existence in the eyes of our gods and beings beyond mortal ken.\n"
        "For in this world of shadows and whispers, even the faintest glimmer of hope may be swallowed whole by the abyss.",
        {"Continue"} // No options for Introduction at beginning
    };
    
    levelInfo["StartingRoom_1_f_1"]["beginning"] = {
        "You wake up in your bedroom. It's not exactly the cleanest... or the brightest, but it's home.\n"
        "You rise out of bed and stand up.\n"
        "It's time to get to work... the day is fresh.",
        {"Walk Forward", "Check Inventory"}
    };
    
    //Beggining transitions
    // Define transitions between rooms based on choices
    transitions["Introduction"]["Option 1"] = "StartingRoom_1_f_1";
}

struct Level {
    string displayName;
    string levelAddress;
    int floorNumber;
    string description;
    vector<string> options;
    vector<item> itemsOnFloor;
    bool doesGameContinue;
};

// Function to create Level based on roomId and progression
Level createLevel(string roomId, string displayName, string progression, int floorNumber, vector<item> itemsOnFloor) {
    Level level;
    level.displayName = displayName; 
    level.levelAddress = roomId; 
    level.floorNumber = floorNumber;
    level.description = levelInfo[roomId][progression].description;
    level.options = levelInfo[roomId][progression].options;
    level.itemsOnFloor = itemsOnFloor;
    level.doesGameContinue = true; // Assuming game continues by default
    return level;
}

vector<Level> beginningLevels {
    createLevel("Introduction", "Introduction", "beginning", 0, {} /*No items on the floor*/),
    createLevel("StartingRoom_1_f_1", "Starting Room, Facing Forward", "beginning", 1, {{"Coins", 5, false, "Currency"}})
};



outputHandling.hpp:
C++
//Display the description of a beginning level
void displayDescription(string roomId, string progression) {
    string description;

    // Check if the roomId and progression combination exists in levelInfo
    if (levelInfo.find(roomId) != levelInfo.end() &&
        levelInfo[roomId].find(progression) != levelInfo[roomId].end()) {
        description = levelInfo[roomId][progression].description;
    }

    // If the description is not empty, display it
    if (!description.empty()) {
        cout << description << endl << endl;
    } else {
        cout << "Description not found for the given roomId and progression." << endl;
    }
}

// Display the options of a level
void displayOptions(string roomId, string progression) {
    vector<string> options;

    // Check if the roomId and progression combination exists in levelInfo
    if (levelInfo.find(roomId) != levelInfo.end() &&
        levelInfo[roomId].find(progression) != levelInfo[roomId].end()) {
        options = levelInfo[roomId][progression].options;
    } else {
        cout << "Room ID or progression not found." << endl;
        return;
    }
    
    cout << "Your options: " << endl;

    // If options are found, display them
    if (!options.empty()) {
        for (int i = 0; i < options.size(); ++i) { cout << i + 1 << ". " << options[i] << endl; }
    } else { cout << "No options available for this level." << endl; }

    cout << endl << endl;
}



entities.hpp:
C++
struct item {
    string name;
    int quantityOnGround;
    bool hasBeenUsed;
    string className;
    int quantityCollected;
    int currentQuantity;
};

struct Player {
    int numberItems;
    int numberDeaths;
    vector<item> itemsInInventory;
    string roomAddress;
    int floorNumber;
};

//Initialize the player statistics
void initializePlayer(Player& player) {
    player.numberItems = 0;
    player.numberDeaths = 0;
    player.roomAddress = "Starting Room";
    player.floorNumber = 0;
    handItem(player, "NONE", 0, false, "NAN", 0, 0);
}

//Define the function to create a player
Player createPlayer() {
    Player player;
    initializePlayer(player);
    return player;
}



playLevels.hpp:
C++
string actionChoice;
bool gameContinues = true;
string beginningProgressionRoomID = ""; //Change this room ID so that it is determined when you move to middle levels
string middleProgressionRoomID = ""; //Change this room ID so that it is determined when you move to final levels

// Function to play a level
int playLevel(string roomId, string progression) {
    displayDescription(roomId, progression);
    displayOptions(roomId, progression);
    cout << "What would you like to do? ";
    int actionChoice;
    cin >> actionChoice;
    return actionChoice;
}

void playGame() {
    string roomId = "Introduction"; // Start at the Introduction level
    string progression = "beginning";

    // Loop until the game ends
    while (true) {
        // Play the current level
        int choice = playLevel(roomId, progression);

        // Handle the player's choice
        if (choice >= 1 && choice <= levelInfo[roomId][progression].options.size()) {
            string chosenOption = levelInfo[roomId][progression].options[choice - 1];
            
            if (transitions.find(roomId) != transitions.end() &&
                transitions[roomId].find(chosenOption) != transitions[roomId].end()) {
                // Update progression based on the transition
                roomId = transitions[roomId][chosenOption];
                if (roomId == beginningProgressionRoomID) { progression = "middle"; /*Move to the "middle" level*/} else
                if (roomId == middleProgressionRoomID) { progression = "final"; /* Move to the "final" level*/ } else
                { progression = "beginning"; /*Move to the "beginning" level*/}
            } else {
                // Handle the case where the next room is not defined
                cout << "Next room not defined for the chosen option." << endl;
                return;
            }
        } else {
            // Handle the case of an invalid option
            cout << "Invalid option. Please choose again." << endl;
        }
    }
    
    endGame();
}


What I have tried:

I have tried changing some if statements, refactoring my levels, creating and deleting random things, almost anything. I can't actually figure out what is happening.

I have done some couts and checks. In "outputHandling.hpp", the line
C++
if (levelInfo.find(roomId) != levelInfo.end() &&
        levelInfo[roomId].find(progression) != levelInfo[roomId].end())


is determined as false. Causing the error message to run.

As a side note: One of the last versions of this code I had used a "nextRoomId" which (as implied) was the ID of the next room.If I did
cout << nextRoomID << ": next room id";
I would get a blank space,
Posted
Updated 9-Apr-24 14:56pm
v2
Comments
merano99 10-Apr-24 16:07pm    
Undeclared functions and identifiers: displayDescription, levelInfo, transitions, handItem, endGame.

1 solution

Compiling does not mean your code is right! :laugh:
Think of the development process as writing an email: compiling successfully means that you wrote the email in the right language - English, rather than German for example - not that the email contained the message you wanted to send.

So now you enter the second stage of development (in reality it's the fourth or fifth, but you'll come to the earlier stages later): Testing and Debugging.

Start by looking at what it does do, and how that differs from what you wanted. This is important, because it give you information as to why it's doing it. For example, if a program is intended to let the user enter a number and it doubles it and prints the answer, then if the input / output was like this:
Input   Expected output    Actual output
  1            2                 1
  2            4                 4
  3            6                 9
  4            8                16
Then it's fairly obvious that the problem is with the bit which doubles it - it's not adding itself to itself, or multiplying it by 2, it's multiplying it by itself and returning the square of the input.
So with that, you can look at the code and it's obvious that it's somewhere here:
C#
private int Double(int value)
   {
   return value * value;
   }

Once you have an idea what might be going wrong, start using the debugger to find out why. Put a breakpoint on the first line of the method, and run your app. When it reaches the breakpoint, the debugger will stop, and hand control over to you. You can now run your code line-by-line (called "single stepping") and look at (or even change) variable contents as necessary (heck, you can even change the code and try again if you need to).
Think about what each line in the code should do before you execute it, and compare that to what it actually did when you use the "Step over" button to execute each line in turn. Did it do what you expect? If so, move on to the next line.
If not, why not? How does it differ?
Hopefully, that should help you locate which part of that code has a problem, and what the problem is.

In this case, you have decided that a specific test is false - the question is "why?" which part of that is false - remember that it requires both sides of the AND to be true in order to give a true result. So use the debugger and find out which part is false - then run it again to find out why it is false when it should be true. Rinse and repeat!

This is a skill, and it's one which is well worth developing as it helps you in the real world as well as in development. And like all skills, it only improves by use!
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900