How to have structs relative to an object?

Hello! I am making a Pokemon program in Visual Studio, and I was wondering if I could have specific attack structs for each Pokemon (Object). So for Pokemon A, it would have these 4 attacks, while Pokemon B would have four different attacks. How would I write that, and is there any way to simplify the code I already have?


Here is the code:

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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include"stdafx.h"
#include <iostream>
#include <string>

using namespace std;

class Pokemon
{
public:
	string name; 
	string type1;
	string type2;
	int HP;
	int Atk;
	int Def;
	int Speed;
};

struct attack
{
	string name;
	int power;
	int pp;
	int accuracy;
	string type;
} att1, att2, att3, att4; 



struct attack_ember : public attack
{
	attack_ember() // constructor
	{
		name = "Ember";
		power = 40;
		pp = 30;
		accuracy = 95;
		type = "Fire";
	}
} ember; 

struct attack_hydropump : public attack
{
	attack_hydropump()  // constructor
	{
		name = "HydroPump";
		power = 120;
		pp = 5;
		accuracy = 75;
		type = "water";
	}
} hydropump;

struct attack_tbolt : public attack
{
	attack_tbolt()
	{
		name = "Thunderbolt";
		power = 100;
		pp = 10;
		accuracy = 100; 
		type = "Electric";
	} 
} tbolt;

struct attack_electroball : public attack
{
	attack_electroball()
	{
		name = "Electro Ball";
		power = 150;
		pp = 10;
		accuracy = 100;
		type = "electric";
	}
} electroball;

struct attack_fireblast : public attack
{
	attack_fireblast()
	{
		name = "Fire Blast";
		power = 150;
		pp = 5;
		accuracy = 80;
		type = "Fire";
	}
}fireblast;

//Pokemon!
Pokemon Shedninja{ "Shedninja","Ghost","Grass",1,0,0,100 };
Pokemon Golem{ "Golem","Rock","Ground",126,102,200,78 };


void StatPg()
{
	cout << "#################################################################\n";
	cout << Shedninja.name << ": " << Shedninja.type1 << "/" << Shedninja.type2 << " type" <<  "\t" << Golem.name << ": " << Golem.type1 << "/" << Golem.type2 << " type" << endl;

	cout << "\t" << Shedninja.HP << " HP" << "\t \t \t \t" << Golem.HP << " HP" << endl;
	cout << "\t" << Shedninja.Atk << " ATK" << "\t \t \t \t" << Golem.Atk << " ATK" << endl;
	cout << "\t" << Shedninja.Def << " DEF" << "\t \t \t \t" << Golem.Def << " DEF" << endl;
	cout << "\t" << Shedninja.Speed << " Speed" << "\t \t \t" << Golem.Speed << " Speed" << endl;
	cout << endl;
	cout << att1.name << " | " << att1.pp << " PP" << endl;
	cout << att2.name << " | " << att2.pp << " PP" << endl;
	cout << att3.name << " | " << att3.pp << " PP" << endl;
	cout << att4.name << " | " << att4.pp << " PP" << endl;
	cout << "#################################################################\n";
}

int main()
{
	att1 = ember; 
	att2 = hydropump;
	att3 = tbolt;
	att4 = electroball;

	StatPg();

	att4 = fireblast;

	StatPg();

	
}
sure you can do it.
how you do it depends a bit.
you could have a class "attack" and have a vector (of 4, or 2, or 10, or whatever) of attacks for each pokey. You could have just 4 integers (enum) that simply name the attacks each has, if an attack is extremely simple (little more than its name and related output text, for example). Given that an attack is probably rich (damage, range, number of targets, stuff like that?) the first design is probably the best one.

you look like you are partway into this idea already, except you have specific attacks as their own class; what you need is a general purpose attack class its members can determine its features. That is what you would have 4 of in the main class.

you don't need the C code here :
struct foo
{
blah;
} cstyle; //don't do this, its outdated and weird.

just do this:

vector<foo> attacks(4);
inside your class. Or if the (4) isn't allowed (can't remember) do 4 pushbacks in the c-tor.

1
2
3
4
5
6
7
8
9
10
11
12
class Pokemon
{
public:
	string name; 
	string type1;
	string type2;
	int HP;
	int Atk;
	int Def;
	int Speed;
       vector<attack> Attacks(4); //or, attack Attacks[4]; if you prefer array.
};


If this does not make sense, ask again.
Last edited on
I agree with @jonnin completely.

I threw together some basic code which just translates your c style code to c++ and makes it work with encapsulation (meaning that the members of your class are private and accessed through methods,rather than directly.) If you can assure me that this is a project just for fun and not a homework assignment I will add the code.
Thank you so much! But, when I write out the object in main , would I write:

Pokemon "Name" {HP, Attack, Defense, Speed, "Attack1", "Attack2","Attack3", "Attack4"}; ?

Also, should I keep the structs there or delete them, since there is a vector?
I believe @jonnin mentions creating an Attack class similar to your Pokemon class. If you do that, there is no need for your structs anymore.
Gotcha. Thanks for the help, guys!
you do not need the special attack structs like
struct attack_tbolt : public attack
at all.

I freely admit I don't have a clue how to initialize your class the way you asked.
All I can think of to do is in 'main' initialize all the attacks there, in a vector, one at a time, possibly using a named enum as the index to keep track, and passing subsets of those to your constructor to populate the pokey class's vector. Which is crude and probably not the best way. I will defer to our more skilled experts on the correct approach here. I'm a dinosaur :)



Last edited on
@Ninjacop is this a project for fun or a homework project? If this is a personal project for fun I have a basic working example that is based off your original code.
While you're at it, how would I initialize the vector? I am having a little trouble:

Pokemon Shedninja {HP, Attack, Defense, Speed, Ember };

ERROR: no suitable user defined conversion from "attack" to "std::vector<attack, std:: allocator<attack>>" exists
Last edited on
All it takes to initialize a vector is vector<type> varName
std::vector<Attack> attacklist{fireblast,blizzard,hydroCannon, aeroblast};
come to think of it though, if attacks are all constant (?) you could just have 1 big vector of all of them (shared, static perhaps) and use a reference/index into it. May or may not make more sense this way.
Last edited on
@jonnin most attacks are constant but there are a few that vary. I agree with a common storage may be appropriate perhaps a std::map with a string as the key mapped to the attack itself.
Yes, all of the attacks are constant, so making one big vector is possible. As @knowclue said above, it would probably just look like that.
@Ninjacop just out of curiosity are you planning to implement all the attacks? If so, it might be worth it to create a text file or a .csv file and read it in to populate all the files instead of writing the code for the thousands of attacks.
Probably not, I was just going to use some personal favorites. @knowclue, using the vector using provided above, how could I write that Shedninja (in this case) has the attack Fire Blast? I am having trouble calling it in that object. (I forgot to mention that I'm a total newbie at OOP)
@Ninjacop is this just a project for fun?
You know it is! (Pokemon is a fan favorite between my friends and I, and I wanted to make something that would blow their socks off!)
Last edited on
Perfect. I am an avid Pokemon fan myself. I have been thinking about making an offline damage calculator, but have never gotten around to it. Here is some code based off your intial input. I changed Shedinja's second type to bug to more accurately reflect the games :)

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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//#include"stdafx.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Attack
{
  public:
    //constructor for attack taking all the information
    Attack(string atkName, int atkPower, int atkPp, int atkAcc, string atkType): //this is used post c++ 11 to initialize the member variable and behaves identical to 
      name(atkName), //name == atkName
      power(atkPower), //power == atkPower
      pp(atkPp), //etc.
      accuracy(atkAcc),
      type(atkType)
    {
    }
    
    //accessor methods. Returns the value of the member variable. 
    string getName()
    {
      return name;
    }
    
    //if you need a public way to change a member variable create the setter
    //void setName(string newName)
    //{
    //  name  = newName;
    //}
    int getPower()
    {
      return power;
    }
    
    int getPp()
    {
      return pp;
    }
    
    int getAccuray()
    {
      return accuracy;
    }
    
    string getType()
    {
      return type;
    }
    
  private:
    string name;
    int power;
    int pp;
    int accuracy;
    string type;
};

class Pokemon
{
  public:
  //constructor with all the needed information to create a pokemon
    Pokemon(string pokeName, string typ1, string typ2, int hpStat, int atkStat, int defStat, int speedStat, vector<Attack> &attacks):
      name(pokeName),
      type1(typ1),
      type2(typ2),
      HP(hpStat),
      Atk(atkStat),
      Def(defStat),
      Speed(speedStat),
      attackList(attacks)
    {}
    
    //prints out the stats for your pokemon
    void statPg()
    {
      cout << "#################################################################\n";
      cout << name << ": " << type1 << "/" << type2 << " type\n"
           << "\t" << HP << " HP\n"
           << "\t" << Atk << " ATK\n"
           << "\t" << Def << " DEF\n"
           << "\t" << Speed << " Speed\n\n";
      //loops through the vector and prints out each attack information
      for(auto iter = attackList.begin(); iter != attackList.end(); iter++)
      {
        cout << iter->getName() << " | " << iter->getPp() << " pp\n";
      }
      cout << "#################################################################\n";
    }
  private:
    string name; 
    string type1;
    string type2;
    int HP;
    int Atk;
    int Def;
    int Speed;
    vector<Attack> attackList; //vector of attacks
    
};

int main()
{
  //create attacks directly no need to inherit and create a new struct
  Attack ember("Ember",40,30,95,"Fire");
	Attack hydropump("HydroPump",120,5,75,"Water");
	Attack tbolt("Thunderbolt",100,10,100,"Electric");
	Attack electroball("Electro Ball",150,10,100,"Elecric");
  Attack fireblast("Fireblast",150,5,80,"Fire");

  //create your attack lists for the pokemon
  vector<Attack> golemAttack{ember,fireblast,tbolt,electroball};
  vector<Attack> ShedinjaAttack{hydropump,tbolt,ember,fireblast};
  
//Pokemon!
  Pokemon Shedninja("Shedninja","Ghost","Bug",1,0,0,100,ShedinjaAttack);
  Pokemon Golem("Golem","Rock","Ground",126,102,200,78,golemAttack );
  
  //show pokemon stats
  Shedninja.statPg();
  Golem.statPg();

	
}


Let me know if you have any questions with it.
Last edited on
No questions needed! Thank you so much, it all comes together! Now to implement pretty much everything else that a pokemon battle needs!
Good luck. If youre trying to implement the actual formulas you will need special stats. Hope it all comes together for you.
Topic archived. No new replies allowed.