Architecture:Rpg Module

From Adonthell
Jump to navigation Jump to search

This is one of the core modules, providing the low level classes essential for role playing games.

Quests and Logs

To represent the plot and record the player’s progress in the game, the quest system has been written. It allows to define milestones of quests that can be queried and changed by various Python scripts, like dialogues, event callbacks or character schedules. Whenever the state of a quest changes, these scripts can make the neccessary changes to the gameworld. (Todo: generate quest event whenever a quest or part of a quest changes its state.)

As quests are usually not linear and often solvable in multiple ways, each quest is represented by a tree, whose root is the quest itself and whose leaves represent its individual milestones. These milestones are the only part of a quest that can be directly influenced by scripts – they can be set to completed. All the quest nodes below the leaves have a rule how to determine their state of completion from the state of their children. Scripts that only need to know whether a quest as whole is completed can query the state of the quest root, while scripts that need more detailed information can query nodes higher up the tree.

Queries are not limited to the two states complete and incomplete though. The engine distinugishes between the following:

  • started A quest is started as soon as its first milestone is set to completed. (As milestones are atomic, starting them means to complete them)
  • in progress A quest that has been started but not yet completed.
  • completed Once the player has accomplished a quest or part thereof, it is set to completed (in which case it is no longer in progress).

What has been described so far allows the engine to keep track of progress through the game. To help players keeping track, a quest log has been implemented too. This is closely tied to the quest tree, as each node of the tree can have a log entry attached that will be copied into the quest log whenever that node is set to completed.

The log system itself supports several log books; but so far, the quest log is the only one integrated into the engine. Others may be implemented by individual games. In order to ease navigation, the engine provieds support for automatic index generation: a list of keywords can be specified and whenever an entry is copied into a log book, its text is searched for those keywords and an index entry is created under each keyword found in the text. Additionally, an entry can provide additional keywords, so that index entries can also be created for keys not found literally in the text.

On top of the indexing mechanism, a fulltext search could be easily implemented too. All it takes is creating a new index with the search terms as its only keywords. Then all entries of the desired log books need to be processed by that index, resulting in a list of index entries for each keyword. By limiting the search result to entries appearing in all lists, one will find the log entries containing all the search terms. More complex boolean search operators could be supported by processing the resulting lists accordingly. Even though the index is optimized for comparing text against a long list of keywords, a fulltext search done that way should still be pretty fast.

Items and Inventories

In this section, we will explore how items are modelled and kept. The main goal was to allow for all kinds of items, with many different abilities. Creation of new items should be fast and simple, without having to modify the engine. And last but not least, the item system as a whole should be efficient and convenient for both designers and players.

Therefore, items have been splitted into three layers.

  1. Engine layer. Functionality required to manage items is implemented by the engine. This includes item instantiation, inventory handling and access to advanced item functionality.
  2. Extension layer. The item system itself – properties and abilities as well as game rules concerning items – is implemented in Python on top of these basic functions. That way, different games can have totally different item systems.
  3. Data layer. On top of the item system sits the item data, i.e. all the individual items actually available in a game.
Item implementation

The figure shows the relation between extension, data and engine layer. For each “class” of items (such as weapons, books, potions, etc), a template needs to be written in Python. By initialising attributes of the same template with different values, different items can be defined. At runtime, multiple instances of every such item can be created and used by the engine.

For efficiency reasons, the engine distinguishes between two different kinds of items:

  • mutable items require a new instance for every occurrence in the game. As a result, they can be easily changed throughout the game.
  • Immutable items on the other hand are instantiated only once. They are kept in a central item_storage and reference counts are used to allow multiple occurrences in the game.

Despite the fact that large parts of the item system are not implemented by the game engine, items are always stored on engine level, in so called slots. A slot may contain several items of the same kind, if the item is stackable. Immutable items are considered to be of a kind when their instance pointers are equal. For mutable items, item names have to match.

Inventory implementation

With the above in mind, an inventory is easily implemented. It is little more than a list of slots. To remain flexible, only the most basic inventory operations have been implemented on engine level, like adding new items. For convenience, the inventory tries to group items of same kind together in a stack. Furthermore, removal of items happens automatically as they are moved from one slot to another.

Inventories are not limited to a certain number of slots. If desired, they can even grow or shrink at runtime. Therefore, inventories can be used whenever large quantities of items need to be stored, not only to represent a character’s backpack.

Characters and Equipment