Creating content from a text file.

The Pixie
This is kind of a proof of concept; I am not at all convinced it is a good idea, but it does show that you can load a file during play, and use that file to add to and change the game world. This example game has two rooms, with exits between them. If you use the UPDATE command, the file is loaded, adding a new room to the north, with exits to and from it, plus a few objects. The description of the first room is also updated.
<!--Saved by Quest 5.6.5621.18142-->
<asl version="550">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Files">
<gameid>c60b599f-eee2-4a05-85d5-50b35c7bb08b</gameid>
<version>1.0</version>
<firstpublished>2015</firstpublished>
<start type="script">
</start>
<publishfileextensions>*.jpg;*.jpeg;*.png;*.gif;*.js;*.wav;*.mp3;*.htm;*.html;*.svg;*.txt</publishfileextensions>
</game>
<object name="room">
<inherit name="editor_room" />
<description>The first room is white.</description>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="hat">
<inherit name="editor_object" />
<look>A top hat, like they use to wear back in the day.</look>
</object>
<exit alias="east" to="otherroom">
<inherit name="eastdirection" />
</exit>
</object>
<object name="otherroom">
<inherit name="editor_room" />
<description>This room looks very neat.</description>
<exit alias="west" to="room">
<inherit name="westdirection" />
</exit>
</object>
<command name="update">
<pattern>update</pattern>
<script>
LoadFile ("file.txt")
</script>
</command>
<type name="readable">
<inventoryverbs type="stringlist">
<value>Look at</value>
<value>Drop</value>
<value>Read</value>
</inventoryverbs>
</type>
<function name="LoadFile" parameters="filename">
s = GetFileData (filename)
current_object = null
foreach (line, Split(s, "\n")) {
line = Crop(line)
if (not line = "" and not StartsWith(line, "#")) {
bits = Split(line, "=")
if (StringListItem(bits, 0) = "new") {
if (ListCount(bits) = 2) {
create (StringListItem(bits, 1))
current_object = GetObject(StringListItem(bits, 1))
}
else {
create (StringListItem(bits, 2), StringListItem(bits, 1))
current_object = GetObject(StringListItem(bits, 2))
}
}
else if (StringListItem(bits, 0) = "find") {
current_object = GetObject(StringListItem(bits, 1))
if (current_object = null) {
error ("Failed to find " + StringListItem(bits, 1) + " in the game world. Things will go badly...")
}
}
else if (StringListItem(bits, 0) = "exit") {
create exit (StringListItem(bits, 2), null, null, null, StringListItem(bits, 1))
current_object = GetObject(StringListItem(bits, 2))
}
else if (StringListItem(bits, 0) = "parent") {
current_object.parent = GetObject(StringListItem(bits, 1))
if (current_object.parent = null) {
error ("Failed to find " + StringListItem(bits, 1) + " in the game world. Things will go badly...")
}
}
else if (StringListItem(bits, 0) = "to") {
current_object.to = GetObject(StringListItem(bits, 1))
if (current_object.to = null) {
error ("Failed to find " + StringListItem(bits, 1) + " in the game world. Things will go badly...")
}
}
else {
if (LCase(StringListItem(bits, 1)) = "false") {
set (current_object, StringListItem(bits, 0), false)
}
else if (LCase(StringListItem(bits, 1)) = "true") {
set (current_object, StringListItem(bits, 0), true)
}
else if (IsInt(StringListItem(bits, 1))) {
set (current_object, StringListItem(bits, 0), ToInt(StringListItem(bits, 1)))
}
set (current_object, StringListItem(bits, 0), StringListItem(bits, 1))
}
}
}
</function>
<function name="Crop" parameters="s" type="string"><![CDATA[
start = 1
end = LengthOf(s)
for (i, 1, LengthOf(s)) {
if (Asc(Mid(s, i, 1)) < 33) {
if (start = i) {
start = i + 1
}
}
else {
end = i
}
}
return (Mid(s, start, end - start + 1))
]]></function>
</asl>

Here is the file that is loaded. You will need to save it as "file.txt" in the same directory to get it to work.
new=teapot
alias=A teapot
parent=room
look=A blue teapot

new=bowtie
alias=A spotted bowtie
parent=room
look=Just a bowtie

# create a new room
new=secondroom
alias=A second room
description=This is the next room, it looks very new.

# Connect it with exits to and from
exit=northdirection=exittonorth
parent=room
to=secondroom

exit=southdirection=exittosouth
parent=secondroom
to=room

#Add an item to the room
#This is of the type "readable"
new=readable=newspaper
alias=An old news paper
look=The paper dates from 1967
parent=secondroom
read=You spend a few minutes catching up on the events of the 23rd of May, 1967.

#Now try to change the existing world
find=room
description=The first room is black.

About the data file format... This is something I devised to be relatively easy for Quest and humans to understand.

Blank lines (without even spaces) and lines starting with a hash are ignored

Use find= to find an existing object, to change an attribute. Use new= to create new objects and exit= to create new exits. For exits you must have the type of the exit, eg (where exittosouth is the name):
exit=southdirection=exittosouth
For objects you can set a type if you want, eg:
new=readable=newspaper
new=secondroom

The "parent" and "to" attributes are converted to objects. Any attribute set to "true" or "false" will be Boolean, and any set to a number will be an integer. Everything else will be a string. It should be possible to modify it to handle objects, string lists, object lists. I think it would be impossible to set a script this way however (you would have to set them up in advance with types or something).

It does some minor sanity testing, but nevertheless it is easy to make mistakes that are hard to track down, which is, I think, the big problem with the system. If you are going to make big changes to existing content, the opportunities for errors will multiply...

By the way, if you want to publish your game, you have to tell Quest to include .txt files by modifying the game.publishfileextensions attribute, as seen above.

lightwriter
OMG! This is magical, I take it we can borrow your code as long as proper credit is given.
However, I think this would be good for add-ons to Quest games like DLC...

The Pixie
I posted it here to get used. Do what you want with it.

For DLCs, I would have a DLc command that asks the player for the file name. You can upload a new version with an extra file, then tell the players to load the DLC. A mechanism to ensure it only happens once would be good (keep a string list of files loaded).

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

Support

Forums