How to make a text adventure look like a gamebook

The Pixie
This has come up on the forum a few times recently.

Why would you want to do that? Gamebooks have very limited functionality; in a text adventure you can do pretty much anything.


Concepts

Remember that a room is a page, and an exit is a link


Setting up

Go to the "game" object first, to set up some options. On the Interface tab, uncheck "Show panes", "Show command bar" and "Show location bar".

On the Room Descriptions tab, uncheck "Display commands entered by the player" and "Use "You are in" prefix". In the "Room description layout" section, set "Objects list" and "Room name" to zero, set "Description" to 2.

Right click in the left pane, and select "New template". Give it the name "GoListHeader" (no quotes, no spaces, same capitalisation). Then in the "Text" box, type "<br />Links:" (no quotes) (or your own text; the first bit adds a blank line, by the way).

First page

Go to the "room" object, and in the Room tab, type is the first page text in the Description box. On the Setup tab, you might want to change the name of the room, say to "first_page".


Second page

Right click in the left pane, and select "New room". Call it "second_page" or whatever, and add your text in the Description box on the Room tab again.


First link

Right click on your first page in the left pane, and select "New exit". In the "To" dropdown list, select the second page. In the "Alias" box, type in the link name (what the player will see).

Be aware that Quest will replace uppercase N, S, E, W, U, D, I and O with the lowercase as you type, but you can go back and change it back.



I want the links embedded in the text

Go to the "game" object, on the Room Descriptions tab, in the Room description layout section, set Exits list to zero.

Now on each page you will need to add the link yourself. The link might look like this:

You wonder if now you should {command:go to get dressed:dress yourself}.

The link part is inside the curly braces, and has three parts, divied by colons. The first part must be "command". You can quickly put this in your text by clicking the "Command link" button. The second part must be "go to " followed by the alias you have given the exit (capitalisation does not matter, but spaces do). The third part is the text the player actually sees.



I want page titles

Go to the "game" object, on the Room Descriptions tab, in the Room description layout section, set Room name to 1.

If you want punctuation in your page title, type the proper title in the "Alias", and a simple title in the "Name" box.

You will probably want to uncheck "Use default prefix and suffix" for each room, otherwise Quest will put "a" before each page title. If you are using the off-line editor, you could stop Quest doing that altogether. In the Tools menu, go to Code View. Scroll down to the bottom. The very last line is:

</asl> 


Add three extra lines, so that is now ends like this:

  <function name="GetDefaultPrefix" type="string" parameters="obj">
return ("")
</function>
</asl>


Go back to the Tools menu, and select Code View to go back to the normal view.


I want to clear the screen for each page

At the very bottom left, click on Filter, and select Show Library Elements. A whole load of new stuff, in grey, will appear in the left pane. Look for the go command, click it, then click "Copy" at the top right.

Some way down there is the word "Srcipt:" with some icons following it. Click the seventh icon, and everything below that will change into code, that looks like this:

if (exit.visible) {
if (exit.locked) {
msg (exit.lockmessage)
}
else if (exit.runscript) {
if (HasScript(exit, "script")) {
do (exit, "script")
}
}
else if (exit.lookonly) {
msg ("You can't go there.")
}
else {
game.pov.parent = exit.to
}
}
else {
msg ("You can't go there.")
}


Change it to this. The only different is a new line has been inserted about two thirds down, which says "ClearScreen". Make sure it is in the right place, right capitalisation.

if (exit.visible) {
if (exit.locked) {
msg (exit.lockmessage)
}
else if (exit.runscript) {
if (HasScript(exit, "script")) {
do (exit, "script")
}
}
else if (exit.lookonly) {
msg ("You can't go there.")
}
else {
ClearScreen
game.pov.parent = exit.to
}
}
else {
msg ("You can't go there.")
}


Click that seventh icon again, and the code will be replaced by GUI stuff. If you see red code, there is a mistake somewhere!

Click on Filter again, and deselect Show Library Elements


A brief example

This example shows some of these ideas at work. The take a shower page has links embedded in the text. Some links set flags, so when you go to breakfast people will comment appropriate to what you have done.

To see it in the off-line editor, create a new game, go to Tools - Code view, delete everything, and paste this in instead. Go to Tools - Code view again.

<!--Saved by Quest 5.5.5328.26617-->
<asl version="550">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<template name="GoListHeader"><![CDATA[<br/>Links:]]></template>
<game name="Making a text game look like a gamebook">
<gameid>a0d4b06b-2264-428a-bd5d-49c4c30a15f6</gameid>
<version>1.0</version>
<firstpublished>2014</firstpublished>
<author>The Pixie</author>
<enablehyperlinks />
<showlocation type="boolean">false</showlocation>
<showcommandbar type="boolean">false</showcommandbar>
<showborder />
<autodescription />
<echocommand />
<autodisplayverbs />
<attr name="autodescription_description" type="int">2</attr>
<attr name="autodescription_youarein" type="int">1</attr>
<attr name="autodescription_youcansee" type="int">0</attr>
<attr name="autodescription_youarein_useprefix" type="boolean">false</attr>
<showpanes type="boolean">false</showpanes>
<start type="script">
</start>
<roomenter type="script">
</roomenter>
</game>
<command name="go">
<pattern type="string"><![CDATA[^go to (?<exit>.*)$|^go (?<exit>.*)$|^(?<exit>north|east|south|west|northeast|northwest|southeast|southwest|in|out|up|down|n|e|s|w|ne|nw|se|sw|o|u|d)$]]></pattern>
<unresolved>You can't go there.</unresolved>
<script>
if (exit.visible) {
if (exit.locked) {
msg (exit.lockmessage)
}
else if (exit.runscript) {
if (HasScript(exit, "script")) {
do (exit, "script")
}
}
else if (exit.lookonly) {
msg ("You can't go there.")
}
else {
ClearScreen
game.pov.parent = exit.to
}
}
else {
msg ("You can't go there.")
}
</script>
</command>
<object name="room">
<inherit name="editor_room" />
<description>You wake up and sunlight is stream in the window. It is a fine day.</description>
<alias>Waking up</alias>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
<dressed type="boolean">false</dressed>
<showered type="boolean">false</showered>
<snoozecount type="int">0</snoozecount>
</object>
<exit alias="Take a shower" to="take_a_shower" />
<exit alias="Get dressed" to="get_dressed" />
<exit alias="Have breakfast" to="have_breakfast" />
<exit alias="Press snooze" to="snooze" />
</object>
<object name="take_a_shower">
<inherit name="editor_room" />
<description>A brisk shower is just what you need to wake you up. Now do you {command:go to get dressed:dressed yourself} or {command:got to have breakfast:get some breakfast}?</description>
<alias>Take a shower</alias>
<firstenter type="script">
player.showered = true
</firstenter>
<exit alias="Get dressed" to="get_dressed" />
<exit alias="Have breakfast" to="have_breakfast" />
</object>
<object name="snooze">
<inherit name="editor_room" />
<description>It is too earlier! you press snooze on the alarm and go back to sleep.</description>
<enter type="script">
player.snoozecount = player.snoozecount + 1
</enter>
<exit alias="Wake" to="room" />
</object>
<object name="get_dressed">
<inherit name="editor_room" />
<description>You quickly put on some random clothes</description>
<alias>Get dressed</alias>
<firstenter type="script">
player.dressed = true
</firstenter>
<exit alias="Have breakfast" to="have_breakfast" />
</object>
<object name="have_breakfast">
<inherit name="editor_room" />
<alias>Breakfast</alias>
<description type="script"><![CDATA[
msg ("You head down to breakfast.")
if (not player.dressed) {
msg ("'Why are you naked?' says Ben.")
}
if (not player.showered) {
msg ("Linda sniffs the air. 'Have you had a shower?' she asks doubtfully.")
}
if (player.snoozecount > 5) {
msg ("'You should've been down more than an hour ago,' says Pat.")
}
else if (player.snoozecount > 1) {
msg ("'Here at last,' says Pat.")
}
else {
msg ("'Good to see you're prompt,' says Pat.")
}
]]></description>
</object>
<function name="GetDefaultPrefix" parameters="obj" type="string">
return ("")
</function>
</asl>

chrisw70
I tried the brief example here and get this error when I attempt to play it...

Failed to load game.
The following errors occurred:
Invalid XML: ReadElementContentAs() methods cannot be called on an element that has child elements. Line 5, position 35.

Any idea why it's not running for me? Great tutorial if I could get it to work.

Pertex
It should work if you remove <br /> from line 5 "<template name="GoListHeader"><br />Links:</template>"

The Pixie
Sorry, my bad. I have updated, so it should work now.

chrisw70
Thank you, works great!

adrao
Hi Pixie...

I have started to play around with your RPG code, and I sort of wanted to make a hybrid gamebook/text game (making sure that it is easy for the player to move around through links, while giving some options to interact). Anyway, I am getting stuck on how to create a link. Essentially I opened your CombatDemo file and started to create a couple of pages in a city, and tried to link them as you suggested, but although I can use the map to go east, if I click on the link it tells me "You can't go there"... I thought I followed your instructions but I am still not too familiar with how Quest works... probably I am doing something wrong?

<object name="A0_Main_Square">
<inherit name="editor_room" />
<description><![CDATA[The Main Square of the city is a very busy area, with many citizens constantly coming and going. <br/><br/>There are a number of exits to the square. To the east you can go to {command: go to A0_Castle_street: Castle Street}, which leads to the main entrance of the city's citadel, where the lord of the city resides. <br/>]]></description>
<alias>A0_Main_Square</alias>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<exit alias="east" to="A0_Castle_Street">
<inherit name="eastdirection" />
</exit>
<object name="player">
<inherit name="defaultplayer" />
<maxpoints type="int">6</maxpoints>
<gold type="int">50</gold>
</object>
</object>
<object name="A0_Castle_Street">
<inherit name="editor_room" />
<alias>A0_Castle_Street</alias>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<exit alias="west" to="A0_Main_Square">
<inherit name="westdirection" />
</exit>
</object>

jaynabonne
You need to set the alias for the exit in order for "go to" to be able to find it.

adrao
I tried that, but still it does not work... same problem...

</object>
<object name="A0_Main_Square">
<inherit name="editor_room" />
<description><![CDATA[The Main Square of the city is a very busy area, with many citizens constantly coming and going. <br/><br/>There are a number of exits to the square. To the east you can go to {command: go to Castle Street: Castle Street}, which leads to the main entrance of the city's citadel, where the lord of the city resides. <br/>]]></description>
<alias>Main Square</alias>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<exit alias="east" to="A0_Castle_Street">
<inherit name="eastdirection" />
</exit>
<object name="player">
<inherit name="defaultplayer" />
<maxpoints type="int">6</maxpoints>
<gold type="int">50</gold>
</object>
</object>
<object name="A0_Castle_Street">
<inherit name="editor_room" />
<alias>Castle Street</alias>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<exit alias="west" to="A0_Main_Square">
<inherit name="westdirection" />
</exit>

The Pixie
Change the alias on the exits:

<exit alias="Castle Street" to="A0_Castle_Street">
<inherit name="eastdirection" />
</exit>

<exit alias="Main square" to="A0_Main_Square">
<inherit name="westdirection" />
</exit>

adrao
Ok cheers that worked!!

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums