Little Text RPG project - Shop

Hello everyone! I've recently began learning c++, and as a little learning project I decided to make a simple text RPG. (I've read somewhere around that text RPGs are pure evil, and they're much harder than they seem. I know i'm gonna be frustrated at some point probably, but that's good. I just want to learn as much as I can while I'm on it.)

So. Basically, what I'm asking for here is a code review. Specifically of this part of the code, which is the "Village Shop". I seem to repeat the same lines a lot for each item, so I was wondering about a better way to do this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
if (village_decision==2){ // VILLAGE SHOP
                int shop_selection;
                cout<<"(You enter the shop. The shopkeeper warmly greets you)\n\n";
                cout<<"-Hello, traveler! Please, look through our fine selection of items.\n";
                do {//To keep the loop untill you exit the shop.
                    int item_amount;
                    int confirm_purchase; // For "Are you sure" question.
                    cout<<"(To buy an item, write the number of the item you wish to inquire about)\n\n";
                    cout<<"*******************************\n"; 
                    cout<<"*********** SHOP **************\n";
                    cout<<"*******************************\n";
                    cout<<"(1) Small Potion  --- 300 Gold\n";
                    cout<<"(2) Long Sword    --- 600 Gold\n";
                    cout<<"(3) Wooden Shield --- 600 Gold\n";
                    cout<<"(Press 4 to exit the shop)\n";
                    cout<<"*******************************\n";
                    cout<<"You have "<<char_gold<<" gold coins.\n\n";
                    cin>>shop_selection;
                    if (shop_selection==1){ 
                        //I basically repeat this "if" block 3 times...
                        cout<<"How many would you like to buy? (Press 0 to go back)\n\n";
                        cin>>item_amount;
                        cout<<"\n\n";
                        while ((item_amount * 300 > char_gold)&&(item_amount!=0)){
                            cout<<"You do not have enough money. Please pick a valid number, or 0 to go back\n\n";
                            cin>>item_amount;
                        }
                        if (item_amount!=0){
                            cout<<"This will cost " <<item_amount*300 <<" gold coins. Are you sure?\n";
                            cout<<"(Press 1 to confirm, 2 to go back)\n";
                            cin>>confirm_purchase;
                            cout<<"\n\n\n";
                            if (confirm_purchase==1){
                                cout<<"You have bought " <<item_amount <<" Small Potion(s) for "<<item_amount*300 <<" gold coins.\n";
                                char_gold = char_gold - (item_amount*300);
                                cout<<"You have " <<char_gold <<" Gold Coins remaining.\n\n";
                            }
                        }
                    }
                    if((shop_selection==2)&&(longsword==true)){
                        cout<<"You already own this item\n\n";
                    } else if (shop_selection==2){
                        if (char_gold>=600){
                            cout<<"This will cost 600 gold coins. Are you sure?\n";
                            cout<<"(Press 1 to confirm, 2 to go back)\n";
                            cin>>confirm_purchase;
                            cout<<"\n\n\n";
                            if (confirm_purchase==1){
                                cout<<"You have bought a Long Sword for 600 gold coins.\n";
                                cout<<"Attack increased by 3!\n";
                                char_att = char_att + 3;
                                char_gold = char_gold - 600;
                                longsword = true;
                                cout<<"You have " <<char_gold <<" Gold Coins remaining.\n";
                            }
                        }else{
                            cout<<"You do not have enough gold.\n\n";
                        }
                    }
                     if((wooden_shield==true)&&(shop_selection==3)){
                        cout<<"You already own this item\n\n";
                    } else if (shop_selection==3){
                        if (char_gold>=600){
                            cout<<"This will cost 600 gold coins. Are you sure?\n";
                            cout<<"(Press 1 to confirm, 2 to go back)\n";
                            cin>>confirm_purchase;
                            cout<<"\n\n\n";
                            if (confirm_purchase==1){
                                cout<<"You have bought a Wooden Shield for 600 gold coins.\n";
                                if (small_shield==true){ 
                                    //Something's horribly wrong here, right? If you have a weaker shield, 
                                    //it subtracts the def of the weaker shield before doing the addition.
                                    //It just seems a wrong way to do it. I'm not even using structs...
                                    cout<<"Defense increased by 2!\n";
                                    char_def = char_def +2;
                                }else if (small_shield==false){
                                    cout<<"Defense increased by 4!\n";
                                    char_def = char_def +4;
                                }
                                wooden_shield= true;
                                char_gold = char_gold - 600;
                                cout<<"You have " <<char_gold <<" Gold Coins remaining.\n";
                            }
                        }else{
                            cout<<"You do not have enough gold.\n\n";
                        }
                    }
                } while (shop_selection != 4);
            cout<<"Thanks for coming! Please stop by again!\n\n";
            cout<<"(Press enter to continue)\n";
            cin.ignore();
            cin.get();
            }


So. Any help, tips, or anything, really, would be VERY appreciated. Flame me for my horrible code too if you wish, I appreciate that as well. ;)

Especially about this segment of the code, but if anyone's got any piece of advice about Text RPGs in general, or even C++ in general, please do tell. I'm really eager to learn, and this community seems a good place to do so.

Thanks in advance for the help!
Last edited on
Sounds like you want functions:
http://cplusplus.com/doc/tutorial/functions/

Also, you should probably use a class or struct for your player. It'll help you pass the information to the functions more easily.
Thanks for your reply!

The problem with the functions, is that I don't see how I could apply them to this scenario. For example, small_potions use "item_amount", while longsword and wooden_shield don't. Also, small potions can be bought indefinitely, while the others can't, and that contributes to making a single function for them all being pretty hard. I really can't see how I can pull that off, which is why I was asking for help.

EDIT: Actually, I have an idea to make a function that works for both of the equipment items, but not for the consumables. Making them 2 different structs would really help. Your answer helped me realize it, Thanks.

Structures, yes. I need to implement that for my items, probably make 2, 1 for equipment and 1 for consumables. But before I do that, I want to think of a good way to make the structure work correctly with however I set the shop functions to work.

Something I had been thinking: How can I make it so that, for example, when I buy a shield, it automatically selects and applies the defense value of only the strongest one?
Last edited on
They're called parameters... use functions.
Thanks for your reply, packetpirate.

My problem was that I wasn't sure of how to implement the functions themselves to allow me to use them for both consumables and equips, and to make them actually work well just specifiying the parameters, but I have a couple of Ideas I'm gonna try out and hopefully make it work.

I know they're parameters, I've used functions before. In fact, here's a little battle function I made for the same game, if anyone has any tips to improve it, they'll be more than welcome!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
int battle(string monster_name, int monster_hp, int monster_att, int monster_def, int monster_exp, int monster_attrange, int monster_type, int monster_gold)
{
    srand (time(0));
    int action_selection;
    int charge_counter = 0;
    int turn_number = 0;
    cout<<"****BATTLE****\n\n";
    cout<<"A(n) " <<monster_name <<" has appeared! What will you do?\n\n";
    cout<<"(Press 1 to attack, 2 to defend)\n\n";
    int current_hp = char_hp;
    do
    {//BATTLE BEGIN
        turn_number = turn_number + 1;
        int char_damage = char_att-char_attrange+(rand()%(char_attrange*2));
        int monster_damage = monster_att-monster_attrange+(rand()%(monster_attrange*2));

        cin>>action_selection;
        cout<<"\n\n";
        //CHARACTER ACTION
            while((action_selection!=1)&&(action_selection!=2)){
            cout<<"Please enter a valid action.\n";
            cout<<"(Press 1 to attack, or 2 to defend)\n\n";
            cin>>action_selection;
            cout<<"\n\n";
            }
            if(action_selection==1){  //ACTION: ATTACK
                cout<<"You have hit the " <<monster_name <<" for " <<char_damage-monster_def <<" damage.\n";
                monster_hp = monster_hp - (char_damage-monster_def);
            }
            else if (action_selection==2){ //ACTION: DEFEND
                char_def=char_def*2;
            }
        //MONSTER ACTION
            //FOR NORMAL MONSTERS...
            if (monster_type==1){
                if (monster_damage>=char_def){
                    cout<<"The "<<monster_name <<" has hit you for " <<monster_damage-char_def <<" damage.\n";
                    current_hp = current_hp-(monster_damage-char_def);
                }
                else{
                    cout<<"The "<<monster_name <<" has hit you for 0 damage.\n";
                }
            }
            //"CHARGER" MONSTERS
            if (monster_type==2){
                if ((charge_counter==1)||(rand()%2)==0){
                    if (charge_counter == 0){
                        cout<<"The "<<monster_name <<" is charging a powerful attack!\n";
                        charge_counter = 1;
                    }
                    else if (charge_counter == 1){
                        cout<<"The "<<monster_name <<" has released the attack and hit you for " <<(monster_damage*2)-char_def <<" damage.\n";
                        current_hp = current_hp - ((monster_damage*2)-char_def);
                        charge_counter = 0;
                    }
                }
                else {
                    cout<<"The "<<monster_name <<" has hit you for " <<monster_damage-char_def <<" damage.\n";
                    current_hp = current_hp - (monster_damage-char_def);
                }
            }
            cout<<"You now have " <<current_hp <<" HP remaining.\n\n";
            if (gameover(current_hp)==1){
                return 0;
            }
            if (monster_hp > 0){
                cin.ignore();
                cout<<"What will you do next? (1 to attack, 2 to defend)\n\n";
            }
            if (action_selection ==2){
                char_def= char_def/2;
            }
    }while ((monster_hp > 0));
    //BATTLE END.
    cout<<"****BATTLE FINISHED****\n\n\n";
    cout<<"You have defeated the " <<monster_name <<", gained " <<monster_exp <<" exp points and gotten " <<monster_gold <<" gold!\n\n";
    char_exp = char_exp + monster_exp;
    char_gold = char_gold + monster_gold;
    cout<<"You now have " <<char_exp <<" exp points and " <<char_gold <<" gold coins.\n\n";
    if (char_exp <= max_exp){
        cout<<"You need " <<max_exp-char_exp <<" more exp points to level up.\n\n";
    }
    cout<<"Press enter to continue\n\n";
    cin.ignore();
    cin.get();
    if (level_up(1)!=0){
        cout<<"Error. Please check level up algorithm.";
    }
    return 1;
}
That function isn't returning anything specific, and in fact, shouldn't return anything at all. Remove the return statement and change the function type to "void".
One thing i would change about your battle function... My teachers always taught me that functions should do one task and do it as effeicently as possible. i noticed this function handles battles for all monsters and senarios i would break it down so that you have a battle function that calls a function if its a normal monster or if its a special monster. that way you dont have to run through all the extra if statements everytime you run the function. This is just me being picky though. great work so far! good luck with your game!
closed account (zb0S216C)
Your code should have classes[1]. Game structures without classes will look a mess, and will be hard to maintain. Incorporate classes, and you'll find you code easier to manage. Right now, just reading your code confuses me.

References:
[1]http://www.cplusplus.com/doc/tutorial/classes/

Wazzak
Topic archived. No new replies allowed.