To those who are reading this to learn something, I must say that I'm going rather quick here, withour explainations - they will come later, be patient :)
So far, I've created the following classes:
- Attribute: handle the creature attributes.
- Skill: handle the creature skills. The creatures skills reference an attribute.
- Inventory: the creature inventory. It contanis a list of...
- InventoryObject: guess what ? Yes, it is. The creature inventory is full of InventoryObject. This is the base class of all the other objects (weapons, armors, keys, money, and so on)
- InventoryVisitor: this is an application of the visitor pattern.
- CreatureRace: abstract class that gives informations about the creature race (its capabilities, its sub-type, the standard skill and attributes values, the racial skill and attributes modifiers, and so on). It is easy to inherit (a lot of small functions to write) so creating new races is really fun :)
- and of course Creature: this is the creature holder class. Any character or monster in the game is a Creature instance (the difference comes from the race and the class [not implemented yet]).
- some small utility classes: Dice<> is a template class that emulates a dice and Dicebag is only used to shuffle the dices (ie seed the randomizer [smile]).
There is something bad with the visitor pattern. It somewhat breaks the open-closed principle (see [RM-1]) because if I add a new InventoryObject type, I need to add a new method in the InventoryVisitor class. Oh, wait. I just had a look to my GoF and found that this is point 3 of the consequences section for the visitor pattern:
3. Adding new ConcreteElement classes is hard. The Visitor pattern makes it hard to add new subclasses of Element. Each new ConcreteElement gives rise to a new abstract operation on Visitor and a corresponding implementation in every ConcreteVisitor class. Sometimes a default implementation can be provided in Visitor that can be inherited by most of the ConcreteVisitors, but this is the exception rather than the rule.
I choose the exception rather than the rule and my visitor class is not abstract (the methods does nothing). This is not a problem for me, because in the game system most visitors will only overload one of the base class method (a key is not a weapon, and you can't use your helmet as a spell). But still, I'll have to modify the base visitor class each time I'll want to add a new object type.
As you see, there is not a lot of code (roughly 18 kB, and there is a lot of comments). Nevertheless the game system code is nearly complete (I have a bunch of InventoryObject inherited classes to write, some InventoryVisitor, as well as the action and combat resolution).
If everything goes well, I'll have some time to work on this subject before the end of the week :)
See you later, dudz !