A flexible, C++ based, engine for creating text-based adventures and RGP games. Featuring customizable character creation, inventory and storage systems, turn-based combat, save/load functionality and more. Games are configured using JSON files.
You can easily run the Adventure Engine using the provided Makefile.
Running make will generate both the engine executable, and documentation.
Alternatively, you can do these steps independently:
- Navigate to the root project directory.
- Run the following:
This will generate the
make compile
run-adventure-engineexecutable. - To start a game, execute the following command, replacing
<game_name>with the desired game:For example, to run the included example games:./run-adventure-engine <game_name>
Alternatively,./run-adventure-engine exampleGame ./run-adventure-engine exampleGameSK
make runcan also be used to run the engine, if the executable is present.
You can generate a full HTML documentation of the project using Doxygen by running:
make docThe generated documentation will be available in the doc directory, with the index.html file being its root.
When the player starts a game made in Adventure Engine, they first make choices that will affect their character.
Firstly, the game displays information about the possible types of the main character. The player then chooses one. For example "warrior" or "intellectual".
Secondly, the game shows a list of attributes. Each of them is set to 100% by default. However, the player then has a chance to increase these values by N percentage points. For example, in a game with N=20 and three attributes - health, power, intelligence - the player could choose values 110%, 104%, 106%.
When the player performs an action in the game, the game can respond differently to the same action depending on the player's attributes. If the player meets the required attributes the game prints the main text response, otherwise it prints an alternative one. Attributes are influenced by both the player's choice of the percentages and by the chosen Type.
The main character has an inventory. It is implemented as a set of Storage objects. Besides the standard "Main character storage" (their hands, pockets), the InventoryStorage can contain "External storages" like bags, backpacks etc. The game also includes Room Storages - one for each room - these are unrelated to InventoryStorage.
Each Storage has a limited capacity. The player can take and remove items from/to InventoryStorage.
The engine features non-playable characters and a combat system. If an NPC is "fightable", then the player can attack it. The player can have Objects in their two hands. If an object is a weapon and it's in a hand, it can be used for combat.
The weapon (or no weapon) that will be used for the combat is determined by the engine once the player wants to start combat. It calculates the power of the possible weapon in the left/right hand and the power of using no weapon, and then chooses the most effective option.
The player can add or remove objects from their two hands before combat to get ready, however (Currently not implemented.)
The player can both save the game and load a save-file. The engine currently supports the saving/loading of:
- the current room
- the Main Character's attributes values
- the Main Character's Type
The game creator creates a game using JSON configuration files.
Each game is in a separate directory in ./example. Each game's root directory must include:
- 3
.jsonfiles:commands.jsontypes-and-attributes.jsongame-setup.json
- and 4 subdirectories:
/events,/rooms,/inventory,/saves
The game creator can get inspired by the working example games in the ./example directory. The keys and values must follow the same syntax as these example files. The key strings contain hints and explanations on how they work.
The engine is not limited to supporting only the English language. Games can be created in any language – see exampleGameSK for a game in Slovak.
Storageis the parent class of:- Main Character
Storage - External
Storage RoomStorage
- Main Character
GameEntityis the parent class of:GameObjectMainCharacterNPC
- One of the most important containers of this project is the map called "entities" in
Gameclass.std::unordered_map<std::string, std::shared_ptr<GameEntity>> entities- it maps names and synonym names (
std::string) toGameEntityobjects. Gameclass further includes methods for manipulation with the map:std::shared_ptr<GameEntity> Game::findEntity(const std::string& noun) constbool Game::addNamesToEntityMap(const std::vector<std::string>& names, GameEntity& entity)void Game::removeEntityFromMap(GameEntity& entityToBeRemoved)
InventoryStoragecontains Storages (oneInventoryStorageand O...N ExternalStorages)- Its methods using Polymorphism, therefore using the
Storageclass include:bool addExternalStorage(Storage& storage);bool removeStorage(const Storage& storage);bool addObject(std::shared_ptr<GameObject> object, Storage& storage);bool removeOneObject(std::shared_ptr<GameObject> object, Storage& storage);bool removeAllObjects(std::shared_ptr<GameObject> object, Storage& storage);const std::vector<std::unique_ptr<ExternalStorage>>& getExternalStorages() const;
- Its methods using Polymorphism, therefore using the
- Finding out how many (if any) instances of an entity are in
Storageuses polymorphism:unsigned int getEntityCount(const GameEntity& object) const- This method gets called when the player enters the Verb/Noun pair. At that point we don't know what type of
GameEntitythe Noun could refer to, so theGameEntityparent class is used in the method.
