0
\$\begingroup\$

I’m coding a text-based RPG and I have my controls working: I have a string checking what you write in against an array of if statements.

It can get it right with everything other than my pick up action.

My if statements are set out as follows:

int game_main() { 

    string PlayerOption;

    //I have a few lines of cout statements just for my gui/hud

    cin >> PlayerOption;

    if (PlayerOption == "look") { 
        //it’s then just calling a script from a separate header file 
    }
    else if (PlayerOption == "pick up") {
        //another script from that header 
    }

My look command and all my others work but I don’t know how to set it up right.

I've tried putting it like "pick up", I tried it like "pick"" ""up" and a couple other ways but I don’t know how to properly write the expression.

Even then my problem might be with my string and not my if statement so any suggestions would be greatly appreciated.

And I think @DMGregory might be right about the word boundaries because even with that command if I make it accept "pick" it works it’s only when I ask it for two words it really breaks

Is there any way I could get around that?

\$\endgroup\$
  • 1
    \$\begingroup\$ The tiny sample of code here makes it difficult to infer what's happening. Are you saying the variable PlayerOption is holding a two word value "pick up" and somehow that is comparing as not equal to the literal string "pick up"? Strings have no built-in concept of word boundaries, so this might point to a problem in how you populate your variable (maybe your input routine grabbed only "pick"?), differences in case, or a non-printing character in one of the strings. Or do you mean PlayerOption contains an unknown word, like "pickup octopus" which naturally is not equal to "pickup"? \$\endgroup\$ – DMGregory Nov 10 at 13:50
  • \$\begingroup\$ It's hard to figure out how to help without seeing your parsing implementation. \$\endgroup\$ – Casey Nov 10 at 22:47
  • \$\begingroup\$ @Casey: I think this is their whole parsing implementation - just taking a raw line of text from cin (standard input stream) and comparing it with if statements. Tj, can you please clarify, does the problem occur when the player types in literally "pick up" or only when they try to add an object to the phrase, like "pick up unicycle"? \$\endgroup\$ – DMGregory Nov 10 at 22:59
2
\$\begingroup\$

Using cin by itself is not going to work in all cases because it automatically stops at whitespace. It will be much easier to grab the whole string at once and parse it into "commands" and "arguments":

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

std::vector<std::string> Split(const std::string& string, char delim = ',', bool skip_empty = true) noexcept;
std::pair<std::string, std::vector<std::string>> ParsePlayerOption(const std::string& playeroption);
void Pick(const std::vector<std::string>& args);
void Look(const std::vector<std::string>& args);

std::vector<std::string> Split(const std::string& string, char delim /*= ','*/, bool skip_empty /*= true*/) noexcept {
    std::size_t potential_count = 1 + std::count(string.begin(), string.end(), delim);
    std::vector<std::string> result;
    result.reserve(potential_count);
    std::string curString;

    std::stringstream ss;
    ss.str(string);
    ss.seekg(0);
    ss.seekp(0);
    ss.clear();

    while(std::getline(ss, curString, delim)) {
        if(skip_empty && curString.empty()) continue;
        result.push_back(curString);
    }
    if(!skip_empty && ss.eof() && string.back() == delim) {
        result.push_back(std::string{});
    }
    result.shrink_to_fit();
    return result;
}


std::pair<std::string, std::vector<std::string>> ParsePlayerOption(const std::string& playeroption) {
    const auto first_space_pos = playeroption.find_first_of(' ');
    std::string command = playeroption.substr(0, first_space_pos);
    std::string args_list = playeroption.substr(first_space_pos);
    auto args = Split(args_list, ' ');
    return std::make_pair(command, args);
}

void Pick(const std::vector<std::string>& args) {
    if(args.front() == "up") {
        std::vector<std::string> item_list{args.begin() + 1, args.end()};
        DoPickUp(item_list);
    } else { //Not a "pick up" command. Could be like "pick flower".
        DoPick(args);
    }
}

int game_main() { 

    string PlayerOption;

    //I have a few lines of cout statements just for my gui/hud
    std::getline(std::cin, PlayerOption);

    const auto [command,args] = ParsePlayerOption(PlayerOption);

    if (command == “look”) { 
        //Do look command
        Look(args); //Trivial to implement
    } else if (command == “pick") {
        //Do partial "pick" command.
        Pick(args);
    }
}
\$\endgroup\$
0
\$\begingroup\$

Another option: use single word tokens.

Instead of using pick up for your command, use pickup.

And do the same for the parameters.

This will simplify the parsing, the processing, the documentation, etc. of the game.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.