================================ Tutorial: HERITAGE Game creation ================================ This page will guide you to creating a HERITAGE game. After completing this guide, you will have a basic game, which you can then tweak to your liking with the knowledge gained from following this guide. To start with following this documentation, create a text file named *main.heritage* using your favourite text editor. Please avoid using office applications such as LibreOffice, as these by default do not save plain text. They often can, but save yourself the headache and use a text editor like gedit. When choosing a text editor, please note that HERITAGE game engines are only required to support UNIX line endings. Therefore, it is good to make sure your text editor of choice supports UNIX line endings. Please also note that, although this guide will indent code, the indentation is not required to be a valid HERITAGE game file. We feel, however, that it greatly improves readability and want to promote it as a best practice. Okay, you have main.heritage file open in your favourite text editor? Time to start! Writing down information ------------------------ So, you're writing a cool new text adventure game in HERITAGE. Obviously, you want people to know you made it. HERITAGE info statements can contain any information you want, but you are recommended to add at least an author name, the name of the game, and some license information. We do this by adding the following lines to your game:: info(): title: Your game name author: Your name license: Your preferred license version: A version identifier Choosing a license is often hard. We recommend you to choose either the Creative Commons Zero 1.0 or the GNU GPLv3+ license. Whatever you choose, make sure to choose a GPL-compatible license, as the main parser is GPL-licensed. Licensing, however, falls out of the scope of this documentation. So, let's say your name is John Doe, the game you're creating is named "Super Cool Text Adventure Game" and the license is Creative Commons Zero 1.0. Your info statement will look like this:: info(): title: Super Cool Text Adventure Game author: John Doe license: Creative Commons Zero 1.0 version: 1 You can add as many additional fields to info() as you want, but it's up to engine in question how (and if) these are displayed. Creating a room --------------- HERITAGE games require at least one room to be present. Rooms are stored on a basic grid, and have an X, Y and Z coordinate. Each game starts off in a room with the X, Y and Z coordinate 0. So, let's say we want the player to start in a grassy field, where they can go north, with a tree. This would look as follows:: room(0.0.0): description: You are in a grassy field, surrounded by trees. items: tree exits: north That's it, your first room, with X.Y.Z coordinates 0.0.0! You may wonder how the game knows what happens when the player types ``go north``. The answer is simple: north is one Y position up from the current location, so the player will be moved to room 0.1.0 (the Y coordinate incremented by 1). HERITAGE understands the following exits: * east: Increments the X coordinate by 1 (1.0.0) * west: Decreases the X coordinate by 1 (-1.0.0) * north: Increments the Y coordinate by 1 (0.1.0) * south: Decreases the Y coordinate by 1 (0.-1.0) * up: Increments the Z coordinate by 1 (0.0.1) * down: Decreases the Z coordinate by 1 (0.0.-1) * northeast: Increments the X and Y coordinate by 1 (1.1.0) * northwest: Decreases the X coordinate by 1, increments the Y coordinate by 1 (-1.1.0) * southeast: Increments the X coordinate by 1, decreases the Y coordinate by 1 (1.-1.0) * southwest: Decreases the X and Y coordinate by 1 (-1.-1.0) It is possible to have more flexible exits than this. They can be called with more than one name, they can only work in certain cases, they can trigger specific actions, they can move to another location, or they can have another name than described above. This will be talked about in more detail later. For now, we are going to concentrate on the tree. Creating an item ---------------- So, we added a tree to the room, but how do we interact with it? Simple, we write a statement for the item. Say, we want the tree to look old and describe the leaves when the player shakes the tree. We do that as follows:: item(tree): on_examine: The tree looks rather old. on_shake: The leaves move slightly as you shake the tree... We have succesfully made some statements to be shown on the screen when the player types ``look at tree`` or ``shake tree`` when in the room the tree is at. For any other actions, such as ``cut down tree``, HERITAGE will display the text ``I do not know how to cut down tree``. We recommend you to always define ``on_examine``, because it sounds rather silly if the game tells you it does not know how to look at tree. If you want to allow players to take the item, make sure to put the following in the statement: ``allow_take: true``. They can then take the item by typing ``take itemname``, in this case, ``take tree``. Looking back: A very basic game ------------------------------- If you have been following the guide, you now have a very basic game, looking like this:: info(): title: Super Cool Text Adventure Game author: John Doe license: Creative Commons Zero 1.0 version: 1 room(0.0.0): description: You are in a grassy field, surrounded by trees. items: tree exits: north item(tree): on_examine: The tree looks rather old. on_shake: The leaves move slightly as you shake the tree... Obviously, this game is not yet complete. It's time to get into more advanced functionality of the HERITAGE format. We will be adding a key to the first room, add another room with a closed door to go north. For the key, we already know all we need to know, we add a statement for it:: item(key): on_examine: It's a key, it probably opens something. allow_take: true For the room, however... Inline Conditions ----------------- So, we want to add a key to the grassy field the player starts in, but only display text for it when the key is still on the ground, but not when the player has picked up the key. We will change the statement for room(0.0.0) to this:: room(0.0.0): description: You are in a grassy field, surrounded by trees. $(require_here:key;A key lies on the ground.)$ items: tree, key exits: north This probably looks weird, and may take a bit getting used to, but it is one of the most powerful features HERITAGE has to offer. They are called "Inline Conditions". An inline condition allows you to specify things which are only to be displayed or done in certain cases. In this case, we require the item "key" to be "here" (meaning: in this room), to display the text "A key lies on the ground". The following types of inline conditions exist: * require_location: Requires a (list of) items to be in a specific location. The first value in the list defines the location. Example: ``$(require_location:0.1.2,goblin;This text is only displayed if there is a goblin in a room with X.Y.Z coordinates 0.1.2)$`` * require_here: Requires a (list of) items to be in the current room. Example: ``$(require_here:key;This text in only displayed in there is a key in the current room)$`` * require_inventory: Requires a (list of) items to be in the user's inventory. Example: ``$(require_inventory:pen,paper;This text is only displayed if the items pen and paper are in the user`s inventory)$`` * equals: Requires a variable to equal a certain value. We will revisit variables later. Example: ``$(equals:test,1;This text is only displayed if the variable test equals one)$`` * less_than: Requires a variable to be less than a certain value. Example: ``$(less_than:test,3;This text is only displayed if the variable test is less than three)$`` * more_than: Requires a variable to be more than a certain value. Example: ``$(more_than:test,2;This text is only displayed if the variable text is more than two)$`` Special exits ------------- So, let's create a castle, with a door on the north in front of us. This will be a bit special, because we want the door to be locked normally:: room(0.1.0): description: You stand in front of a castle, a grassy field to your south, a door to the north. exits: south, north|castle.1 exit(1): fail: The door is locked. equals: door_opened,1 There are two meaningful things here, the exit list in the room, and the exit statement. Let's focus on them one at a time. ``north|castle.1`` is rather special, and it means the following: * There is an exit north, which is special exit number 1 * castle is a synonym for north, with special exit number 1 It is important to know that ``castle`` is the synonym, not ``north``. This allows the player to type ``go castle``, and it will move the player north, just like they would if they were to type ``go north``. However, because north is a special exit, HERITAGE will first make sure the conditions set for that exit (by ``exit(1)``) are all satisfied. If they are not, HERITAGE will display the text "The door is locked.". Otherwise, the player will be moved north. Variable Management and Actions ------------------------------- As you can see, we want to make sure the variable ``door_opened`` equals ``1``. That is all nice and dandy, but this means that we will need to learn variable management. Variable management consists of two parts: * Variable creation * Inline expressions First, we will create a variable:: var(door_opened,0) That's all we need to do to create a variable named ``door_opened`` with the value ``0``. HERITAGE supports number, names of other variables, or strings. Do note to put strings between "double quotes". Now, let's create an action to allow players to open the door. This action will required the key to be in the user's inventory, will make us lose it (we admit, losing the key makes no sense, but we don't want to clutter the user's inventory) and set the variable door_opened to 1, so that we can enter the castle:: action(open_door): succeed: The door opens.#(door_opened=1)# require_inventory: key lose: key So, if the player types ``open door``, and they have a key in their inventory, they will lose it, the text "The door opens" will be displayed on the screen, and the variable door_opened will be set to one. Instead of ``=``, we could have also used ``+`` or ``-`` to increment or decrease the value on the variable door_opened. Another interesting thing to notice is ``lose``, this makes the user lose an item. The following item management statements are supported: * lose: causes an item to disappear from the player inventory * gain: puts an item into the player inventory * drop: makes the player drop the item in the current room * disappear: causes the item to disappear from the current room Putting it together ------------------- We have learned a lot, and have created a fairly sophisticated game already. So far, this is our code:: info(): author: John Doe title: Super Cool Text Adventure Game license: Creative Commons Zero 1.0 version: 1 room(0.0.0): description: You are in a grassy field, surrounded by trees. $(require_here:key;A key lies on the ground.)$ items: tree, key exits: north item(tree): on_examine: The tree looks rather old. on_shake: The leaves move slightly as you shake the tree... item(key): on_examine: It's a key, it probably opens something. allow_take: true room(0.1.0): description: You stand in front of a castle, a grassy field to your south, a door to the north. exits: south, north|castle.1 exit(1): fail: The door is locked. equals: door_opened,1 action(open_door): succeed: The door opens.#(door_opened=1)# require_inventory: key lose: key var(door_opened,0) We can move the statements around as we wish, sort it in the way that makes it easiest for us to maintain the game. Now, let's finish the game. Finishing the game ------------------ So, the player has played our amazing game, and solved all our cool challenges, and now we want to end our game. To be more exact, we want the player to be eaten by a grue as they enter the castle. For that, we do create a new room for them to enter through the door we previously created:: room(0.2.0): first_enter: You are eaten by a grue. #(_game_over=1)# first_enter is a special statement, displayed only when the player first enters the room. We could have just used description here as well, as the user won't be able to enter the room again. By setting _game_over to 1, we tell HERITAGE that the game is over. It locks all input and ends the game, forcing the player to load a new game or restart. Our complete game ----------------- That's it, we have created a complete game in HERITAGE, and it looks like this:: info(): title: Super Cool Text Adventure Game author: John Doe license: Creative Commons Zero 1.0 version: 1 room(0.0.0): description: You are in a grassy field, surrounded by trees. $(require_here:key;A key lies on the ground.)$ items: tree, key exits: north item(tree): on_examine: The tree looks rather old. on_shake: The leaves move slightly as you shake the tree... item(key): on_examine: It's a key, it probably opens something. allow_take: true room(0.1.0): description: You stand in front of a castle, a grassy field to your south, a door to the north. exits: south, north|castle.1 exit(1): fail: The door is locked. equals: door_opened,1 action(open_door): succeed: The door opens.#(door_opened=1)# require_inventory: key lose: key var(door_opened,0) room(0.2.0): first_enter: You are eaten by a grue. #(_game_over=1)# There are some features we have not documented in this guide yet, these will be documented later. For now, please look at the example directory shipped with the engine, it contains an example game. All that rests now is to upload your game somewhere, so people can play it. For example, if you upload your game to ``http://example.com/mygame/main.heritage``, it can be loaded by typing ``load http://example.com/mygame``. Don't forget to name it main.heritage! Have fun, and create something cool!