How would I create an 'enemies' database? (Text-based game)

Started by
11 comments, last by 0r0d 10 years, 11 months ago

Ravyne, your answer was very enlightening but it also raised a few questions:

  1. Call me an absolute newbie, but I don't quite understand what a parser is. The only notion of it I have in mind is the text parsers used in text games (like Zork) to handle sentences and turn them into strings usable by the program.
  2. When you say 'a vector of structs', do you mean something like that:

    
    vector<enemy> enemyVec
     

    where enemyVec is a vector of elements of the 'enemy' struct type? Also, why not use a class instead of a struct?

  3. As I said, I'm planning on introducing skills later (just like in the early Pokemon games). I haven't completely conceptualized how this will work -I am going to do that after I have a playable combat system- but it will probably be something like this: each monster (and the player) will have an arsenal of skills to use - think Stun, Blind etc. As I see things now, this will probably be ANOTHER database containing all known skills as functions that alter the member variables of the enemy -or the player, in case of healing spells- but this creates two additional problems:
  • I understand how to store the enemy stats in a file like .csv, but that contains single values in each comma-separated instance. For example,

"troll01","a fearsome enemy",100,4 

but how would I save an actual LIST of skills in such a format?

  • How would I go creating the actual code for the skills? Will it be a class defining a generic skill template like

class Skills
{
  string SkillName;
  string SkillDescription = "a skill";
  int damage = 0;
  
  bool canStun() {};
  int doDmg(int damage,int &hp) {};
}; 

that I will have to update the member variables/functions for? Or do I write separate functions for each skill?

  1. Yes, a parser is exactly that, except that in this case its parsing a structured file rather than user input. The structured file could contain XML, YAML, JSON, or any other text-based data format. The job of a parser is to read the file and transform it into a data structure, or set of data structures, that your program can interact with easily, and without hitting the disk again.
  2. Yes, basically. In C++ the only difference between classes and structures is that member visibility for classes defaults to private, while it defaults to public for structs. Otherwise they are identical. However, many programmers prefer to use classes for objects that supply member functions, and structs for objects that do not (or only supply constructor/destructor/assignment). Since in my suggestion I'm advocating that this vector only hold the archetypal monsters (that is, the dictionary definition of particular monsters), rather than the actual monsters that you will be fighting, this struct won't need member functions aside from constructor, destructor, and assignment. When you need a vampire to fight, you can create an instance of a different enemy class by copying data out of the vampire archetype. This other class can provide member functions necessary for dealing and taking damage, using abilities, etc.
  3. You could do a mini component-entity type system to implement abilities, or define an interface and have each monster have a vector/linked list of abilities they can use. You're right that it could also be a "separate database" too; in that case, you'd create a separate vector of structs that provides the ability archetypes (only in this case, the archetype doesn't provide data, it provides a member function (or set of member functions) that expresses the effect, and also you may not have to copy it to use it, because it won't have internal state. To your specific questions:
  • It depends. If you know you'll never have more than 3 abilities, then its sufficient to just have 3 separate values in the CSV and put a null-value in unused ability slots. Another option is to have a formatted field which you can parse a little bit further to figure out, for example {stun|blind} means that the monster has both abilities, {stun} means just stun.
  • It depends. In general I prefer a more data-driven approach (similar to your "generic skill template") because its more flexible if done right. On the other hand, providing an interface made of separate functions or classes for each skill can be more straight-forward. Additionally, the benefits of the skill template approach are reduced if very few abilities are similar (though this is rarely the case).

throw table_exception("(? ???)? ? ???");

Advertisement
Juliean's advice, learning the C++ standard library until you are confident with data structures, is more important than the specific issue of creating and accessing an enemy database. If I were doing it, I'd use a Sqlite database to store enemy definitions and use loaded data (e.g. a list of suitable opponents for a so-and-so player) to populate the data structure that the menu system needs. Using Sqlite offers reliable and easy to use editing tools for free (as opposed to naked text files or writing a proprietary Enemy Editor), flexibility in the monster definitions themselves (just define different tables and move data from the old ones) and flexibility in enemy selection logic (when setting up the menu you run a SQL query, and it's the only thing that needs to change).

Omae Wa Mou Shindeiru

I'd not recommend XML actually, its very verbose and you don't actually seem to need hierarchical structure for what you're doing here. An actual database (e.g. SQLlite) would likewise be overkill.

My recommendation would either be a Comma-Separated-Value file (.csv) which basically any spreadsheet program can work with (which can be a bit more convenient than plain-text so long as the data model is completely flat) or a lighter-weight markup language like json or yaml, both of which have very simple, fast, embeddable parsers, and you don't need to navigate a complex DOM to use effectively.

I'd load the file contents into a vector of structs that represent the enemy stats (the archetype of enemy instances created later), sorted by name (or whatever other key you want to use) so that you can find these archetypes using a binary search.

I agree with this. Use a simple comma-separated text file.

When you're starting out you need to do the simplest things before you can move to the more complicated ones. You need to know what's good and bad about the simple solutions before you can understand why the more complex ones are better, and when they are or are not appropriate.

Trying to do too much and learn too many concepts at the same time will only lead to frustration and failure.

This topic is closed to new replies.

Advertisement