3

Example code:

#ifndef SPELL_ENUMS_H
#define SPELL_ENUMS_H

namespace spellEnums {
        // Cantrips
    enum LEVEL_ZERO 
    {
        enum EVOCATION 
        {
            _DANCING_LIGHTS
        };
        enum CONJURATION 
        {
            _ACID_SPLASH
        };
    };

};

So I can do stuff like LEVEL_ZERO::EVOCATION::_DANCING_LIGHTS ?

Although an alternative suggestion to have all 300+ 3.5e Dungeons and Dragon's type defined in a tight tidy easily readable and conveniently accessible would be greatly appreciated. :D

Or do I have to do lame namespacing like:

namespace LEVEL_ZERO {
        // Cantrips
        enum EVOCATION 
        {
            _DANCING_LIGHTS
        };
        enum CONJURATION 
        {
            _ACID_SPLASH
        };

};

namespace LEVEL_ONE {
        // Level one spells
        enum EVOCATION 
        {
            _FLAMING_HANDS
        };
        enum CONJURATION 
        {
            _MAGE_ARMOUR //BECAUSE JE SUIS CANADIEN le poutine eh?! 
        };

};

Or will this cause weird problems?

RaenirSalazar
  • 556
  • 1
  • 7
  • 20
  • 3
    You're using [reserved identifiers](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). – chris Oct 29 '13 at 06:31
  • They're just personal variable naming scheme to avoid the dreaded "BLARGH IS AMBIGUOUS" syntax error, that I can never seem to figure out. The Linked page doesn't seem to address my question. – RaenirSalazar Oct 29 '13 at 06:44
  • The point of the link was to show that ordinary programs are not supposed to use names beginning with underscores, because those are reserved for compiler vendors. If you open up one of the library files in your compiler, you'll find it filled with identifiers like `_rb_tree_node`; they name them like this so that if you want to implement your own Red-Black Tree using the name `rb_tree_node`, you don't run into a conflict with the one in the standard libary. – Ben S. Oct 29 '13 at 07:07
  • The bigger problem is that `level 0` is an attribute of spell `FLAMING_HANDS`, which is an `EvocationSpell`. You probably should implement these spells as derived classes. – MSalters Oct 29 '13 at 08:42

2 Answers2

1

I do not think that nesting enums is good approach I would use rather something like this:

enum _spell_enum 
    {
    _spell_evocation_beg=0x00000000,
    _spell_dancing_lights0,
    _spell_dancing_lights1,
    _spell_dancing_lights2,
    _spell_dark_shroud0,
    _spell_dark_shroud1,
    _spell_dark_shroud2,
    _spell_...,
    _spell_evocation_end,

    _spell_conjuration_beg=0x01000000,
    _spell_acid_splash0,
    _spell_acid_splash1,
    _spell_acid_splash2,
    _spell_acid_beam0,
    _spell_acid_beam1,
    _spell_acid_beam2,
    _spell_...,
    _spell_conjuration_end,

    _spell_teleport_beg=0x02000000,
    _spell_teleport_home,
    _spell_teleport_town_a,
    _spell_teleport_town_b,
    _spell_teleport_town_c,
    _spell_teleport_town_d,
    _spell_...,
    _spell_teleport_end,
    };

PS. if you need additional info like level and so then you can use additional tables with the needed information or use const int instead of enum and code the info into code directly (for example level could be high or low n bits) or you can group enum by level not spell type ...

also your second solution is not good because i think you need unique ID for spells and separate enums are overlapping (unless you provide start value)

Spektre
  • 49,595
  • 11
  • 110
  • 380
0

If you really want to do this, I believe you have to use namespace and not enum. Note that the enum name isn't treated like a scope, so in the case of:

namespace LEVEL_ONE {
    // Level one spells
    enum EVOCATION 
    {
        FLAMING_HANDS
    };
    enum CONJURATION 
    {
        MAGE_ARMOUR //BECAUSE JE SUIS CANADIEN le poutine eh?! 
    };
};

The values would be referred to in the form LEVEL_ONE::FLAMING_HANDS, not LEVEL_ONE::EVOCATION::FLAMING_HANDS. You could get the desired effect with something like:

namespace LEVEL_ONE {
    // Level one spells
    namespace EVOCATION 
    {
        const int FLAMING_HANDS = 0;
        const int MAGIC_MISSILE = 1;
    };
};

I don't think that you want the values to be different types anyway, which is what you would get using enum in the way you had suggested. It seems likely that you're going to want to pass around objects of type Spell (or similar) that can refer to any spell rather than having separate types for spells from all the different schools and levels. I would probably tend toward something like:

class Spell
{
public:
    enum Magic_Type
    {
        ARCANE,
        DIVINE
    };

    enum School
    {
        EVOCATION,
        CONJURATION,
        DIVINATION,
        ...
    };

    int get_level();
    Magic_Type get_type();
    School get_school();
    void cast_on(Target &t, Board &b);  // Needs the Board to affect secondary targets.
    ...
};
Ben S.
  • 1,133
  • 7
  • 7
  • Supposing that I wish to have every spell I'm able to implement listed; for example such as when I populated an "Available Spells" menu for a Wizard character on level up of all available spells for his level? Edit: So thinking on it, the issue I find is having to define some 300 spells supposing I managed to implement that many. It seems useful to my mind to have those 300 spells having pre-defined enumerated variables to pass to the constructor for easy comparison. So I would combine the Spell class you suggest, with the const int namespace, and have some pre-made spell object array? – RaenirSalazar Oct 29 '13 at 07:10
  • 1
    I'm not sure what question you're trying to ask here - it seems like you've given me the setup ("Suppose that X") without a following question. If you're asking if that's an example where you'd want to have `Spell` objects of any school or level, I would say yes. – Ben S. Oct 29 '13 at 07:17
  • I just wanted to clarify that this below is how I am likely implementing spells: 1. Within the namespace you have in the middle have all my implemented spells defined as const ints. 2. Whenever I create a new spell object, I manually pass which one it is. So, Spell* mySpell = new Spell(MAGIC_MISSILE,ARCANE,LEVEL_ONE,ETC) for all implemented spells in Some_Spell_Array if I wanted a handy list of all available spells to pick from sorted by level. And then otherwise create new spell objects in the game itself when they're casted? – RaenirSalazar Oct 29 '13 at 07:40
  • 1
    @RaenirSalazar: You can't iterate from `namespace LEVEL_ZERO` to `namespace LEVEL_THREE`. So, how would you get the spells for a level 3 wizard? – MSalters Oct 29 '13 at 08:44
  • @MSalters if I had an array of all my spells wouldn't be possible to display only those spells in the array whose level is <= current level? This is what I am trying to figure out. – RaenirSalazar Oct 29 '13 at 15:43
  • 1
    @RaenirSalazar: Your enums, as currently designed, all have their own type. `FLAMING_HANDS` has numerical value 0, as does `_ACID_SPLASH`, but they have different types. That does mean you can't even put them in one array as-is. And if you cast them to `int` the distinction is lost. They'd both be 0. – MSalters Oct 29 '13 at 15:53