Reading from a file

Richard Headkid
30 Nov 2017, 21:28Let's say you want Quest to read the information from a file in the game's folder.
I created a file named README.txt.
The contents:
Hello, Quest!The game's code:
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Read from a file">
<gameid>0872edb9-52ea-4bfb-ab02-79fead46bb02</gameid>
<version>1.0</version>
<firstpublished>2017</firstpublished>
</game>
<object name="room">
<inherit name="editor_room" />
<description type="script">
msg (GetFileData("README.txt"))
</description>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
</object>
</asl>
The output:
Now, I'll change the contents of the file to this:
Hello, Quest!<h1>THIS IS A HEADER!</h1>
NOTE: I don't think Quest can read a file from the hard drive that isn't in the game's folder. I am experimenting with that next, but it seems like I've read a post by Pixie saying that exact thing. (I think it concerned the Save/Load system.)
The Pixie
30 Nov 2017, 21:41I am not sure if you can read from another directory or not, but just don't!
When you publish the game Quest will only include files in the current folder (actually, library files from elsewhere will be included).
Also, it will only include games with specific file extensions (or rather, that match specific patterns). You can modify game.publishfileextensions
to include your .txt file, but by default it will not be included.

Richard Headkid
30 Nov 2017, 21:55I am not sure if you can read from another directory or not, but just don't!
Boom. Sage advice.
(It didn't work anyway, kids. )
Also, it will only include games with specific file extensions (or rather, that match specific patterns). You can modify game.publishfileextensions to include your .txt file, but by default it will not be included.
Good looking out!
This is what Quest includes by default:
<publishfileextensions>*.jpg;*.jpeg;*.png;*.gif;*.js;*.wav;*.mp3;*.htm;*.html;*.svg </publishfileextensions>
NOTE:
I just renamed README.txt as README.html, and everything works just the same. (It's just reading the text. If there's HTML code, it will be displayed as coded. If not, it will display plain text.)
msg (GetFileData("README.html"))
Now, I wonder if it can read from an online file...
(It seems like the answer is no, but I'm bored. Be right back.)

DarkLizerd
01 Dec 2017, 03:13Nice!!!
I assume there is a way to read the file info into a variable, like "result", then process that for needed info...
I'm thinking of a game where by completing several "missions" you get promotions for new ships (space based) and accedd for new missions...
GetFileData() should have a counter command PutFileData()...

K.V.
01 Dec 2017, 04:02Heck yeah, there is. (It's in Pixie's Quest, too. I'll go find it. Be right back.)

K.V.
01 Dec 2017, 04:07Here you go:
http://textadventures.co.uk/forum/quest/topic/np4q-x6_je_uw_aqk27zpq/creating-content-from-a-text-file-im-bringing-it-back

K.V.
01 Dec 2017, 04:16 <function name="LoadFile" parameters="filename">
s = GetFileData (filename)
current_object = null
game.setUp = false
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") {
newParent = StringListItem(bits, 1)
if (newParent = "game.pov") {
current_object.parent = game.pov.name
game.setUp = true
list remove (bits, "game.pov")
list add (bits, game.pov.name)
}
else if (newParent = "game.pov.parent") {
current_object.parent = game.pov.parent.name
game.setUp = true
list remove (bits, "game.pov.parent")
list add (bits, game.pov.parent.name)
}
else if (newParent = "here") {
current_object.parent = game.pov.parent.name
game.setUp = true
list remove (bits, "here")
list add (bits, game.pov.parent.name)
}
else if (newParent = "player.parent") {
current_object.parent = player.parent.name
game.setUp = true
list remove (bits, "player.parent")
list add (bits, player.parent.name)
}
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)))
}
if (not game.setUp) {
set (current_object, StringListItem(bits, 0), StringListItem(bits, 1))
}
else {
set (current_object, StringListItem(bits, 0), game.pov)
}
}
}
}
msg ("Done.")
</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>
<command name="px_update">
<pattern>load #text#</pattern>
<script>
LoadFile (text)
</script>
</command>

K.V.
01 Dec 2017, 04:19You can load a file like this example.
find=
just finds an existing object you want to change attributes on.
new=
creates a new object, of course.
Everything else should be familiar.
Pixie created all this, by the way. I just added a couple of tweaks to his code.
new=kv_special_item_1
alias=black shard of ∞
look=It's the black shard, which is the most powerful of them all!
parent=game.pov
find=kv_green_shard
parent=game.pov
new=thingy
parent=game.pov.parent
new=anotherThing
parent=player.parent
new=thing3
parent=here

K.V.
01 Dec 2017, 05:38GetFileData() should have a counter command PutFileData()
I can build you a version of Quest where Log doesn't print the date and time at the beginning of each entry.
You could then just use Log("whatever you want to save on a line to the .txt file") in place of PutFileData().
(I can do that. I'll damned if I can figure out how to call a function that Quest can't already call, though. I've been trying to figure out how to make it so I can call the Restart function forever!)