null synonyms
billchelonis
03 May 2004, 10:01I saw in someone else's game sourcecode they used a null synonym. In other words, changing words like "of, to, the" to a blank string via synonyms.
i.e.
... I have found this doesn't really work too well though, and if you try it in the QDK editor itself vs. a text editor you'll find that QDK doesn't like that empty string, so here is my workaround for this. Setup a synonym for an actual word named "null" :
...and then write up a "beforeturn" script like this:
What happens is the script will loop through the quest.command every time it encounters the word "null" in the command, and wipes it out and re-runs the command until there are no "null" words. So this way you can really eliminate out some synonyms or parts of object aliases that used words like "of, the, to, on" etc. and simplify things.
Now, where this really comes in useful is in your custom commands because now you can make a custom command that has:
put #@mything# #@myotherthing#
instead of...
put #@mything# on #@myotherthing#
It wouldn't be a command syntax the player would necessarily be aware of, or even make much sense. What it does, though is simplify your code a little (internally and behind the scenes).
In the above example, I wrote a routine to put a rope over a wall, and aliased out everything so the command is really shortened to "put rope wall." Now for putting objects IN things, I probably will have a different command for that or allow the word "IN" to stay vs. nulling it out.
Anyhow just something I thought I'd share. Not sure if this is the best way to null out words you don't want, but it seems to work better than putting in an empty string synonym (at least since QDK doesn't seem to like those).
One thing to be careful of though. If you null out the word "on" then later want to have a "wear" command (i.e. put on clothes), the player's command of "put on jacket" changes to "put jacket" (which in some games means "drop jacket"). To avoid this you should probably add a synonym above the "null" synonym to change "put on" to "wear" :
If you do it in that order, it catches the "on" before it can nullify "on" and the player command for "put on jacket" is processed correctly.
The downside is if you wanted to allow the player to "put jacket on" then you're back to the old "put jacket" (i.e. "drop jacket" interpretation). However you could write up your own "put #@mything#" routine and query the player "Where do you wish to put #mything#?"
Of course in my code above I used the substring "null_" where the underscore means the code is looking for the word null with a space after it. So it would not nullify out the last null by itself at the end of a command. So you could have a custom command for "put #@mything# null" and have it execute the "wear @#mything#" command, and allow just "put #@mything#" to still act as a drop object command.
i.e.
define synonyms
on; the; of =
end define
... I have found this doesn't really work too well though, and if you try it in the QDK editor itself vs. a text editor you'll find that QDK doesn't like that empty string, so here is my workaround for this. Setup a synonym for an actual word named "null" :
define synonyms
on; the; of = null
end define
...and then write up a "beforeturn" script like this:
beforeturn {
if ( $instr(#quest.command#;null_)$ >= 1 ) then {
' REM see synonym NULL where on = NULL. this is for things like "put hook on rope" which changes to "put hook rope"
set string <substring; null_>
set numeric <p1; $instr(#quest.command#;#substring#)$>
dec <p1>
set string <s1; $left(#quest.command#;%p1%)$>
inc <p1; $lengthof(#substring#)$>
set string <s2; $mid(#quest.command#;%p1%)$>
set string <quest.command; #s1# #s2#>
set string <quest.originalcommand; #s1# #s2#>
' REM stop quest.command and then re-run it. otherwise the above work is no good
dontprocess
exec <#quest.command#>
}
}
What happens is the script will loop through the quest.command every time it encounters the word "null" in the command, and wipes it out and re-runs the command until there are no "null" words. So this way you can really eliminate out some synonyms or parts of object aliases that used words like "of, the, to, on" etc. and simplify things.
Now, where this really comes in useful is in your custom commands because now you can make a custom command that has:
put #@mything# #@myotherthing#
instead of...
put #@mything# on #@myotherthing#
It wouldn't be a command syntax the player would necessarily be aware of, or even make much sense. What it does, though is simplify your code a little (internally and behind the scenes).
In the above example, I wrote a routine to put a rope over a wall, and aliased out everything so the command is really shortened to "put rope wall." Now for putting objects IN things, I probably will have a different command for that or allow the word "IN" to stay vs. nulling it out.
Anyhow just something I thought I'd share. Not sure if this is the best way to null out words you don't want, but it seems to work better than putting in an empty string synonym (at least since QDK doesn't seem to like those).
One thing to be careful of though. If you null out the word "on" then later want to have a "wear" command (i.e. put on clothes), the player's command of "put on jacket" changes to "put jacket" (which in some games means "drop jacket"). To avoid this you should probably add a synonym above the "null" synonym to change "put on" to "wear" :
define synonyms
put on = wear
on; the; of = null
end define
If you do it in that order, it catches the "on" before it can nullify "on" and the player command for "put on jacket" is processed correctly.
The downside is if you wanted to allow the player to "put jacket on" then you're back to the old "put jacket" (i.e. "drop jacket" interpretation). However you could write up your own "put #@mything#" routine and query the player "Where do you wish to put #mything#?"
Of course in my code above I used the substring "null_" where the underscore means the code is looking for the word null with a space after it. So it would not nullify out the last null by itself at the end of a command. So you could have a custom command for "put #@mything# null" and have it execute the "wear @#mything#" command, and allow just "put #@mything#" to still act as a drop object command.
paul_one
23 May 2004, 04:18How would you diferentiate between under/over/in/beside/left/right/etc...
billchelonis
24 May 2004, 00:12Well, after experimenting with Quest's custom commands awhile I figured out other ways to do this. The example above was just for making a null word without getting a compiler error. I wasn't implying you'd make "on" null in all games. This was just an example.
I think the custom commands might need a bit more documentation though, because how do you know that you have to do the command syntax in this order:
climb over #@mything# with #@myotherthing#;climb #@mything# with #@myotherthing#;climb #@mything#
vs. a backwards order:
climb #@mything#;climb #@mything# with #@myotherthing#;climb over #@mything#
The backwards order example doesn't seem to work... it's like the game doesn't recognize some of the commands and only catches the first one. i.e. climb #@mything#
I didn't realize this at first and was using null words and aliases to change things like "climb over" to "climbover" or "climb over <something> with <somethingelse>" to just: climbover #@mything# #@myotherthing#
So in that workaround case some words like "on" were actually nulled out or replaced, but now I know you've got to write out the commands in a certain order (most complex to simplest).
I think the custom commands might need a bit more documentation though, because how do you know that you have to do the command syntax in this order:
climb over #@mything# with #@myotherthing#;climb #@mything# with #@myotherthing#;climb #@mything#
vs. a backwards order:
climb #@mything#;climb #@mything# with #@myotherthing#;climb over #@mything#
The backwards order example doesn't seem to work... it's like the game doesn't recognize some of the commands and only catches the first one. i.e. climb #@mything#
I didn't realize this at first and was using null words and aliases to change things like "climb over" to "climbover" or "climb over <something> with <somethingelse>" to just: climbover #@mything# #@myotherthing#
So in that workaround case some words like "on" were actually nulled out or replaced, but now I know you've got to write out the commands in a certain order (most complex to simplest).
Anonymous
24 May 2004, 10:03I think the 'null synonym' (making 'noise words' = a blank) was something I came up with for one of my early Quest libraries - at the time it worked well enough although I confess it wa hardly elegant 
As for the required sequencing of user commands, I think it makes most sense if you regard each component of a multi command (reading conventionally left to right) as an individual line to be processed in top to bottom order - Looked at in this way it becomes obvious which order the commands have to be in to work as required.
For example a command written like so:
command <climb #@thing#; climb over #@thing#> do <climbprocedure>
should be 'read' as being exactly equal to:
command <climb #@thing#> do <climbprocedure>
command <climb over #@thing#> do <climbprocedure>
then it becomes obvious why a player input of "climb over fence" won't work. Quest happily matches this to the first command and tries to interpret climb with the variable #thing# holding 'over fence' as if 'over fence' was an object... oops!
Doing them in reverse (correct) order it becomes:
command <climb over #@thing#; climb #@thing#> do <climbprocedure>
which should be 'read' as being exactly equal to:
command <climb over #@thing#> do <climbprocedure>
command <climb #@thing#> do <climbprocedure>
Now "climb over fence" matches the first command & so it will work properly. Inputting "climb fence" would not match the first command but be caught by the second command and therefor also work properly.
Basic rule of thumb is to do the specific stuff first, and have your basic catch all construct at the end. This 'filters' the command down until it finds a match if one is provided.
Al (MaDbRiT)
As for the required sequencing of user commands, I think it makes most sense if you regard each component of a multi command (reading conventionally left to right) as an individual line to be processed in top to bottom order - Looked at in this way it becomes obvious which order the commands have to be in to work as required.
For example a command written like so:
command <climb #@thing#; climb over #@thing#> do <climbprocedure>
should be 'read' as being exactly equal to:
command <climb #@thing#> do <climbprocedure>
command <climb over #@thing#> do <climbprocedure>
then it becomes obvious why a player input of "climb over fence" won't work. Quest happily matches this to the first command and tries to interpret climb with the variable #thing# holding 'over fence' as if 'over fence' was an object... oops!
Doing them in reverse (correct) order it becomes:
command <climb over #@thing#; climb #@thing#> do <climbprocedure>
which should be 'read' as being exactly equal to:
command <climb over #@thing#> do <climbprocedure>
command <climb #@thing#> do <climbprocedure>
Now "climb over fence" matches the first command & so it will work properly. Inputting "climb fence" would not match the first command but be caught by the second command and therefor also work properly.
Basic rule of thumb is to do the specific stuff first, and have your basic catch all construct at the end. This 'filters' the command down until it finds a match if one is provided.
Al (MaDbRiT)