0

I have searched for nearly 4 days, several hours per day on gooogle, without result. I didn't want it to get to this point, but I really can't find anything. Now, I will describe my problem - Ask if you need clarification:

Problem: I have 3 HPP files that are circular depenent of EACHOTHER, and header guards don't help at all, except avoiding the "#include nested too deeply" problem. But now I get the following error: 'forest' was not declared in this scope

#ifndef MAINMENU_HPP
#define MAINMENU_HPP
#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>
using namespace std;

#ifndef MAINMENU_HPP
#include "Areas.hpp"
Areas areas;
#endif
#include "Player.hpp"

#include "SetColor.hpp"
void mainMenu();


void mainMenu()
{
    int action;
    //battle();
    initPlayer();
    if(player.xp >= player.xpRequired)
        {
            player.xp -= player.xpRequired;
            player.lvl += 1;
            SetColor(14);
            cout << endl << "_-*You have leveled up!*-_" << endl << endl;
            SetColor(7);
            player.xpRequired = 40 + player.lvl * 10 * player.lvl;
            levelUp();
        }
    player.damageModifier = 5 + player.strength/2;
    player.baseDamage = 5 + player.strength/2;

    cout << "=================================City of Town==================================" << endl;
    cout << "Made by Erik aka Einar aka NukeTester and Mr.WertyQaz" << endl;
    cout << "Enter [0] to quit" << endl;
    cout << "Enter [1] to view stats" << endl;
    cout << "Enter [2] to go to the forest" << endl;
    cout << "Enter [3] to save the game" << endl;
    cin >> action;

    switch (action)
        {
        case 0:
            //quit();
            break;
        case 1:
        player.xp = 400;
        cout << player.playerName << "'s Inventory " << endl;
        cout << "Health: ";
        SetColor(13);
        cout << player.health;
        SetColor(7);
        cout << "/";
        SetColor(13);
        cout << player.maxHealth << endl;
        SetColor(7);
        cout << "Gold: ";
        SetColor(14);
        cout << player.money;
        SetColor(7);
        cout << endl;
        cout << "Experience: ";
        SetColor(3);
        cout << player.xp;
        SetColor(7);
        cout << "/" ;
        SetColor(3);
        cout << player.xpRequired << endl;
        SetColor(7);
        cout << "Level: ";
        SetColor(2);
        cout << player.lvl << endl;
        SetColor(7);
        cout << "Strength: " << player.strength << endl;
        cout << "Dexterity: " << player.dexterity << endl;
        cout << "Vitality: " << player.vitality << endl;
        cout << "Speed: " << player.speed << endl;
        system("PAUSE");
        system("CLS");
        mainMenu();
        break;
        case 2:
        forest(); // THIS IS THE ERROR
        break;
        }
        }
#endif

//Areas.hpp (Where forest lays)
#ifndef MAINMENU_HPP
#include "MainMenu.hpp"
MainMenu menu;
#endif

#ifndef AREAS_HPP
#define AREAS_HPP

#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>

#include "SetColor.hpp"

using namespace std;


void battle();
void forest();


void battle()
{
    int action;
    system("CLS");
    srand (time(NULL));
  /* generate secret number between 1 and 10: */
    int monster;
    monster = rand() % 2 + 1;

    goblin.enemyID = monster;
    if(goblin.enemyID == 1)
{
    goblin.enemyName = "Goblin";
    goblin.dead = false;
    goblin.enemyID = 1;
    goblin.health = 33;
    goblin.baseDamage = 3;
    goblin.damageModifier = 5;

    srand (time(NULL));
    goblin.damage = rand() % goblin.damageModifier + goblin.baseDamage;

    srand (time(NULL));
    goblin.money = rand() % 5 + 10;
    cout << "====================================BATTLE======================================";
    cout << "Opponent: " << goblin.enemyName << endl;
    cout << "It's health is: " << goblin.health << endl;
    cout << "Do you want to battle it?" << endl;
    cout << "Enter [1] for yes" << endl << "Enter [2] for no" << endl;

    cin >> action;
        if(action == 1)
        {
            BattleGoblin:
                    if(player.health <=0)
        {
            player.dead = true;
        }
    if(player.dead){
            cout << "You have died! Game Over!" << endl;
            cout << "Press Enter to continue..." << endl;
            system("PAUSE");
            //quit();
    }
            cout << "Enter [3] for a quick heal" << endl;
            cin >> action;
            if(action == 3)
                {
                    player.health = player.maxHealth;
                    goto BattleGoblin;
                }
    if(action == 1)
        {
            //Player Damage

            player.damage = rand() % player.damageModifier + player.baseDamage;
            goblin.health -= player.damage;

            cout << "You deal ";
            SetColor(4);
            cout << player.damage;
            SetColor(7);
            cout << " damage to the evil Goblin!" << endl;
            cout << "Goblin health: " << goblin.health << endl;

            //Goblin Damage
            if(goblin.health >0)
                {
            srand (time(NULL));
            goblin.damage = rand() % goblin.damageModifier + goblin.baseDamage;

            cout << "Goblin strikes you, dealing " << goblin.damage << " damage!" << endl;
            player.health -= goblin.damage;
            cout << "Your health: ";
            SetColor(13);
            cout << player.health << endl;
            SetColor(7);
            system("PAUSE");
            system("CLS");
            }
            else if(goblin.health <=0)
        {
            SetColor(2);
            cout << "Goblin is now DEAD!" << endl;
            SetColor(7);
            system("PAUSE");
            system("CLS");
            goblin.dead = true;
        }
      if(goblin.dead)
        {
            cout << "You killed the greedy Goblin!" << endl;
            cout << "You have earned " << goblin.money << " Gold Coins!" << endl;
            cout << "You have also gained a total 5 experience from the Goblin!" << endl;
            player.money += goblin.money;
            player.xp += 5;
            system("PAUSE");
            menu.mainMenu();
        }
            goto BattleGoblin;
            }
        }
        if(action == 2)
        {
            srand(time(NULL));
            int fleeOpponent = rand () % 4 + 1;

        if(fleeOpponent >=2)
        {
            cout << "You flee the evil Goblin. " << endl;
            system("PAUSE");
            system("CLS");
            mainMenu();
        }
        else if (fleeOpponent == 1)
        {
            cout << "The evil Goblin catches you, before you get away, and deals 5 damage!" << endl;
            player.health -= goblin.damage;
            goto BattleGoblin;
        }

            cout << "You flee the evil Goblin. " << endl;
            system("PAUSE");
            system("CLS");
            mainMenu();
        }
        if(action > 2)
            {
                cout << "Undefined action. Press Enter.";
                cin.get();
                goto BattleGoblin;
            }
}


//=========================================================================================================================================================================================


    orc.enemyID = monster;
    if(orc.enemyID == 2)
    {
    orc.enemyName = "Orc";
    orc.dead = false;
    orc.enemyID = 1;
    orc.health = 140;
    orc.baseDamage = 7;
    orc.damageModifier = 8;

    srand(time(NULL));
    orc.damage = rand() % orc.damageModifier + orc.baseDamage;

    srand (time(NULL));
    orc.money = rand() % 7 + 3;
    cout << "====================================BATTLE======================================";
    cout << "Opponent: " << orc.enemyName << endl;
    cout << "It's health is: " << orc.health << endl;
    cout << "Do you want to battle it?" << endl;
    cout << "Enter [1] for yes" << endl << "Enter [2] for no" << endl;
    cin >> action;
    if(action == 1)
        {
            BattleOrc:
                    if(player.health <=0)
        {
            player.dead = true;
        }
    if(player.dead){
            cout << "You have died! Game Over!" << endl;
            cout << "Press Enter to continue..." << endl;
            cin.get();
            //quit();
    }
            cout << "Enter [1] for attack" << endl;
            cout << "Enter [3] for a quick heal" << endl;
            cin >> action;
            if(action == 3)
                {
                    player.health = player.maxHealth;
                    goto BattleOrc;
                }
    if(action == 1)
        {
            player.damage = rand() % player.damageModifier + player.baseDamage;
            orc.health -= player.damage;

            cout << "You deal ";
            SetColor(4);
            cout << player.damage;
            SetColor(7);
            cout << " damage to the evil Orc!" << endl;
            cout << "Orc health: " << orc.health << endl;

            srand(time(NULL));
            orc.damage = rand() % orc.damageModifier + orc.baseDamage;
            if(orc.health >0)
                {
            cout << "Orc strikes you, dealing " << orc.damage << " damage!" << endl;
            player.health -= orc.damage;
            cout << "Your health: " << player.health << endl;
            system("PAUSE");
            system("CLS");
                }
                else if(orc.health <=0)
        {
            SetColor(2);
            cout << "Orc is now dead!" << endl;
            SetColor(7);
            system("PAUSE");
            system("CLS");
            orc.dead = true;
        }
      if(orc.dead)
        {
            cout << "You killed the ferocius Orc!" << endl;
            cout << "You have earned " << orc.money << " Gold Coins!" << endl;
            cout << "You have also gained a total 21 experience from the Orc!" << endl;
            player.money += orc.money;
            player.xp += 21;
            system("PAUSE");
            mainMenu();
        }
            goto BattleOrc;
            }
        }
     if(action == 2)
        {
            srand(time(NULL));
            int fleeOpponent = rand () % 4 + 1;

        if(fleeOpponent >=2)
        {
            cout << "You flee the evil Orc. " << endl;
            system("PAUSE");
            system("CLS");
            mainMenu();
        }
        else if (fleeOpponent == 1)
        {
            cout << "The evil Orc catches you, before you get away, and deals 5 damage!" << endl;
            player.health -= orc.damage;
            goto BattleOrc;
        }

            cout << "You flee the evil Orc. " << endl;
            system("PAUSE");
            system("CLS");
            mainMenu();
        }
        if(action > 3)
            {
                cout << "Undefined action. Press Enter.";
                cin.get();
                goto BattleOrc;
            }
}
}



void forest()
{

    int action;
    system("CLS");
    cout << "===================================FOREST=======================================";
    cout << "Enter [0] to go back to town" << endl,
    cout << "Enter [1] to chop some wood" << endl;
    cout << "Enter [2] to go for a walk. Might be risky..." << endl;

    cin >> action;
    if(action == 0)
        {
//            mainMenu();
        }
    if(action == 1 && player.hasHatchet)
        {
            cout << "you cut some wood.";
            system("PAUSE");
            system("CLS");
//            mainMenu();
        }

        else if(action == 1)
            {
                cout << "You can't chop trees without a hatchet! Go buy one at the blacksmith!" << endl;
                system("PAUSE");
                system("CLS");
//                mainMenu();
            }
    if(action == 2)
        {
            srand (time(NULL));
            int forestBattle;
            forestBattle = rand() % 10 + 1;
            if(forestBattle >=1 && forestBattle <=5)
                {
                    cout << "You walk into the forest." << endl << "All you found was peace. You decide to head back to town." << endl << endl;
                    system("PAUSE");
                    system("CLS");
//                    mainMenu();
                }
                if(forestBattle >=5 && forestBattle <10)
                    {
                        cout << "Something is heading towards you!" << endl;
                        system("PAUSE");
                        system("CLS");
                        //battle();

                    }
            if(forestBattle == 10)
                {
                    cout << "You found some fresh apples laying on the ground. You eat the apples and gain +1 health." << endl << endl;
                player.health += 1;
                system("PAUSE");
                system("CLS");
//                mainMenu();
                }
        }
}

#endif

//main.cpp
#ifndef MAINMENU_HPP
#include "MainMenu.hpp"

#endif
//#endif // MAINMENU_HPP
#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include "Player.hpp"
#include "MainMenu.hpp"

using namespace std;

int action = 0;


int quit();
void matchMaking();
void battle();
void saveGame();
void setColor();

int quit()
{
    exit(1);
}

void matchMaking()
{

}


void saveGame()
{
    std::string saveName = "save";

    cout << "Enter savegame name: ";
    std::getline(std::cin, saveName);
    ofstream save(saveName.c_str());
    save << "Health: " << player.health << endl << "Damage: " << player.damage << endl << "Gold: "  << player.money << endl << endl;
}


int main()
{
//Initialize functions
    initPlayer();
    mainMenu();

//Initialize local variables
/*
v1 = rand() % 100;         // v1 in the range 0 to 99
v2 = rand() % 100 + 1;     // v2 in the range 1 to 100
v3 = rand() % 30 + 1985;   // v3 in the range 1985-2014
*/
}

//Strangest thing of all, because this is included in different files more than twice, but
//this works fine! I don't have any idea why.
#ifndef SETCOLOR_HPP
#define SETCOLOR_HPP

#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>

//#include "Player.hpp"

using namespace std;

void SetColor(int value);

void SetColor(int value)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),  value);
}
#endif

As you can see, I am desperate enough to post nearly my whole project, just to get help! And that means I am seriously pissed off at C++ right now. As you may see, I am a newbie programmer, but I thought it would be medium-hard for me to make a simple RPG game, with seperate HPP files, instead of all the code laying in main.cpp, as I did before.

Thanks in advance, I hope this isn't too much trouble, at least not for pro-programmers!

Maybe this helps clearifying: I used a site called PenguinProgrammer: http://www.penguinprogrammer.co.uk/rpg-tutorial-2/battles/

You can see that this guy has used "battle.hpp" and also done something like this:

#include "dialogue.hpp"
Dialogue dialogue;

And I don't understand how that seems to work for HIM and not for ME. I havn't tested his code, and I am not a good programmer, but in my world, this seems really weird! Any answer to that?

Einar
  • 1
  • 3

3 Answers3

2

What you're trying to do is create a circular reference, which is not allowed in C++.

Header guards should appear in every header file, not in your source files like:

#ifndef HEADER_NAME_MACRO
#define HEADER_NAME_MACRO

//Header contents...

#endif

To fix your circular reference issues, you need to revisit your design to eliminate the circular reference. Often you'll do this by having one or more of your headers only refer to things in other by pointer or reference and forward declaring the other class:

Header A:

#ifndef HEADER_A
#define HEADER_A
//Forward declaration, you've told the compiler you'll eventually define B.
class B;

class A {
public:
    B* b;
};

#endif

And Header B:

#ifndef HEADER_B
#define HEADER_B

#include <A.hpp>

class B {
public:
    A a;
};

The reason for this is that the C++ compiler needs to know the size of everything you define at the time it is defined. If you have a circular reference, the compiler doesn't know the size of the one you define second.

You're also going to have trouble at link-time with your non-member functions that are defined in your header files. To fix this, you either need to put them in source files or declare them inline to get around the one definition rule

You seem to misunderstand how people generally organize code in C++. Headers should include declarations and your source files should include definitions. See this c++-faq question about the difference

Community
  • 1
  • 1
Collin
  • 11,977
  • 2
  • 46
  • 60
  • Thank you for your detailed explanation! I will rewrite my code and see what happens! Thank you! – Einar Mar 22 '14 at 16:27
1

You need not to add inclusion guards in any .cpp file, you should only use inclusion guards in header files. I can see you have added inclusion guards at many places in your main.cpp file.

Inclusion guard should be added very first lines of your header files, and even that header files will be included many times, you will get its contents only once, because rest of portion will be deleted after prepossessing.

Pranit Kothari
  • 9,721
  • 10
  • 61
  • 137
  • Where should I add the header guards/How should I add the header guards? I've seen people who guard like this: #ifndef FOO_H #define FOO_H int x; int y; #endif and also something like this: #ifndef FOO_H #define FOO_H #include "Bar.h" #endif class Foo { //BLA BLAH BLAH }; – Einar Mar 22 '14 at 16:22
  • Starting of header `#ifndef HEADER_A #define HEADER_A` and end `#endif` of header. That's it. Just give proper names, if file name is CircleClass.h then `#ifndef CIRCLE_CLASS` – Pranit Kothari Mar 22 '14 at 16:48
  • Thanks for the clarification! I think I will have to re-write my game engine again, in order to get it working properly, with no bugs like the ones I've got. – Einar Mar 22 '14 at 17:50
  • @Einar Before deciding to do lot of hard work, understand problem correctly. May be problem is very small, and you end up doing lot of work. Sometime debugging problem takes more time than expected. – Pranit Kothari Mar 22 '14 at 17:53
  • Yeah, that's basically where I fail, in this state of programming, since I'm not experienced enough for broad thinking - before acting. What I did with this project was that I wrote functions instead of classes in my main.cpp file, which is really, REALLY bad programming practice. So then I tried to make classes instead of functions in main.cpp, and now I ended up here. Perhaps I have to rewrite all the code once again. – Einar Mar 22 '14 at 20:53
1

It cannot find forest() because you use an already defined include guard before Areas.hpp

#ifndef MAINMENU_HPP
#define MAINMENU_HPP

// ...

#ifndef MAINMENU_HPP
#include "Areas.hpp"
Areas areas;
#endif

// ...

To resolve circular dependencies, you usually use forward declarations in the header files, where needed.

In your case, it would be sufficient to move the function definitions into a .cpp file and leave just the declarations in the header file.

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198
  • Thank you for your help! I will see if I can do this, and then fix this hell of a problem! – Einar Mar 22 '14 at 16:28