Sign in to follow this  
RavynousHunter

a few questions about vectors

Recommended Posts

I've begun work on the StatBlock class of my D+D game, and I have a few questions reguarding vectors. first question : Is this code right?
vector<EnumVar> myVector;


Basically, I'm creating a vector "myVector," and setting it so that the data within it are of the things found in "EnumVar," which, as the name implies, is a variable of the enum type. second question: I'm trying to make accessor functions that take in the player's different vectors for things such as feats, classes, and whatnot, which are protected, and I want them returned as a vector consisting of strings, and was wondering if this was the proper way to put the function into code:
vector<string> getClasses();


third question: This relates to the second question strongly. How would I properly code the function to read through the vector, read the specific entries, and return the results as strings of the names of the different entries. Something like this:
vector<string> playerClasses;
int ListSize = StatBlock::ClassList.size();  // set it equal to the size of the vector
for (int i=0; i<ListSize; ++i)
{
  // reading, writing, and conditional statements should go here.
}
return playerClasses;


and an example of whats going on inside the "for" loop:
if (StatBlock::ClassList[i] == Monk)
{
  playerClasses[i] = "Monk";
}
if (StatBlock::ClassList[i] == Ranger)
{
  playerClasses[i] = "Ranger";
}

The enum variable for the Classes is stored as a public variable within the class, so would I need to reference the class and corresponding enum for this particular conditional statement to function properly? I'm just looking for some direction here, as its a little confusing on my end.

Share this post


Link to post
Share on other sites
Your example in your first question is correct.

As for the second and third, I think you've got generally the right idea, but you're off a little bit. Why expose the classes as a list of strings (that appear to just represent the names of the classes)? What happens if, in the future, you might want to know about the list of, say, base HP values for each class? You'd have to write a method called getClassHPs(), which is going to eventually tightly couple your class to whatever object is exposing this getClasses() method.

A better overall solution might be to simply model a "class" as a type itself

class PlayerClass
{
/* getName(), getBaseHP(), etc */
};

instead of just an enum value. Then you can make your getClasses() method look like:

const std::vector<PlayerClass>& getClasses() const { return (myInternalClassList); }

where myInternalClassList is the std::vector<PlayerClass> stored within the object that getClasses() is a member of.

Share this post


Link to post
Share on other sites
You seem to have a good grasp on this.

For returning a vector, I would suggest using a pointer though. I do not know how exactly a vector handles copying itself (does it actually copy all elements? can anyone confirm).

As for going through all the elements, you can either use your method or used iterators. Check this out: http://www.cplusplus.com/reference/stl/vector/begin.html

Iterators are variables that act like pointers to specific elements in the vector, which you can increase sequentially either forward or backwards. I am not exactly sure about the benefits of iterators vs manual (int x =0; x < vec.size();x++) iteration, but iterators seem to be the favored choice. Again, can someone more experienced elaborate on this?

Share this post


Link to post
Share on other sites
Quote:
Original post by jpetrie
Your example in your first question is correct.

As for the second and third, I think you've got generally the right idea, but you're off a little bit. Why expose the classes as a list of strings (that appear to just represent the names of the classes)? What happens if, in the future, you might want to know about the list of, say, base HP values for each class? You'd have to write a method called getClassHPs(), which is going to eventually tightly couple your class to whatever object is exposing this getClasses() method.

A better overall solution might be to simply model a "class" as a type itself

class PlayerClass
{
/* getName(), getBaseHP(), etc */
};

instead of just an enum value. Then you can make your getClasses() method look like:

const std::vector<PlayerClass>& getClasses() const { return (myInternalClassList); }

where myInternalClassList is the std::vector<PlayerClass> stored within the object that getClasses() is a member of.



Wait a minute, you have me confused here. I think you misconstrue the context of a "class". The way I intended it to be read as was "the player's profession(s)," not an actual C++ class.

The reason I made it enum was because making the professions thier own class seemed to me to be unnecessairly complicated. Besides, the only thing a profession has is certain abilities (ie: spellcasting, bonus feats, etc) and assiciated hit dice (ie: d6, d10). It would be simpler to simply make a few flag variables for things like spellcasting and bonus feats. That way, I can have everything I need in only one class, and keeping things far simpler and far more organized.

Share this post


Link to post
Share on other sites
I would tend to pass in a reference to a vector that I want filled with info, then the function can do whatever it needs to however it likes, i.e. it can append to the vector, clear it first, copy to it or whatever. That then leaves the return value for whatever other use I need.

eg.
bool GetClasses(std::vector<Class>&)

Also I second making the professions instances of a class, or a struct at least. I get the impression you're going to end up with an enormous lookup table of variables and that kind of thing can get disorganised very quickly. Why not encapsulate all info for a profession in a single item? Then (if you need to) have a single std::map from a string to a profession object.

L
-

Share this post


Link to post
Share on other sites
...?

Youre confusing me here w/ the profession thing. All in all, theres at most like 10 professions (cant remember right offhand). Theres really no point in making a profession its own class, heres my idea:


/*
Flags to determine what kind of spells, if any,
the player can utilize. False is the default
setting unless the player chooses a magic-using
class such as Sorcerer or Druid.
*/

bool canCastArcane = false;
bool canCastDruid = false;
bool canCastBard = false;
bool canCastPaladin = false;
bool canCastCleric = false;

/*
Flags to determine what kind of special,
class-based things the player can take
advantage of. Default = false, abridged.
*/

bool hasFighterBonusFeats = false;
bool hasMonkBonusSpeed = false;
bool hasWildShape = false;




In my mind, this would be simpler. Basically, when the player chooses a class, either as a primary or secondary, one or more of these flags are set. For example, if the player is a primary Fighter, thier hasFighterBonusFeats flag is set to true, and if they choose later on to be a Sorcerer secondary, thier canCastArcane flag is set to true. Also, the appropriate enum values are placed into the ClassList vector. This way, we dont have to mess with the potentially messy inheritance problems associated with making each profession its own inhereted class.

This also brings up something else i forgot, i need to make two different level-based vars, one for the player's actual level, and another, a vector, for class levels.



[edit]
Ive completed v1.0 of the getClasses function, can you tell me if i got it right?


const vector<string>& StatBlock::getClasses() const
{
vector<string> playerClasses;
int ListSize = StatBlock::ClassList.size();
for (int i=0; i<ListSize; i++)
{
switch (StatBlock::ClassList[i])
{
case Barbarian:
{
playerClasses[i] = "Barbarian";
break;
}
case Bard:
{
playerClasses[i] = "Bard";
break;
}
case Cleric:
{
playerClasses[i] = "Cleric";
break;
}
case Druid:
{
playerClasses[i] = "Druid";
break;
}
case Fighter:
{
playerClasses[i] = "Fighter";
break;
}
case Monk:
{
playerClasses[i] = "Monk";
break;
}
case Paladin:
{
playerClasses[i] = "Paladin";
break;
}
case Ranger:
{
playerClasses[i] = "Ranger";
break;
}
case Rogue:
{
playerClasses[i] = "Rogue";
break;
}
case Sorcerer:
{
playerClasses[i] = "Sorcerer";
break;
}
case Wizard:
{
playerClasses[i] = "Wizard";
break;
}
}
}
return playerClasses;
}


[/edit]

Share this post


Link to post
Share on other sites
No, I understood what you meant by "class" (same as "profession"). And you're correct that there is no point in making each profession a separate class; however, you should create one class that models the concept of a Profession (this is perhaps a better name than my hastily-chosen and ill-thought-out "PlayerClass," above).

Anyway, responding to your newest post will allow me to restate my original suggestion (which still applies even in light of all this new information), so here we are:

Quote:

Ive completed v1.0 of the getClasses function, can you tell me if i got it right?

This function is generally poor and redundant. The first issue is the name. StatBlock::getClasses() doesn't return a list of classes, it returns a list of class names. So, if this is really desired, the function should be called getClassNames(). The second issue is that the function is poorly designed, as it places responsibility for naming classes with the StatBlock and not with the profession class itself. Finally, it is redundant because StatBlock::ClassList itself provides exactly the same information.

What I suggested before, and what I continue to suggest now, is that you have:

class Profession
{
public:
Profession(const std::string &name,int baseHP,int baseMP); //...and so on.

const std::string &getName() const;
};


This class models the concept of a profession, including that professions display name, base stats, abilities (can it cast clerical spells, mage spells, turn undead, and so on).

StatBlock::ClassList becomes a vector<Profession>. You can initialize this however you like, from a file, or from code:

StatBlock::ClassList.push_back(Profession("Warrior",100,25));
StatBlock::ClassList.push_back(Profession("Mage",50,250));
StatBlock::ClassList.push_back(Profession("jpetrie",std::numeric_limits<int>::max(),std::numeric_limits<int>::max()));

And so on.

This makes getClasses() redundant, as you can just iterate through ClassList and call the Profession's getName() method, or whatever other method you want to call that exposes the functionality you need (such as what the abilities, HP, et cetera of that profession are). This is actually more flexible and maintainable, and overall a better object model for the system.

The player object itself can be assigned a Profession instance that is a copy of, or a reference to, an element in StatBlock::ClassList. That way you can represent the profession of the player without redundant information.

The idea of keeping everything in one class seems simpler, but its actually more brittle and generally poorer design in 99% of the cases. It's possible that your "stat block" class might be the same as what my "profession" class is supposed to be, but in that cases I would argue that your name is poorly chosen, and that getClasses() is an inappropriate member function... but that all depends.

Can you explain your system in a large context? What is a StatBlock, what does it represent, and how is it used in your system? How do you represent the player? And so on. It will help focus our discussions.

[Edited by - jpetrie on May 14, 2007 1:38:25 PM]

Share this post


Link to post
Share on other sites
A StatBlock is basically all the essential statistics for the player, thier name, level, class(es), HP, ability scores/modifiers, feats, etc. As for how i represent the player, in context of the StatBlock, is that the actual Player Character is a class of its own, with such properties as its sprite and whatnot, and has a "has-a" relationship w/ the StatBlock class. The entire concept of a StatBlock was introduced to me w/ an earlier project, it helps keep all necessary stats in one place so they can be easily accessed and dont take up space in the main player class.

As i said before, the profession class would be redundant, the only thing a profession determines is weather or not you have access to certain special traits such as a Fighter's Bonus Feats or a Wizard's Arcane Spellcasting, and the Hit Dice for the respective profession (Fighter=d10, Wizard=d4, etc). If you really want to look at what im modelling this after, pick up a copy of the 3.5 version of the Dungeons and Dragons Player's Handbook, thats the exact ruleset Im using.

[Edited by - RavynousHunter on May 15, 2007 8:31:43 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this