6
\$\begingroup\$

This is my code for The Mysts of Aesthoth so far. I'd like to know if I'm following best practices, and what can be improved.

/*
______________________________________
This Program was made by: Andrew Tew
______________________________________

*/

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

int main()
{
//EVERYTHANG IN DER BACKGRUND

int Charma = 0;
unsigned int Hunger = 10;
unsigned int Energy = 50;
unsigned int Health = 100;

string Ans1;
string Ans2;
string Ans3;
string Ans4;
string Ans5;
string Ans6;
string Ans7;
string Ans8;
string Ans9;
string Ans10;
string Ans11;
string Ans12;
string Ans13;
string Ans14;
string Ans15;
string Ans16;
string Ans17;
string Ans18;
string Ans19;
string Ans20;
string Ans21;
string Ans22;
string Ans23;
string Ans24;
string Ans25;
string Ans26;
string Ans27;
string Ans28;
string Ans29;
string Ans30;
string AnsCharSure;

string eyecolor;
string skintone;
string haircolor;
string height;
string name;
string race;
string gender;

bool dead = false;
bool human = false;
bool orc = false;
bool goblin = false;
bool elf = false;
bool lizard = false;
bool cat = false;
bool vampire = false;
bool werewolf = false;
bool SNK = false;
bool Get_Backpack = false;

StartScreen:
system ("cls");
system ("color 0c");
system ("title Mysts of Altyar");
cout << "|---------------------------| Answer all questions in all lowercase letters\n";
cout << "|    The                    |      and single words\n";
cout << "|Mysts of Altair            | Answer all questions yes/no unless otherwise\n";
cout << "|            by: Andrew Tew |     specified\n";
cout << "|---------------------------| Enjoy and have fun!\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
system ("pause");
system ("cls");
system ("color 0e");
BackStory:
cout << "There once was an old man who's name was\n";
cout << "Stewart.\n\n\n";
system ("pause");
system ("cls");
cout << "Stewart has stayed isolated for the majority of the old man\n";
cout << "portion of his life. He wasted his time playing pointless\n";
cout << "games such as Realm of the Mad God, World of Warcraft, and\n";
cout << "pretty much just staring at a screen pressing buttons on a\n";
cout << "Keyboard.\n\n\n";
system ("pause");
system ("cls");
cout << "Then one day... something peculiar happened.\n\n\n";
system ("pause");
system ("cls");
cout << "Stewart had an urge to get up from his smelly old chair and\n";
cout << "walk out of his hut. He decided to go on an adventure through\n";
cout << "the forest!\n\n\n";
system ("pause");
system ("cls");
system ("color 0a");
cout << "Stewart thought the forest smelled splendid! The scent of the\n";
cout << "trees filled the air! Stewart also found the absolute beauty of\n";
cout << "nature splendid as well.\n\n\n";
system ("pause");
system ("cls");
cout << "Before long, Stewart found himself standing in a circle of trees\n";
cout << "with a wide open spot in the middle that contained nothing but a\n";
cout << "stone block with some sort of ancient writing on it.\n";
cout << "          ____________________________ \n"; 
cout << "        /                            /|\n";
cout << "       /Some sort of Ancient Writing/ |\n";
cout << "      /____________________________/  |\n";
cout << "      |                            |  /\n";
cout << "      |                            | /\n";
cout << "      |____________________________|/\n\n\n";
system ("pause");
system ("cls");
cout << "Does Stewart ";
cout << "throw the brick at the ground? ";
cin >> Ans1;
cout << "\n";
if (Ans1 == "yes"){
    cout << "Stewart walked through the dirt towards the stone and he then\n";
    cout << "picked the brick up and decided (as any sensible person would)\n";
    cout << "to throw the brick at the dirt..\n\n\n";
    system ("pause");
    system ("cls");
}else {cout << "Stewart walked through the dirt towards the stone and felt\n";
cout << "a strange urge to touch it. Although the urge was quite obviously\n";
cout << "a hint that the story lays beyond, he walks back to his hut.\n";
cout << "Stewart lived a crappy life and died the next month.\n\n\n";
system ("pause");
system ("cls");
goto StartScreen;
}
system ("color 09");
cout << "The brick shattered and released a dark blue smoke that had laid\n";
cout << "within the brick for 1000s of years. The smoke began to surround\n";
cout << "Stewart spinning rapidly around him until everything suddenly went\n";
cout << "black.\n\n\n";
system ("pause");
system ("cls");
system ("color f0");
cout << "Stewart woke up to the sound of the waves crashing against the shore\n";
cout << "of the sandy beach.\n\n\n";
system ("pause");
system ("cls");
cout << "As Stewart stands up he sees a figure walking in the distance...\n\n\n";
WhoAreYou:
cout << "Who... are you?\n";
Race:
cout << "What race are you? ";
cin >> race;
if (race == "lizard"){
    lizard = true;
    goto SkinTone;
}
if (race == "elf"){
    elf = true;
}
if (race == "orc"){
    orc = true;
}
if (race == "SupahNinjaKitty"){
    SNK = true;
}
if (race == "cat"){
    cat = true;
}
if (race == "goblin"){
    goblin = true;
};
if (race == "human"){
    human = true;
}
Gender:
cout << "What is your gender (Male, Female, It)? ";
cin >> gender;
HairColor:
cout << "What color hair do you have? ";
cin >> haircolor;
SkinTone:
cout << "What tone of skin do you have? ";
cin >> skintone;
EyeColor:
cout << "What color eyes do you have? ";
cin >> eyecolor;
Height:
if (goblin = true){
    goto Name;
}
cout << "Are you tall or short? ";
cin >> height;
if (haircolor == "black" && skintone == "white" && eyecolor == "red" && height == "tall"){
    vampire = true;
}
if (haircolor == "brown" && skintone == "brown" && eyecolor == "brown" && height == "tall"){
    werewolf = true;
}
Name:
cout << "What is your first name? ";
cin >> name;
cout << "\n\n\n";
cout << "\tAre you sure this is who you want to be?\n";
cout << "\t\tYou won't be able to return after this.\n";
cin >> AnsCharSure;
if (AnsCharSure == "yes"){
}else {
    system ("cls");
    goto WhoAreYou;
}
system ("pause");
system ("cls");
cout << "As you turn your head you see a peculiar looking  old\n";
cout << "man dressed in saggy clothes that are littered with\n";
cout << "wrinkles all over his sweatpants and sweatshirt\n";
cout << "and on his whole person he was littered with stains\n";
system ("pause");
test1:
system ("cls");
cout << "Do you approach that strange old guy? ";
cin >> Ans2;
if (Ans2 == "yes"){
    cout << "\nYou approach that old guy debating whether or not\n";
    cout << "he seems 100% human. Maybe he's from your home world,\n";
    cout << "Earth.\n";
}else {
    cout << "That old guy runs towards you.\n\n";
    cout << "Do you...\n";
    cout << "Kill Him? ";
    cin >> Ans3;
    if (Ans3 == "yes"){
        cout << "You attempt to kill that old guy with your fists, but\n";
        cout << "He shoots lasers from his eyes and kills you in 2\n";
        cout << "seconds\n";
        system ("pause");
        goto StartScreen;
    }else {
        cout << "Run? ";
        cin >> Ans4;
        if (Ans4 == "yes"){
            cout << "You run from that crazy old guy, but his laser eyes\n";
            cout << "catch you and you die\n\n\n";
            system ("pause");
            goto StartScreen;
        }else{
            cout << "Teleport? ";
            cin >> Ans5;
            if (Ans5 == "yes"){
                cout << "You teleport into... \n";
                cout << "Enter a number 1-10 to see if you live :O\n";
                cin >> Ans5;
            }else {
            }if (Ans5 == "7"){
                cout << "You teleport to Earth and live!\n";
                cout << "But you obviously still died because of\n";
                cout << "the mass pollution on earth...\n";
                system ("pause");
                goto StartScreen;
            }else {
                cout << "You teleport somewhere where particles don't move for measly\n";
                cout << race << "s and you die from never existing O.O\n\n\n";
                system ("pause");
                goto StartScreen;
            }
        }
    }
}
system ("cls");
cout << "Unknown: what is your name? Who are you?\n";
cout << "He seemed bewildered and out of breath.\n\n\n\n";
cout << "Do you...\n";
cout << "Say your name?";
cin >> Ans6;
if (Ans6 == "yes"){
    cout << "You: My name is " << name << "\n\n";
    cout << "Unknown: Hello " << name << " I am Stewart.\n\n\n";
}else {
    cout << "(Threaten)Ask for his name first?";
    cin >> Ans7;
}if (Ans7 == "yes"){
    Charma = Charma - 1;
    cout << "(Success!)Unknown: M- M- My name is Stewart... I don't know how\n";
    cout << "I got here, wh- who are you?\n\n";
    cout << "You: I am " << name << "\n\n\n";
    cout << "Charma -1\n\n\n";
}
system ("pause");
system ("cls");
cout << "Stewart: TICKLE ME!\n";
cout << "Do you tickle him?\n\n";
cin >> Ans8;
if (Ans8 == "yes"){
    cout << "You tickle him until the point he explodes\n and a bear comes and eats you both.\n\n\n";
}else {
    cout << "Stewart: Oh thank god your not a creeper that was just a test.\n\n\n";
}
system ("pause");
system ("cls");

cout << "Stewart: would you like to go on an adventure with me? \n";
cin >> Ans9;
if (Ans9 == "yes"){
    cout << "Then lets get started shall we?\n\n\n";
}else{
    cout << "You drown in tears\n\n\n";
    system ("pause");
    goto StartScreen;
}
system ("pause");
ChapterOne:
system ("cls");
cout << "\n\n\n\n\n\t\tChapter 1: The Forest\n\n\n";
cout << "Everytime you die you will now respawn to this checkpoint :D, your welcome.\n\n\n\n";
system ("pause");
Fork:
system ("cls");
cout << "As you begin you great adventure through the forest you and Stewie\n (as you now call him)\n";
cout << "find yourselves at a 3-way forked path through the trees once you\n go one way you can't go any";
cout << "other way.\n\n";
cout << "Stewie: I think we should go right... my mother once told me";
if (Charma <= -1){
    cout << "...(you zone out)\n\n";
}if (Charma >= 0){
    cout << " that the path that leads right either leads to bears or victory!\n\n";
}
cout << "Do you go left, straight, or right?";
cin >> Ans10;
if (Ans10 == "left"){
    system ("cls");
    cout << "you go left and travel for 3 hours before realizing that you keep ending up at the same fork.\n";
    Hunger = Hunger - 1;
    Energy = Energy - 1;
    system ("pause");
    goto Fork;
}if (Ans10 == "right"){
    system ("cls");
    cout << "After traveling on the right path for hours you hear twig snap.\n";
    cout << "Suddenly you hear a booming roar coming from your left, it's\n";
    cout << "a BEAR!";
    cout << "Stewie tripped and got eaten, soon you were devoured also...\n";
    system ("pause");
    system ("cls");
    goto ChapterOne;
}if (Ans10 == "straight"){
    system ("cls");
    cout << "You go straight (since you are more cool than Stewie) and continue on your\n";
    cout << "journey glad that you didn't get lost or die. Good thing you didn't\n";
    cout << "listen to Stewie!\n";
    system ("pause");
    system ("cls");
}
adven1:
cout << "After hours of adventuring you and Stewie grow exhausted\n";
cout << "in the distance you see an adventurer with a pretty desirable\n";
cout << "backpack on...\n";
cout << "Do you...\n";
cout << "Get the backpack?\n";
cin >> Ans11;
if (Ans11 == "no"){
    goto ignadv1;
}
if (Ans11 == "yes"){
    cout << "How do you get the backpack?\n";
    cout << "kill, mug, nevermind\n";
    cin >> Ans12;
}
    if (Ans12 == "nevermind"){
        goto ignadv1;
    }if (Ans12 == "mug"){
        cout << "You walk up to the adventurer...\n";
        cout << "Adventurer: Hi! I'm Timothy, pleased to meet you!\n";
        Charma = Charma - 3;
        cout << name << ": Hand over the backpack... now\n";
    }
            if (Charma <= -4){
                cout << "Adventurer: Okay! Okay! Please don't hurt me!\n";
                cout << "The Adventurer cowers down and drops the backpack\n";
                cout << "to your feet.\n\n\n";
                cout << "You Gained A Backpack!\n";
                cout << "Charma -3\n";
                Get_Backpack = true;
                goto adv1;
            }else{
                cout << "Adventurer: Good One! talk to you later!\n";
                cout << "The adventurer walks away casually.\n\n\n";
                goto ignadv1;
            }

    if (Ans12 == "kill"){
        Charma = Charma - 5;
        cout << "You sprint towards the adventurer and kill him with\n";
        cout << "your bare hands as Stewie is peeing. You take the backpack\n";
        cout << "and continue on the trail.\n\n\n";
        cout << "You Gained A Backpack!\n";
        cout << "Charma -4\n";
        goto adv1;
    }
adv1:
    system ("pause");
    system ("cls");
    cout << "Hold up, hold up.";
    cout << "Do you know how to use the backpack?";
    cin >> Ans13;
    if (Ans13 == "no"){
        cout << "At any time, type 'backpack' with no quotes around it\n";
        cout << "and your backpack will open for you to see/equip\n";
        cout << "items that you have collected!\n";
    }else{
    }
    goto Chap1Next1;
ignadv1:

    system ("pause");
    system ("cls");
    cout << "As you continue your journey you notice a backpack hanging from a branch\n";
    cout << "and you decide to take it good thing you didn't do anything to that\n";
    cout << "adventurer back there!\n\n\n";
    cout << "You Gained A Backpack!\n";
    cout << "Charma +1\n";
    Get_Backpack = true;
    Charma = Charma + 1;
    goto adv1;
Chap1Next1:
    cout << "You and Stewie arrive at a huge steel gate with several guards\n";
    cout << "all of which were armed with bows and arrows.\n";
    cout << "One guard draws his sword and walks towards you and\n";
    cout << "Stewie.\n";
    cout << "Guard: Who are you, why are you here?\n\n\n";      
    cout << "Do you...";
    cout << "Say Your Name?";
    cin >> Ans14;
        if (Ans14 == "yes"){
            cout << name << ": I am " << name << " and this is Stewart.\n";
            cout << "We are adventurers who are looking to find our way.\n\n";
            cout << "Guard: Very well then, you may go into the city of\n";
            cout << "Aesthoth.\n\n\n";
            goto EnterAesthoth;
        }
    cout << "(Threaten) ask for his name first";
    cin >> Ans15;
    if (Ans15 == "yes"){
        cout << "Guard: Hahahaha... you can't threaten me,\n";
        cout << "Why don't you try again?\n";
        system ("pause");
        system ("cls");
        goto Chap1Next1;
    }
    cout << "Kill";
    cin >> Ans16;
    if (Ans16 == "yes"){
        cout << "You attempt to kill the well armored guard with\n";
        cout << "Your bare hands... you can imagine what went\n";
        cout << "through your head last... a sword.\n";
        system ("pause");
        system ("cls");
        goto ChapterOne;
    }
EnterAesthoth:
    system ("pause");
    system ("cls");


system ("pause");
return 0;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ I see a couple of errors that can be caught by the compiler. Increase you warning level of your compiler and fix all the warnings. If you are using G++ -Wall -Wextra -Werror if you are using dev studio it is on one of the preferences. \$\endgroup\$ – Martin York Oct 8 '15 at 19:37
  • \$\begingroup\$ Where did you learn this style of coding? It looks very seventies \$\endgroup\$ – Alessandro Teruzzi Oct 9 '15 at 13:14
  • 2
    \$\begingroup\$ @AlessandroTeruzzi Text adventure games are very seventies, too :P \$\endgroup\$ – Golden Dragon Oct 9 '15 at 14:26
  • 1
    \$\begingroup\$ Why is nobody commenting on the use of goto? This might be the most approriate use of goto I have ever seen, but I still would avoid using it since it leads to a single huge function. c-faq.com/style/stylewars.html \$\endgroup\$ – dberm22 Oct 9 '15 at 14:53
  • \$\begingroup\$ @dberm22 Nobody? \$\endgroup\$ – Barry Oct 9 '15 at 15:09
29
\$\begingroup\$

There's a lot to comment on here, so I'll try to cover everything while being brief.

Encapsulation

int Charma = 0;
unsigned int Hunger = 10;
unsigned int Energy = 50;
unsigned int Health = 100;

Presumably, these are all attributes of a player. That suggests that you want to stick them all in a type:

struct Player {
    int Charma = 0;
    unsigned int Hunger = 10;
    unsigned int Energy = 50;
    unsigned int Health = 100;
};

and have an instance of Player, instead of just referencing variables. Reading further, there are other attributes that correspond to the player's character that should also get added.

That's a LOT of variables

At some point while declaring all your string Ans*, you should pause to realize that this is excessive. You only ever need one of these at a time, and you only ever need them for a local instance. That is, all of these variables are unnecessary. You need to separate your one giant function into small pieces.

Since a lot of your questions are yes/no, that strongly suggests a:

bool prompt(std::string const& message) {
    std::string answer;
    std::cout << message;
    std::cin >> answer;
    if (answer == "yes") {
        return true;
    }
    else if (answer == "no") {
        return false;
    }
    else {
        throw std::runtime_error("fail"); // or keep looping until
                                          // the user enters something valid
                                          // but definitely do SOMETHING
    }
}

Hence:

bool get_backpack = prompt("Get the backpack?\n");

And we no longer have name pollution with cryptic names. get_backpack is a lot easier to understand than Ans11.

Goto

At a first approximation, never use goto. It makes it more or less impossible to follow code. Without goto, you also don't need labels. Instead, just call different functions. Or keep an internal state machine. Or really any possible other solution. Code with goto like this is incredibly brittle - what if you want to add more states somewhere in between? Good luck keeping track of everything.

Use Enumerations

Right now, you have ten bools for race. But only one of those is ever going to be on, and that might prove difficult to ensure long-term. Prefer to instead use an enumeration:

enum Race {
    UNKNOWN,
    DEAD,
    HUMAN,
    ORC,
    GOBLIN,
    ELF,
    LIZARD,
    CAT,
    VAMPIRE,
    WEREWOLF,
    SNK
};

Then we can just have one variable of type Race, that will get set as appropriate - and will definitely only ever refer to one Race. This should also probably be a member variable of Player.

\$\endgroup\$
  • \$\begingroup\$ 'Data member initializer is not allowed' that error comes up under the = operator for the struct Player { int Charma = 0; unsigned int Hunger = 10; // At the = operator is the error unsigned int Energy = 50; unsigned int Health = 100; }; \$\endgroup\$ – Andrew Tew Oct 10 '15 at 1:34
  • \$\begingroup\$ That initialization syntax is a relatively recent addition to C++. So if you're using an older compiler, you will need to create a class constructor to set the initial values. \$\endgroup\$ – user673679 Oct 11 '15 at 10:35
15
\$\begingroup\$

Your code is all code.
So you are writting specific code for each situation.

A better style is called "Data Driven" coding.
This is where you use generic code that can be used for all situations. But what exactly happens depends on the data. This allows you to change the game simply changing the data.

Example:

 struct Location
 {
      std::string         name;
      std::string         description;
      std::vector<Item>   items;
      std::vector<Exits>  exits;
 };

 typedef std::vector<Location>   Dungeon;
 Dungeon   dungen = { {"Start",
                       "After hours of adventuring you and Stewie grow exhausted\n"
                       "in the distance you see an adventurer with a pretty desirable\n",
                       {{"Backpack"}, {"Sword"}},
                       {{"North", 2},
                        {"South", 3},
                        {"East and home", -1}}
                      },
                      {"With a band of of elves",
                       "You are with a band of elves singing happy songs around a campfire",
                       {{"Elronds Harp"}, {"Wand of Illusion"}}
                       {{"Tent", 4},
                        {"North", 15}}
                      },
                      .... // etc
\$\endgroup\$
8
\$\begingroup\$

There many things here that can be improved. First off, let's tackle some best practices. Generally, doing stuff like this with system isn't very good:

system("pause");
system("cls");

To start off, system("pause"); is a bad way of "pausing" for user input. First off, there's a decently sized overhead just to execute a shell command, and doing this is rather insecure. If you really need to pause on user input, and ignore it, then just do something like this:

std::cin.get();

Secondly, putting anything like this at the top of your file is a bad idea:

using namespace std;

This pollutes your local namespace with everything in std, and it can lead to some name conflicts, especially if you're using a library like boost. There's a good reason it's named std and not standard. It's easier to prefix everything with std:: rather than standard::.

\$\endgroup\$
  • \$\begingroup\$ I believe std::cin >> var works too. \$\endgroup\$ – Hosch250 Oct 8 '15 at 16:57
  • \$\begingroup\$ @Hosch250 It works, but it requires that you declare an unused variable, which can clutter code. \$\endgroup\$ – Ethan Bierlein Oct 8 '15 at 17:00
  • \$\begingroup\$ Ah. I usually use don't care - I never create 16 variables for answers anyway... \$\endgroup\$ – Hosch250 Oct 8 '15 at 17:04

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.