[ LiB ]

I'm beginning to feel like a broken record here: "Here's the player database; here's the item database; here's the room database...". Guess what? Here are the enemy databases! (I bet you didn't see that one coming).

There are two enemy databases, as you saw earlier in Figure 10.1: one database to store enemy templates, and one database to store enemy instances.

It is crucial to determine what kind of database will be optimal to use for each of these different types. First you need to think about how they are used.


Since you're storing the enemy templates inside of a vector array, the IDs of your templates need to be contiguous, or else you'll have holes in your database; you'll have enemy templates that just don't exist, but the database thinks they do.

Enemy Template Database

Enemy templates are loaded one time, from disk, and then never modified. If you're careful when you create the enemy templates, they should have contiguous ID numbers (meaning that if you have 50 enemies, they should occupy IDs 1 through 50). Because of these properties, a vector-based database sounds ideal, and that's what I use:

 class EnemyTemplateDatabase : public EntityDatabaseVector<EnemyTemplate> { public:     static void Load(); }; 

The database simply uses one function to load the template data from disk. The file is /enemies/enemies.templates. The Load function is similar to all the other database loading functions you've seen in the past two chapters, so I'm not going to bother with it here.

Enemy Database

The enemy database stores all of the enemy instances within the game. These instances are far more volatile than the templates. The instances are created whenever the game needs more enemies, and they are deleted when the enemies die. It makes a lot more sense to use a map-based database for these:

 class EnemyDatabase : public EntityDatabase<Enemy> { public:     static void Create( entityid p_template, room p_room );     static void Delete( enemy p_enemy );     static void Load();     static void Save(); }; 

There are two functions that deal with creating and deleting instances, and two functions dealing with loading and saving. I'll skip the file functions (if you're interested, you can always look at the source, but they basically loop through the enemies/enemies.instances file and load in individual enemy instances) and go right into the creation and deletion functions.

Creating Enemy Instances

The game should be capable of quickly and painlessly creating new enemies. The EnemyDatabase class has a function designed just for that purpose. It's a factory function, which means that you just tell it what kind of enemy you want and where you want it, and the function creates the enemy for you.


Factory generators are a popular method of generating actual instances of entities in MUDs. I like the method so much that the BetterMUD uses it almost exclusively.

Here's the code:

 void EnemyDatabase::Create( entityid p_template, room p_room ) {     entityid id = FindOpenID();    // find an open ID     Enemy& e = m_map[id];          // get reference to enemy at ID     e.ID() = id;                   // set its ID     e.LoadTemplate( p_template );  // load its template     e.CurrentRoom() = p_room;      // set its room     p_room->AddEnemy( id );        // add the enemy to its room } 

The function uses the EntityDatabaseVector::FindOpenID function to find the first ID in the map that isn't being used. Once you have an ID, the function uses the map's operator[] to retrieve a reference to the Enemy object bundled with that ID. (It doesn't matter that it doesn't exist. I showed you previously that std::map::operator[] automatically creates entries that don't exist.)

After the ID of the enemy is set, the enemy's template is loaded, and the enemy's current room is set. The final step is to add the enemy to the room.

Within the game, you can simply call the function like this:

 EnemyDatabase::Create( 1, 5 ); 

That creates an enemy of type 1 in room 5.

Deleting Enemy Instances

Deleting enemy instances is a simpler processit must merely reverse the creation process:

 void EnemyDatabase::Delete( enemy p_enemy ) {     p_enemy->CurrentRoom()->RemoveEnemy( p_enemy );     m_map.erase( p_enemy ); } 

The enemy is removed from its room, and then erased from the std::map that stores all the instances. That's it!

Database Pointers

As with most of the previous entity types you've seen (players and items in Chapter 8, rooms in Chapter 9), both enemy classes have corresponding database pointers.

These two lines are added to the SimpleMUD/DatabasePointer.h file:

 DATABASEPOINTER( enemy, Enemy ) DATABASEPOINTER( enemytemplate, EnemyTemplate ) 

And these two lines are added to the .cpp file for the implementation of the pointer functions:

 DATABASEPOINTERIMPL( enemy, Enemy, EnemyDatabase) DATABASEPOINTERIMPL( enemytemplate, EnemyTemplate, EnemyTemplateDatabase ) 

Now you have access to two database pointer classes: enemy and enemytemplate . They are used just like any other database pointer object within the SimpleMUD.

[ LiB ]

MUD Game Programming
MUD Game Programming (Premier Press Game Development)
ISBN: 1592000908
EAN: 2147483647
Year: 2003
Pages: 147
Authors: Ron Penton

Similar book on Amazon © 2008-2017.
If you may any questions please contact us: