Using an abstract class type as a parameter...? and some more...

I'm screwing around with this little game program. I have a Player class and an abstract Enemy class. I need to be able to access the Enemies atk and hp whether the enemy is a Beast or some other derived class. Quite frankly I have no idea how to do this (see the code below).

On a side note...I am quite new to building full comprehensive programs...Does anyone have any recommendations to changing the layout of my header/cpp files? Or perhaps the use of a namespace? etc...

Furthermore, how can I give default values to Enemy::a and Enemy::h in deriving classes?
ex) I always want to have 'a' set to 1 and 'h' set to 5 for every Beast.

entities.h

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
#include "std_lib_facilities.h"
#include "numbers_manager.h"

	class Character
	{
	public:
		void set_hp(int x) { h = x; };
		int hp() { return h; }
		void set_atk(int x) { a = x; };
		int atk() { return a; }

		void attack(Character c) { c.set_hp(c.hp() - calculate_dmg()); }

		Character& operator=(const Character&) = delete;

		virtual ~Character() {};
	protected:
		Character(int h, int a)
			:h{ h }, a{ a } {};
	private:
		int calculate_dmg();
		int h;
		int a;
	};

	class Player : public Character
	{
	public:
		Player(string n) : Character(20, 5) { nm = n; };
		void encounter_enemy(Enemy e); // <--------------- Problematic

		string name() { return nm; };

	private:
		string nm;
	};

	class Enemy : public Character
	{
	public:
		virtual void appear() = 0;
		virtual void defeated() = 0;

		Enemy(const Enemy&) = delete;

		virtual ~Enemy() {};
	protected:
		using Character::Character;
	private:
	};
	class Beast : public Enemy
	{
	public:
		Beast() : Enemy(5, 1) {};
		void appear() override { cout << "A beast has appeared!\n"; }
		void defeated() override { cout << "The beast has been defeated!\n"; }
	};

	Player create_player();
	int calculate_dmg();


entities.cpp

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
#include "entities.h"

Player create_player()
{
	cout << "Enter your name: ";
	string name;
	cin >> name;

	Player p{ name };
	return p;
}
void Player::encounter_enemy(Enemy e) // <----------- Problematic
{
	while (true) {
		//TODO
	}
}
bool is_crit()
{
	int c = randint(1, 100);
	//5% crit chance
	return c <= 5;
}
int Character::calculate_dmg()
{
	int low_hit = atk() - (round(atk()*dmg_mod));
	int high_hit = atk() + (round(atk()*dmg_mod));

	double damage{ 0 };
	damage = randint(low_hit, high_hit);

	if (is_crit()) damage *= crit_mod;

	return int(damage);
}
Last edited on
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
94
95
96
97
98
99
100
#include <iostream>
#include <string>
// using namespace std ;

class Enemy ; // *** declare Enemy

class Player
{
    public:
        Player( std::string n )
            :nm{ n }, h{ 20 }, a{ 1 } {};

        std::string name() const { return nm; }; // *** const
        void set_hp(int x) { h = x; };
        int hp() const { return h; } // *** const
        void set_atk(int x) { a = x; };
        int atk() const { return a; } // *** const

        void attack_enemy( Enemy& e ); // *** pass reference

    private:
        std::string nm;
        int h;
        int a;
};

class Enemy
{
    public:
        void set_hp(int x) { h = x; }
        int hp() { return h; }

        void attack_player(Player p);
        virtual void appear() = 0;
        virtual void defeated() = 0;

        Enemy(const Enemy&) = delete;
        Enemy& operator=(const Enemy&) = delete;

        virtual ~Enemy() {};

    protected:
        Enemy(int h, int a)
            :h{ h }, a{ a } {};

    private:
        int h;
        int a;
};

class Beast : public Enemy
{
    public:

    // *** Enemy::Enemy is protected; therefore, the inheriting constructoris also protected
    // *** Either make Enemy::Enemy public in the base class
    // using Enemy::Enemy; // <-- Problematic code 2

    // *** Or write a public constructor
    Beast( int h, int a ) : Enemy{h,a} {}

    void appear() override { std::cout << "A beast has appeared!\n"; }
    void defeated() override { std::cout << "The beast has been defeated!\n"; }
};

Player create_player();

Player create_player()
{
    std::cout << "Enter your name: ";
    std::string name;
    std::cin >> name;

    // Player p{ name };
    return Player{ name };
}
void Player::attack_enemy( Enemy& e ) // *** pass reference
{
    e.set_hp(e.hp() - atk());
}

void Enemy::attack_player(Player p) // pass reference ???
{
    p.set_hp( p.hp() - this->a ) ;
    //TODO
}

int main()
{
    Player player_one{ "player_one" } ;
    player_one.set_atk(25) ;

    Beast gargoyle{ 52, 12 } ;
    gargoyle.appear() ;

    std::cout << gargoyle.hp() << '\n' ;
    player_one.attack_enemy(gargoyle) ;
    std::cout << gargoyle.hp() << '\n' ;
    gargoyle.defeated() ;
}

http://coliru.stacked-crooked.com/a/46ad15cc611ade61
Topic archived. No new replies allowed.