#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    1

    Random Events Text Adventure Errors


    Hey guys,

    So I wrote a really simple text adventure program that will call different functions that just contain scenarios for the player to either say yes or no to (y or n), and I'm having a few difficulties.

    The main error I'm getting is in calling the event1 function in the main section of the program even though it is clearly defined in its own section.

    Do I have to initialize it within the main section before I call it?

    Here's my code, the error is in red:

    Code:
    #include <iostream>
    #include <string>
    #include <Windows.h>
    
    // Goal for program: A user inputs a number from 1 to 5, and random events
    // aka messages will appear as a user further progresses in this 
    // text based game
    
    // Super excited, even though this is probably going to be extremely simple looking
    // to the user, a bit lengthy on my side, but it still probably will just mimic
    // one of those Pick Your Adventure games
    
    // Theme: Fantasy-based text adventure
    
    // I'm also going to be utilizing functions instead of just including them in the main
    // and simply calling them for number that the user inputs from 1 to 5
    
    // I'm going to label each of these functions as "events" aka a series of events
    // that happen that pertain to individual situations with yes or no events
    
    using namespace std;
    
    void userInput(int scrollnumber);
    
    // This will contain an array of 10 elements and we'll use the second function to
    // find the largest element in the array
    
    int main ()
    {
    	int scrollnumber;
    
    	userInput(scrollnumber);
    
    	if (scrollnumber = 1)
    	{
    		event1();
    
    	}
    
    
    	system("PAUSE");
    	return 0;
    
    }
    
    
    void userInput(int scrollnumber)
    { cout << "Please enter which one of the five scrolls you wish to read to enter the game world: " << endl;
    	
    	cin >> scrollnumber;
    
    	return scrollnumber;
    	
    
    }
    
    
    event1(scrollnumber)
    {
    	string answer;
    
    	cout << "You sank to the ocean floor after your ship has wrecked during a terrible storm. You are slowly choking on water and are becoming unable to maintain composure. There is a treasure chest nearby, would you like to open it? (y or n)" << endl;
    	cin >> answer;
    
    	if (answer = "y")
    	{
    	cout << "You find water breathing potions inside the chest! You pop open the corks on each of them and drink. You swim to the top and become rescued by a nearby sailor." << endl;
    	}
    
    	if (answer = "n")
    	{
    	cout << "You die a slow agonizing death as you inhale water inside your lungs. Your body is found by a necromancer and you live once again as a member of his skeleton army." << endl;
    	}
    
    	else 
    	{
    		cout << "Not a valid answer, please try again!" << endl;
    		return event();
    	}
    
    	return 0;
    
    }
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    1. USE CODE TAGS! This is your 18th post! You should know better by now! Absolutely no excuse!

    This is what your listing would look like with code tags:
    Code:
    #include <iostream>
    #include <string>
    #include <Windows.h>
    
    // Goal for program: A user inputs a number from 1 to 5, and random events
    // aka messages will appear as a user further progresses in this 
    // text based game
    
    // Super excited, even though this is probably going to be extremely simple looking
    // to the user, a bit lengthy on my side, but it still probably will just mimic
    // one of those Pick Your Adventure games
    
    // Theme: Fantasy-based text adventure
    
    // I'm also going to be utilizing functions instead of just including them in the main
    // and simply calling them for number that the user inputs from 1 to 5
    
    // I'm going to label each of these functions as "events" aka a series of events
    // that happen that pertain to individual situations with yes or no events
    
    using namespace std;
    
    void userInput(int scrollnumber);
    
    // This will contain an array of 10 elements and we'll use the second function to
    // find the largest element in the array
    
    int main ()
    {
    	int scrollnumber;
    
    	userInput(scrollnumber);
    
    	if (scrollnumber = 1)
    	{
    		event1();
    
    	}
    
    
    	system("PAUSE");
    	return 0;
    
    }
    
    
    void userInput(int scrollnumber)
    { cout << "Please enter which one of the five scrolls you wish to read to enter the game world: " << endl;
    	
    	cin >> scrollnumber;
    
    	return scrollnumber;
    	
    
    }
    
    
    event1(scrollnumber)
    {
    	string answer;
    
    	cout << "You sank to the ocean floor after your ship has wrecked during a terrible storm. You are slowly choking on water and are becoming unable to maintain composure. There is a treasure chest nearby, would you like to open it? (y or n)" << endl;
    	cin >> answer;
    
    	if (answer = "y")
    	{
    	cout << "You find water breathing potions inside the chest! You pop open the corks on each of them and drink. You swim to the top and become rescued by a nearby sailor." << endl;
    	}
    
    	if (answer = "n")
    	{
    	cout << "You die a slow agonizing death as you inhale water inside your lungs. Your body is found by a necromancer and you live once again as a member of his skeleton army." << endl;
    	}
    
    	else 
    	{
    		cout << "Not a valid answer, please try again!" << endl;
    		return event();
    	}
    
    	return 0;
    
    }
    2. Just exactly what is this nonsense?
    event1(scrollnumber)
    Where is the datatype for scrollnumber? Where is the return type? Just where did you learn to code C++?

    3. Why is there no function prototype for event1 up above main()? Just how do you expect the compiler to know what event1 is unless you tell it?

    4. Why haven't you fixed the other errors yet?
    C:TEST>g++ -Wall haunt1.cpp
    haunt1.cpp: In function `int main()':
    haunt1.cpp:34: warning: suggest parentheses around assignment used as truth valu
    e
    haunt1.cpp:36: implicit declaration of function `int event1(...)'
    haunt1.cpp: In function `void userInput(int)':
    haunt1.cpp:52: `return' with a value, in function returning void
    haunt1.cpp: At top level:
    haunt1.cpp:58: `scrollnumber' was not declared in this scope
    haunt1.cpp:59: ANSI C++ forbids declaration `event1' with no type
    haunt1.cpp:59: warning: `event1' was previously implicitly declared to return `i
    nt'
    haunt1.cpp:59: syntax error before `{'
    haunt1.cpp:62: syntax error before `<'
    haunt1.cpp:63: syntax error before `>'

    C:TEST>
    Line 34: = is assignment. If you want to test for equality, you need to use ==
    Line 36: no function prototype, as already mentioned in #3.
    Line 52: userInput() is declared as void, so why are you returning a value?
    Line 58: the compiler has no idea what scrollnumber is, and apparently no idea what you mean there by event1(scrollnumber)
    Line 59: You cannot declare a function without a return type. Already pointed out to you in #2
    Line 59: when you called event1 without a prototype before, the compiler tried to guess what it was. Now your "redeclaration" of it conflicts with that guess.
    Lines 59-63: I think you made the compiler lose its way and become terminally confused.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    1
    Wow...

    Um, sorry, I'm new at this. I've been teaching myself through tutorials and a pdf book I have on my computer.

    I'll be sure to add the code button at the top next time, didn't mean it.

    Thanks for your suggestions, I'll check them out.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    1
    Yeah, after looking at my code, I think I'm not even understanding what I'm doing, though I'm trying to change the parts you mentioned before.

    I declared the event() function in the section before main, but I'm having trouble deciding whether or not to make it void, since I want

    The overall goal of the program is to make the user type in a scroll number from 1 to 5, and I want the program to reference functions below main that have a series of yes or no choices that will progress the story of the game.

    I guess its just that I'm very new to this. I'll keep reading the book I have and progressing through their tutorials until they get to the proper usage of referencing functions before I attempt this again since the tutorials I've done so far on YouTube didn't help apparently.
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    It takes time to learn, kind of like learning a language only your mouth doesn't hurt as much at the end of class and you don't bite your tongue very often. A lot of learning is by doing and then correcting your mistakes.

    Start with declaring the function as void and when you figure out whether it needs to return a value and what, then you can easily change it. But in the meantime place the prototype.

    Learn to read your error messages and warnings. Their wording may not seem to make much sense, but they are pointing you to where there's a problem and as you gain experience you will learn what mistakes can cause certain error messages. The number after the file name is the line number, so you know where to look. Try to always start correcting the first error, because sometimes some of the errors further down are caused by the earlier errors. For example, you might get a lot of errors complaining that a variable wasn't declared even though you clearly see the declaration, but it turns out that that declaration had failed because you forgot to end the previous line with a semicolon or something like that.

    Never ignore warnings. The compiler may generate an executable, but if there are warnings then it most likely has problems and will not do what you expect it to do. It is always best to treat a warning as if it were an error. Indeed, I say all the time that warnings are more important than error messages.

    Keep hacking away at it and you'll get there.
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    3
    Rep Power
    0
    Down to business:
    Code:
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int userInput(void);
    void event1(void);
    
    // This will contain an array of 10 elements and we'll use the second function to
    // find the largest element in the array
    
    int main (void)
    {
      int scrollnumber = userInput();
      if (scrollnumber == 1)
      {
        event1();
      }
      return 0;
    }
    
    
    int userInput(void)
    {
      int usrChoice;
      cout << "Please enter which one of the five scrolls you wish to read to enter the game world: " << endl;
      cin >> usrChoice;
      return usrChoice;
    }
    
    
    void event1(void)
    {
      char answer;
    
      do
      {
      cout << "You sank to the ocean floor after your ship has wrecked during a terrible storm.\nYou are slowly choking on water and are becoming unable to maintain composure.\nThere is a treasure chest nearby, would you like to open it? (y or n)" << endl;
      cin >> answer;
    
      switch(answer)
      {
        case 'y':
        case 'Y':
          cout << "You find water breathing potions inside the chest! You pop open the corks on each of them and drink. You swim to the top and become rescued by a nearby sailor." << endl;
          break;
        case 'n':
        case 'N':
          cout << "You die a slow agonizing death as you inhale water inside your lungs. Your body is found by a necromancer and you live once again as a member of his skeleton army." << endl;
          break;
        default:
          break;
      }while(!(answer == 'N' || answer == 'n' || answer == 'Y' || answer == 'y');
    }
    Now, without changing much of what actually happens, and keeping in mind that I'm somewhat rusty with C++, I believe that this will work significantly better for you.

    Also keep in mind that I didn't test this, and probably won't test it, because aside from the coding errors, I believe there are quite a few logical and procedural errors that I just don't want to deal with, aside from the fact that there's not a significant reason why anybody would actually use more than the main(void) function for something this small.

    As an aside, ANYTHING with SYSTEM() calls in it is a really, really bad idea until you know at least enough about your system to know WHY it's a bad idea, and I mean specifics, not just general reason.

    As far as ignoring warnings, yes, there ARE times when you ignore warnings, but if you don't know what bit packing is yet, or intentionally using one data type to represent another, then don't worry about it.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    1
    Hey, thanks for the encouragement, its been totally fun so far though on a huge side note.

    In high school, I had this very jaded teacher near the end of her retirement that really was strict in the worst way possible.

    I've always been a self learner for a couple things, most prominently guitar which I'm pretty proficient at so after tackling up to Calculus II (not that its a life achievement) during the course of my B.S., I feel ALOT more okay with working in programs than I ever did in high school.

    Step by step, I'll get it. Either way, I'll take your advice to heart, thanks a bunch!
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    3
    Rep Power
    0
    I just noticed I left out the closing paren on the last line there, the conditional statement on the do..while() loop.

    More accurately, maybe, the do..while( loop. :p
  16. #9
  17. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Originally Posted by ciphermagi
    I just noticed I left out the closing paren on the last line there, the conditional statement on the do..while() loop.

    More accurately, maybe, the do..while( loop. :p
    You also have mismatched braces. If you had been using proper indenting style, you would have seen it.

    Snippet of your code, roperly indented (also increased tab to 4 spaces to make it more obvious, as well as adding the missing closed parens you pointed out):
    Code:
    void event1(void)
    {
        char answer;
    
        do
        {
            cout << "You sank to the ocean floor after your ship has wrecked during a terrible storm.\nYou are slowly choking on water and are becoming unable to maintain composure.\nThere is a treasure chest nearby, would you like to open it? (y or n)" << endl;
            cin >> answer;
    
            switch(answer)
            {
            case 'y':
            case 'Y':
                cout << "You find water breathing potions inside the chest! You pop open the corks on each of them and drink. You swim to the top and become rescued by a nearby sailor." << endl;
                break;
            case 'n':
            case 'N':
                cout << "You die a slow agonizing death as you inhale water inside your lungs. Your body is found by a necromancer and you live once again as a member of his skeleton army." << endl;
                break;
            default:
                break;
                
        } while(!(answer == 'N' || answer == 'n' || answer == 'Y' || answer == 'y'));
    }
    Now you can see that the switch statement is missing its close brace.

    There should have been an error message about missing or mismatched braces or the end-of-file encountered before the end of the program.

    Also, HauntJemimah, many editors have a feature which matches up parentheses and braces. Read your editor's help file/documentation for how to use it. It can come in very handy, especially if you get into long loop bodies with multiple levels of indentation.
  18. #10
  19. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Originally Posted by ciphermagi
    ... aside from the fact that there's not a significant reason why anybody would actually use more than the main(void) function for something this small.
    I believe that Hauntjemimah described this as the starting point of a larger program and not the finished product. In writing a large program, you start small and grow it out, usually establishing in that small beginning the overall structure of the final program.

    In this case, he would want to have several functions handling different events which would be chosen within main.

    BTW, HauntJemimah, starting small and growing it bigger is a good strategy. Many try to write a large program in its entirety and then are overwhelmed by the mountains of compiler and logic errors to correct. Write a small program, such as the basic menuing system, and get it to work. Then add a feature and get that to work. If you have features that you haven't implemented yet, then substitute in a dummy function that will only report that it was called; that would satisfy and allow you to test the menuing system. Incremental growth will help keep you sane.

    Originally Posted by ciphermagi
    As an aside, ANYTHING with SYSTEM() calls in it is a really, really bad idea until you know at least enough about your system to know WHY it's a bad idea, and I mean specifics, not just general reason.
    I really find having to kludge your code in order to keep the window open to be aesthetically displeasing and would prefer that better solutions be used. For example, if the program is to be run from the command line, that is exactly where I run it (and compile it too). Another acceptable example would be to prompt the user to either run it again or exit, thus presenting the user with a logical choice.

    In this case, a menuing system in main() should be what HauntJemimah is working towards, as I understand. A simple one in which the options are displayed and the user chooses one to execute. One of those options would be to quit/exit.

    Originally Posted by ciphermagi
    As far as ignoring warnings, yes, there ARE times when you ignore warnings, but if you don't know what bit packing is yet, or intentionally using one data type to represent another, then don't worry about it.
    Yes, there are some warnings that would do no harm of left uncorrected, but knowing which those are requires knowledge and experience which beginners simply do not have. But that is still no excuse for ignoring warnings. At the very least, each warning needs to be investigated to at the very least determine whether the condition it warns of is benign.

    One benign warning would be "variable not used". You declared a variable and either you haven't added the code yet that uses it or else you deleted that code. But what if you had added code (eg, by copy and pasting and then editing) that is supposed to use that variable? You thought you had modified that copied code to use that variable but somehow you overlooked that. In this case, that "benign" warning would be alerting you to a very serious problem.

    You mention intentionally using one data type as another as triggering a "benign" warning. If you didn't do it right (eg, you use an int in place of a pointer), then you're in very serious trouble. And there are a great many cases where you would accidentally use one type as another, in which case you very much would want to investigate this warning. If you honestly and truly want to use one type as another, then cast it as such, which would remove that warning. Here's another rule: always be explicit.

    Never ignore warnings! At the very least, always investigate the warning -- ignoring a warning means you don't even investigate it. Then correct the condition, or not but only if you are absolutely postive that you don't need to. And you cannot be absolutely positive of that unless you really know what you are doing.

    HauntJemimah and all other beginners do not yet know what they are doing to the degree of certainty that would be required. They need these rules to guide them into following good practices until they do know enough, at which time they will no longer need the rules.

    PS

    The reason why I promote the "never ignore warnings!" rule is because so many beginners do ignore warnings. They think that just because the compiler generated an executable then it compiled correctly. So when that "correctly compiled" program crashes or produces unexpected results, they post here swearing up and down that it compiled correctly when in reality they have a dozen or more warnings. Warnings which point directly to the lines of code that are jacked up and with a warning message that tells them what's wrong with that code.

    By ignoring warnings, they falsely believed that their programs were correct. They were unaware of potential problems in their programs. And they were clueless as to where the bugs in their programs were.

    So why does the compiler throw warnings instead of error messages that keep an executable from being generated?
    Originally Posted by Doug Gwyn
    UNIX was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things.
    C is a professional programming tool. It was designed by professional programmers for professional programmers to do whatever they needed to do. Unlike so many modern programming languages, it was not loaded down by all kinds of safety features meant to protect the system and the programmer from the programmer. The prevailing philosophy in C is that the programmer knows what he is doing. So if you tell C to do something, it will do it because you, the programmer, know what you are doing. If you do something that is questionable, it will warn you, but since you know what you are doing it will do it anyway.

    Warnings are more important than errors messages, because:

    1. They alert you to possible problems.

    2. They point you to where those problems lie; ie, they give the line number in question.

    3. They tell you what's questionable about it.

    We may make typographical errors or logic errors which warnings can help trap out for us. Beginners especially will try mind-bogglingly weird stuff that warnings will point out, albeit not pointing out that it's weird, but rather the weirdness has succeeded in confusing the compiler. Thus warnings can be a valuable took in sanity-checking our code.

    It would make no sense to ignore such a valuable tool.
    Last edited by dwise1_aol; August 22nd, 2013 at 11:30 AM.
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    3
    Rep Power
    0
    Yessss.....I fiddled with it in the scratchpad buffer, and the scratchpad's idea of indenting is deleting any existing indenting. I missed that closing brace...because I was llaazzyy......

    Originally Posted by dwise1_aol
    I believe that Hauntjemimah described this as the starting point of a larger program and not the finished product. In writing a large program, you start small and grow it out, usually establishing in that small beginning the overall structure of the final program.

    In this case, he would want to have several functions handling different events which would be chosen within main.
    The menu, especially in something as small as a text-based game, should be handled in a do..while(1) loop inside the main function, and each action should be slaved out to a separate algorithm. What he's doing above is trying to implement the right idea, but splitting the hairs too fine; he's divided his single concept into more than one execution portion.

    Originally Posted by dwise1_aol
    BTW, HauntJemimah, starting small and growing it bigger is a good strategy. Many try to write a large program in its entirety and then are overwhelmed by the mountains of compiler and logic errors to correct. Write a small program, such as the basic menuing system, and get it to work. Then add a feature and get that to work. If you have features that you haven't implemented yet, then substitute in a dummy function that will only report that it was called; that would satisfy and allow you to test the menuing system. Incremental growth will help keep you sane.
    So true.......

    Don't forget, Hauntjemimah, (unless you haven't learned it yet) that you can totally take an entire section of your program, make a header file for it, and then put the functions into a completely different .cpp file. That'll clean up a lot of code for you, and it will make debugging easier, because even if a compiler doesn't know what line the error is on, the linker will tell you what file it's in.

    And don't split hairs about ignoring warnings, dwise1_aol. You and I both know that I meant that, while we observe the warnings are there, there's an appropriate time to take absolutely no action about it.

    What I was referring to, by the way, when I was talking about intentionally using one type to represent another, as an example:
    Code:
    struct short_24{
        int short_24:24;
    }short_24;
    Now you have a 3 byte short.
  22. #12
  23. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    1
    Good ideas,

    I totally agree that while its completely unnecessary to call different functions that implement different events, I just wanted to challenge myself to get over that fear of calling different functions.

    Like you said though, I could totally just do this in a do while loop.

    A menu system in main would make it cleaner huh? Good idea.

    I'll add it to my goals section near the top, because I even thought about adding health, magic, and fatigue later on too (got the idea the other night).

    Thanks a bunch for pointing out the warnings section, I recently have been catching dumb mistakes by STILL looking at the error section after it "successfully" builds, to find a warning that completely botched one of the tutorials I was working on.

IMN logo majestic logo threadwatch logo seochat tools logo