Structures, Referencing Structures

Hey guys, hopefully this is an easy one. I'm trying a more difficult pokemon battle, and this time, I'm trying to link Pokemon with specific attacks. So, here is what I would like, and what my issue is.

When a pokemon is chosen, that pokemon will reference a specific list, with attacks specific to him. I'm ok there. So, here is the issue.

The first pokemon will be chose at random from an array: rand() % 6
-Until the code is ran, I will never know what was chosen. Is there a way to link the list of attacks, so that the correct one will always match up with the random pokemon chosen?
You could define an object hierarchy for Pokemon. So Pokemon would be an interface.

Each actual Pokemeon would have implement the specifics of that type of Pokemon, and each instance of an object would collect experience and capabilities. It's a standard OO design.

Someone's spent some time on this somewhere in the forum before. You could try to find the posts, or discuss it in depth here. There are many who know a lot about this kind of thing.
I don't understand what you're asking.
What is this "list of attacks specific to him"?
How does this "list of attacks" relate to a specific pokemon?

In your previous thread, you had a structure for each Pokemon (Opponent, Mystats). Those strucures held information specific to a each Pokemon. Have you tried storing the list of attacks as a member of those structs?

Perhaps if you showed some code about this list of attacks and gave some information about why you're having a hard time relating a list of attacks to a specific pokemon it would be easier to understand what you're asking.

Maybe use an std::bitset to represent attributes that limit what kind of attacks each creature is capable of? For example; let's say the flaming lizard thing gets selected and you're at the point where you are building his list of attacks. He rolls 'X' and it turns out to be a claw attack, you check that creatures std::bitset and it is allowed so the attack gets added. Now the next roll comes up as a water attack but a check of the std::bitset says that is not allowed so it then re-rolls. I may have messed up in explaining that, I'm trying to describe the same idea that file systems use to manage permissions.

Alternatively you could just have a list of valid attacks for each creature type loaded into an std::map. The attack generator would first check to see which list to use and then it would apply your RNG result to that list. This one might be easier but it's less flexible and more tedious to manage then my first suggestion.
All good suggestions. Love the flaming lizard comment. I used one structure for two creature lists, and then another structured that is a list of moves. Something like 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
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
//1 Vs 1 Battle
#include <iostream>
#include <string>
#include <sstream>
#include <ctime>
#include <cstdlib>
using namespace std;

struct Pokemon {			//Pokemon list
	string name;
	int health; // HP 100-200
	int defense;// Def 50-100
	};
	
Pokemon matt [6] = {    //Matt's Pokemon
	"Scizor", 140, 100,
	"Mewtwo", 150, 65,
	"Hitmonlee", 120, 55,
	"Umbreon", 160, 90,
	"Lucario", 130, 70, 
	"Lugia", 180, 80
	};
	
Pokemon chad [6] = {		//Chad's Pokemon
	"Garchomp", 160, 80,
	"Metagross", 150, 100,
	"Charizard", 145, 74,
	"Aegislash", 130, 100,
	"Quagsire", 155, 85,
	"Gardevoir", 175,65};
	
struct Attacks {	//Pokemon Attack List
	string name;
	int damage;
};	

Attacks garchomp[4] = {		//Garchomps Moveset
	"Take Down", 28
	"Sand Tomb", 10,
	"Dual Chop", 12,
	"Dragon Rush", 30
};

Attacks metagross[4] {		//Metagross's Moveset
	"Metal Claw", 15,	
	"Zen Headbutt", 25,
	"Psychic", 28,
	"Hammer Arm", 30
};

Attacks charizard[4] = {	//Charizard's Moveset
	"Flare Blitz", 30,
	"Flame Thrower", 28,
	"Slash", 15,
	"Fly", 15
};

Attacks aegislash[4] = {	//Aegislash's Moveset
	"Fury Cutter", 12,
	"Shadow Sneak", 12,
	"Iron Head", 25,
	"Pursuit", 12
};

Attacks quagsire[4] = {		//Quagsire's Moveset
	"Water Gun", 12,
	"Mud Shot", 15,
	"Earthquake", 30,
	"Muddy Water", 25
};

Attacks gardevoir[4] = {	//Gardevoir's Moveset
	"Moon Blast", 28,
	"Magical Leaf", 17,
	"Confusion", 15,
	"Psychic", 28
};

Attacks scizor [4] = {		//Scizor's Moveset
	"Metal Claw", 15,
	"Fury Cutter", 13,
	"X-Scissor", 25,
	"Night Slash", 22
};

Attacks mewtwo [4] {		//Mewtwos Moveset
	"Psychic", 25,
	"Psystrike", 30,
	"Swift", 20,
	"Aura Sphere", 23
};

Attacks hitmonlee [4] = {		//Hitmonlees Moveset
	"Close Combat", 30
	"Blaze Kick", 25,
	"Mega Kick", 22
	"Brick Break", 18
};

Attacks umbreon [4] = {			//Umbreons Moveset
	"Tackle", 15
	"Assurance", 20,
	"Hyper Beam", 30,
	"Pursuit", 13
};

Attacks lucario [4] = {			//Lucarios Moveset
	"Aura Sphere", 25,
	"Bone Rush", 10,
	"Metal Claw", 15,
	"Dragon Pulse", 25
};

Attacks lugia [4] = {			//Lugias Moveset
	"Dragon Rush", 30,
	"Ancient Power", 20,
	"Gust", 10,
	"Aeroblast", 30
};	


So, Chad is a random roll, and Matt will be a user selection. If Chad's random roll is Pokemon chad.Charizard, , how do I associate Attacks charizard[4] to the first list of Pokemon chad?
If there is a tight coupling between the pokemon and their available attacks, there is no reason to separate them:

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
struct Pokemon
{
    string name;
    int health;
    int defense;
    Attacks attacks[4];
};


/////////////////////
//  In general, hardcoding data is a bad idea.  Consider storing this information in a text
//  file or something, and loading it when the program starts.  I'll have it hardcoded here
//  in the interest of keeping this example short

const Pokemon allPokemon[] = {
    {
        "Scizor", 140, 100,
        {"Metal Claw", 15,
        "Fury Cutter", 13,
        "X-Scissor", 25,
        "Night Slash", 22}
    },{
        "Mewtwo", 150, 65,
        {"Psychic", 25,
        "Psystrike", 30,
        "Swift", 20,
        "Aura Sphere", 23}
    }
    // ... put the rest of the pokemon here
    // ... but again... this is better if it's not hardcoded in your program.
    // Put it in a file and load it.
};

////////////////////
// Have a function return the pokemon based on name lookup
//
// Note:  in hindsight this would be easier to do if the pokemon were stored in a map
//  instead of an array.  But whatever
Pokemon findPokemon(const string& name)
{
    for(auto& i : allPokemon)
    {
        if(i.name == name)
            return i;
    }
    
    // Pokemon not found... possibly throw an exception, but instead I'll
    //  just return a default/junk pokemon to keep the example simple.  But again
    //  this is a very bad idea since this is extremely poor error handling.
    return Pokemon();
}

////////////////////
//  Then, rather than giving your players all the pokemon they could potentially start with,
//  just give them the name:

Pokemon chadsPokemon[6] = {
    findPokemon("Garchomp"),
    findPokemon("Metagross"),
    //...
    };
    
I second Disch's excellent suggest that you not hard code your pokemon characteristics. By loading your pokemon characteristics from a file, you can easily change the dynamics of your game simply by loading a different text file.

However, if you're going to use the hard coded approach, you can simplyfy Disch's initializaton lists for the pokemons by using a pointer to the attack entry for the respective pokemon.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Pokemon 
{   string name;
    int health; // HP 100-200
    int defense;// Def 50-100
    const Attacks * attacks;  // pointer to attack array for this pokemon
};

Pokemon matt [6] = {    //Matt's Pokemon
	"Scizor", 140, 100, scizor,   // 4th entry is name of attack array
	"Mewtwo", 150, 65, mewtwo, 
	"Hitmonlee", 120, 55, hitmonlee,
	"Umbreon", 160, 90, mewtwo,
	"Lucario", 130, 70, mewtwo,
	"Lugia", 180, 80, mewtwo,
	};
//  Ditto for chad 


BTW, check your attack arrays closely. You have several missing = or commas.
Ok. I already have them in separate .txt files (yay me) just threw them together for the forum.

At this moment, I have no idea what you mean by map. But, that's for me to attempt to figure out first. Those are fantastic suggestions, and thanks for the advice. AbstractionAnon, how long have you been coding?

I ask, because you've posted on just about everyone of my posts, and your help has been greatly appreciated.
They are referring to the container std::map http://www.cplusplus.com/reference/map/map/

Example code from std::map::map (http://www.cplusplus.com/reference/map/map/map/ ).
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
// constructing maps
#include <iostream>
#include <map>

bool fncomp (char lhs, char rhs) {return lhs<rhs;}

struct classcomp {
  bool operator() (const char& lhs, const char& rhs) const
  {return lhs<rhs;}
};

int main ()
{
  std::map<char,int> first;

  first['a']=10;
  first['b']=30;
  first['c']=50;
  first['d']=70;

  std::map<char,int> second (first.begin(),first.end());

  std::map<char,int> third (second);

  std::map<char,int,classcomp> fourth;                 // class as Compare

  bool(*fn_pt)(char,char) = fncomp;
  std::map<char,int,bool(*)(char,char)> fifth (fn_pt); // function pointer as Compare

  return 0;
}
Topic archived. No new replies allowed.