Thread: A Tale of Two Classes: The Conundrum of Choosing More Modularity or Fewer Definitions

  1. #1
    Registered User
    Join Date
    Jul 2012
    Posts
    36

    A Tale of Two Classes: The Conundrum of Choosing More Modularity or Fewer Definitions

    For once, when posting in this forum, I have a problem that I actually know how to code around, in fact I might be able to think of two ways to code around it, I'm just not sure which one would be better in the long run and if there's an easier way to do what I'm thinking about.

    Some background is in order, I've been trying to learn C++ by writing a text adventure. I've recently finished up the "tutorial level" part of the text adventure that all players go through in my main function and now my plan is to write a series of interlinked functions for each of the separate rooms encased within a while loop until the game ends when the player selects an option in one of the functions that shifts the variable "int chapter_over" from zero to one. The start of what I'm building is below:

    Code:
      player_choices.chapter_over = 0;
        location_reference = 2;
        int& chapter_over_reference = player_choices.chapter_over;
        while (player_choices.chapter_over != 1)
        {
            if (location_reference = 2)
            {
                game_rooms.training_room(game_rooms.hard_knock_conversation_choice_one, game_rooms.examine_locker, game_rooms.spiked_horse_shoes, game_rooms.first_visit, game_rooms.group_conversation_choice_one, game_rooms.group_conversation_choice_two, player_name_reference);
            }
        }
    All well and good so far, though I'm certain I'll have kinks to iron out once I start asking the program to swap between rooms using the reference variable, but that's all just background, I'll get to the point.

    I created a class to house all of the room functions like so:
    Code:
    class rooms
    {
        public:
        rooms();
        ~rooms();
        int examine_locker, spiked_horse_shoes;
        int mushroom;
        int letter_opener;
        int sharp_letter_opener;
        int first_visit;
        int group_conversation_choice;
        void clinic (int wind_conversation_choice_two);
        void training_room (int& player_race_reference, int hard_knock_conversation_choice_one, int examine_locker, int spiked_horse_shoes, int first_visit, int group_conversation_choice_one, int group_conversation_choice_two, int* player_name_reference);
        void lab (int mushroom, int ura_conversation_choice_one, int spiked_horse_shoes, int letter_opener, int sharp_letter_opener);
        void bed_room (int blueblood_conversation_choice, int letter_opener, int sharp_letter_opener);
    };
    
    //destructor, constructor and contained functions not shown.
    Earlier, I had created a separate class to house all of the functions associated with the various characters in the rooms who the players can ask questions and have conversations with like so:

    Code:
    class characters
    {
        public:
        characters();
        ~characters();
        int wind_choice_one;
        int wind_conversation_choice_one;
        int wind_conversation_choice_two;
        int wind_opinion;
        int ura_conversation_choice_one;
        int ura_conversation_choice_two;
        int ura_opinion;
        int blueblood_conversation_choice_one;
        int blueblood_conversation_choice_two;
        int blueblood_opinion;
        int hard_knock_conversation_choice_one;
        int hard_knock_conversation_choice_two;
        int hard_knock_opinion;
        int wind_actions (int wind_opinion); // okay, so the idea here is that as Wind's oppinion increases, new dialogue options are opened up.
        void wind_conversation_one (int wind_conversation_choice_one);
    };
    
    //destructor, constructor and contained functions not shown.
    Now the problem I've run into is that it's very clear that the way I've got it set up now, all of the variables from the character functions (and now that I really think of it, all of the character functions themselves, because players would be asking the characters questions while they were in the room with them) would have to also appear in the room class.

    Now, the separate classes provide an easy more modular way of organizing the functions in my code, but it seems like I'm either going to have to define a metric ton of references in main and then write them into the classes (which now that I'm really thinking about it, probably wouldn't work, because the last time I tried to define a reference in a class my compiler screamed bloody murder at me), but the only other way I can think to solve the problem is to merge the two classes into one super class, which would make my program much harder to edit later on.

    I get the sense that a post like this would make many an experienced programmer ram their faces into their desks out of frustration at my stupidity, but I just can't figure out how to do this without making a mega class or tying the two classes together somehow in a really long series of definitions with pointers or references.

    So I humbly ask the wise programmers of these forums what they think I should do. Is there a way around making such a mad amalgamation that I just don't know about yet?

    I would be very grateful for any advice.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    So you are implementing a game of clue? I have a few questions. Why did you choose to implement the rooms as functions? What are different about the rooms in a way that impacts the implementation of the game? Why did you choose to implement the different characters as functions? What are different about the characters in a way that impacts the implementation of the game? What you think really is more important than what I think right now, but I really don't think there is a need for so much detail, unless you can communicate what all this stuff is doing. So what is all of this going to do?

    While you're at it, look for places where you repeat yourself. If you repeat yourself, it is a strong hint you are implementing something tediously.
    Last edited by whiteflags; 08-01-2012 at 08:30 PM.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Hmm... I think the problem is that the classes that you have now are effectively just namespaces, and logically, everything you have now belongs in a single namespace (possibly subdivided into nested namespaces). Hence, despite defining classes, you are actually working with separate functions that use "global" variables.

    I suggest defining a Room class that models a single room. Think of how the various rooms are similiar, then make it such that you can create a Room object with values for a clinic, a training room, a lab, a bedroom, etc. Likewise, define a Character class that models a single character.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Jul 2012
    Posts
    36
    Quote Originally Posted by whiteflags View Post
    So you are implementing a game of clue? I have a few questions. Why did you choose to implement the rooms as functions? What are different about the rooms in a way that impacts the implementation of the game? Why did you choose to implement the different characters as functions? What are different about the characters in a way that impacts the implementation of the game? What you think really is more important than what I think right now, but I really don't think there is a need for so much detail, unless you can communicate what all this stuff is doing. So what is all of this going to do?

    While you're at it, look for places where you repeat yourself. If you repeat yourself, it is a strong hint you are implementing something tediously.

    Okay, so basically the idea of this game is that it's a puzzle item adventure game where the goal is to find specific items in certain rooms and bring them to the room where it's needed. So for example, in the game one of the characters is a chemist who will accidentally produce an effervescing mixture that produces a noxious gas that could kill the other characters and the player trapped below. Fortunately, she has access to a cobbled together, old fashioned fume hood, which she can run by pumping a bellows so the gas is constantly pushed out a vent. She can stop the effervescing mixture if the player will open a container with another reagent in it for her (she can't move because she has to keep moving the bellows), but the container is stuck shut and the player needs to find something sharp to prize it open.

    Now, here's where the planned interesting part comes in. All of the characters have reasons to distrust the player, so depending on different dialogue choices, different characters will trust him more and thus be more willing to help him. If the player has palled around with the guard, the guard will have a high opinion stat and might give the character a sharp weapon to prize open the container that he otherwise wouldn't have trusted the player with. The medic might go and get a weapon from the locker herself to help the chemist if the player has palled around with her, but might not be so inclined to if she thinks the player is just trying to raid the clinic for drugs while her back is turned. If the player has convinced the chemist that he's trustworthy and smart enough to operate the bellows the proper way, then she can let him take over while she finds a way to open the container. Finally, as a default option, if the player has been a total jerk to everyone, there's a character who genuinely wants to trust him, but all he can offer is a dull letter opener that the player will then have to find some way to sharpen.

    In short, it's an inventory puzzler where you have to figure out not only what you have to do, but also who is willing to help you. The player's conversations with the characters will greatly influence their opinion and thus whether he gets a certain item or not and thus has a certain way of solving the puzzle.

    The problem with this from a coding standpoint is it means a player has to go from one defined area to another, have a likely complex case switch or if-statement defined conversation with another character that modifies a variable for that character's opinion stat to convince them, pick up an item (which must be defined as a variable in both rooms), and then go back to the first room to use it.

    The way it comes out is that any time I want to have something interesting happen (say the medic comes into one of the rooms to have a conversation with the guard about why he won't open the door for the player that she has a higher opinion of), I have to have things like both the medics opinion and the guard's opinion defined as variables in the room as well as different (or possibly recycled though that can be a somewhat tricky process) variables representing the player's various conversation choices and actions during said conversation, which may change depending on what items he's carrying (for example,if the player picked up the letter opener earlier out of desperation, the guard might tell the medic "He's already got a letter opener to pry the box open if he's telling the truth, why would he need a sword too if he wasn't trying to slit our throats?"

    You see how this simple little text adventure can quickly be overwhelmed by a flurry of variables. I think it will be a really good game if I can get it to work, but the way I'm writing it now, it seems like I'll need to have 12 different variables for each function that runs every time the player steps into a new room, and I was trying to figure out if there was a way to define them somewhere once so I didn't have to redefine them constantly in every function by reference.


    Well, that was a mouthful... Not sure if that's what you were looking for, but I hope it helps.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by chaucer345
    The problem with this from a coding standpoint is it means a player has to go from one defined area to another, have a likely complex case switch or if-statement defined conversation with another character that modifies a variable for that character's opinion stat to convince them, pick up an item (which must be defined as a variable in both rooms), and then go back to the first room to use it.
    So, if you have a Room class that models a single room, two possibilities come to mind:
    a) Keep a master list of Room objects, then each Room will have a list (e.g., a vector) of pointers to the next Room.
    b) Map room ids to Room objects, then define some kind of state machine to determine the set of allowable Room objects that the player can "go" to when in a particular room (as designated by room id).

    Each room could have a store of Item objects, defined as say, a vector. The player could have an inventory of Item objects. This way, you won't be defining individually named variables for each item that could be in a given room.

    Quote Originally Posted by chaucer345
    The way it comes out is that any time I want to have something interesting happen (say the medic comes into one of the rooms to have a conversation with the guard about why he won't open the door for the player that she has a higher opinion of), I have to have things like both the medics opinion and the guard's opinion defined as variables in the room as well as different (or possibly recycled though that can be a somewhat tricky process) variables representing the player's various conversation choices and actions during said conversation, which may change depending on what items he's carrying (for example,if the player picked up the letter opener earlier out of desperation, the guard might tell the medic "He's already got a letter opener to pry the box open if he's telling the truth, why would he need a sword too if he wasn't trying to slit our throats?"
    It may be possible to model events that are attached to a room, and triggered based on certain factors.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Jul 2012
    Posts
    36
    Hmm... from what you're saying it seems like I should be looking at this tutorial: Linked Lists in C++ Tutorial - Cprogramming.com

    I guess I've got more reading to do on the fundamental things it's possible to do in C++. Thank you for your help! I'll see if I can't get it to work something like that.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by chaucer345
    Hmm... from what you're saying it seems like I should be looking at this tutorial: Linked Lists in C++ Tutorial - Cprogramming.com
    Err... yes and no. Yes in that being familiar with pointers such that you can implement a linked list is useful in general and possibly useful for this project; no in that if you actually need a linked list, you should use std::list (or some other linked list library).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    You may have started a new title trend. Some possibilities:

    Class Expectations

    Much Ado About Classes

    Class and Punishment

    Moby Class (Classy Dick?)
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  9. #9
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Much Ado About Classes
    Would have liked "Much Ado About NULL" more...

    Soma

  10. #10
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Good point. Trying again.

    Much Ado about NULL

    Twelfth Node

    The Comedy of Warnings

    A Midsummer Night's Debugging

    Great Exceptions

    David Bitfield

    Through the Looking Class

    The Scarlet Unicode Code Point

    The Importance of Being Aligned

    The Strange Class of Dr Reference and Mr Pointer

    Pilgrim's Progress Bar

    To Kill A Process

    The Catcher in the Main

    Of Mice and Users

    Brave New Object

    The Old Man and the C
    Last edited by oogabooga; 08-01-2012 at 11:27 PM.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  11. #11
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    While you're trying to understand laserlight's advice I do have some other advice.

    This game seems to be based on dialogue, so make a flow chart for the dialogue. Like you said, every decision affects each character's opinion stat. Weigh all the choices with points instead of keeping track of what choices the player made with an if-else. You should end up with a decision that affects everyone's opinion at once. The reason you want to use the flowchart is so that you can plan routes through it; as long as all the possible sums up to a certain spot are different, you will know everything, from what items the player deserves to the ending.

    And if you ever make a dating sim, you can do the same thing.

    Now that I've eliminated a whole mess of if-else trees, I think all you have to do is figure out how to design rooms.
    Last edited by whiteflags; 08-02-2012 at 12:04 AM. Reason: grammar girl

  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    The Strange Class of Dr Reference and Mr Pointer
    ^_^

    Soma

  13. #13
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    And if you ever make a dating sim, you can do the same thing.
    Now I want to play your "dating sim".

    Also, watch "Red Versus Blue" for some reason...

    *shrug*

    Soma

  14. #14
    Registered User
    Join Date
    Jul 2012
    Posts
    36
    Quote Originally Posted by laserlight View Post
    Err... yes and no. Yes in that being familiar with pointers such that you can implement a linked list is useful in general and possibly useful for this project; no in that if you actually need a linked list, you should use std::list (or some other linked list library).
    Oh, then what did you mean by a vector when you were talking about keeping a master list before?

  15. #15
    Registered User
    Join Date
    Jul 2012
    Posts
    36
    Quote Originally Posted by whiteflags View Post
    While you're trying to understand laserlight's advice I do have some other advice.

    This game seems to be based on dialogue, so make a flow chart for the dialogue. Like you said, every decision affects each character's opinion stat. Weigh all the choices with points instead of keeping track of what choices the player made with an if-else. You should end up with a decision that affects everyone's opinion at once. The reason you want to use the flowchart is so that you can plan routes through it; as long as all the possible sums up to a certain spot are different, you will know everything, from what items the player deserves to the ending.

    And if you ever make a dating sim, you can do the same thing.

    Now that I've eliminated a whole mess of if-else trees, I think all you have to do is figure out how to design rooms.
    I'd already implemented part of what you're saying into my code. In the tutorial it's possible to make two decisions that affect the medic's opinion of you, which is expressed in code as an opinion stat. The tutorial ends with the following statement:


    Code:
    cout << "End Tutorial. Wind's oppinion of you is: ";
                if (wind_opinion_reference == 0)
                {
                    cout << "FAVORABLE";
                }
                if (wind_opinion_reference == 1)
                {
                    cout << "SLIGHTLY FAVORABLE";
                }
                if (wind_opinion_reference == 2)
                {
                    cout << "NEUTRAL";
                }
    I had not thought of trying to track that by using a flow chart though. That definitely seems like a clever strategy. Thank you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 23
    Last Post: 03-07-2011, 05:28 PM
  2. Sending fewer parameters then arguments
    By gar35 in forum C++ Programming
    Replies: 1
    Last Post: 05-01-2010, 09:20 PM
  3. Best journalism...saddest tale.
    By Sebastiani in forum General Discussions
    Replies: 4
    Last Post: 06-18-2009, 05:55 AM
  4. A tale of two systems.
    By sean in forum Linux Programming
    Replies: 8
    Last Post: 05-25-2002, 12:12 AM
  5. classes and definitions
    By scott27349 in forum C++ Programming
    Replies: 6
    Last Post: 05-15-2002, 10:11 PM