How to get very specific responses for unresolved objects?
Mareus
06 Jun 2014, 13:15I just tried playing The Hitchhikers Guide to the Galaxy and I was impressed at very specific responses one gets for unresolved objects. Look at these 3 examples:
If I write something that does not make sense like PICK UP HOUSE, I get a response: Nice try.
If I write PICK UP SHIT, I get a response: I don't know the word "shit".
If I write SMELL SOUTH, I get a response: You used the word "south" in a way that I don't understand.
So it looks like the author made a code which literally understands the difference between unknown words that do not exist in the game, and ones that do. How does one do that?
PS. I have managed to find a command "UnresolvedObject", and when I type in "I don't know the word" I get a response: I don't know the word (shit) - which is fine btw, but how do I then achieve the response: "You used the word "south" in a way that I don't understand." Can somebody please decipher the code and tell me which things to change in the hidden library to what to be able to achieve the same result as from The Hitchhikers Guide to the Galaxy game? That guy must have been an amazing coder.
If I write something that does not make sense like PICK UP HOUSE, I get a response: Nice try.
If I write PICK UP SHIT, I get a response: I don't know the word "shit".
If I write SMELL SOUTH, I get a response: You used the word "south" in a way that I don't understand.
So it looks like the author made a code which literally understands the difference between unknown words that do not exist in the game, and ones that do. How does one do that?
PS. I have managed to find a command "UnresolvedObject", and when I type in "I don't know the word" I get a response: I don't know the word (shit) - which is fine btw, but how do I then achieve the response: "You used the word "south" in a way that I don't understand." Can somebody please decipher the code and tell me which things to change in the hidden library to what to be able to achieve the same result as from The Hitchhikers Guide to the Galaxy game? That guy must have been an amazing coder.

jaynabonne
06 Jun 2014, 13:37Well, basically, they're completely different parsers with different strategies. I don't think there's a simple solution for what you want (but who knows - I haven't looked totally yet!).
The Quest parser handles an "unresolved object" with something like "I don't see that." The reason why is that the parser makes no distinction between an object (or word for an object) that doesn't exist at all vs one which just doesn't happen to be in the current scope. I suspect that you want it where, if you have an apple in the game but not a banana, if you're in an empty room and type "x apple", it will say, "I can't see that." whereas if you type "x banana", it will response with "I don't know the word 'banana'." You could probably code for that contingency by trying to do a match on all the objects in the game to see if there is one that satisfies the text, but Quest was not coded for that. Though, upon further thought, that won't work either, as you could type "take eat", and it would not find an object called "eat" and so say it doesn't know the word, when it does - as a verb. So then you have to search through all the verbs and commands as well, and all the exits names, and... It's just not made to do that. If you designed it to do that, it would be easier to code.
Quest is based on pattern matching, not on knowing what various words mean. I think to get the responses you list, you'd have to change the fundamental way the parser is put together, unless you want to create numerous hacks. It's an interesting problem, and I'll think about it some more, but it might not be as easy a change as some others have been!
The Quest parser handles an "unresolved object" with something like "I don't see that." The reason why is that the parser makes no distinction between an object (or word for an object) that doesn't exist at all vs one which just doesn't happen to be in the current scope. I suspect that you want it where, if you have an apple in the game but not a banana, if you're in an empty room and type "x apple", it will say, "I can't see that." whereas if you type "x banana", it will response with "I don't know the word 'banana'." You could probably code for that contingency by trying to do a match on all the objects in the game to see if there is one that satisfies the text, but Quest was not coded for that. Though, upon further thought, that won't work either, as you could type "take eat", and it would not find an object called "eat" and so say it doesn't know the word, when it does - as a verb. So then you have to search through all the verbs and commands as well, and all the exits names, and... It's just not made to do that. If you designed it to do that, it would be easier to code.
Quest is based on pattern matching, not on knowing what various words mean. I think to get the responses you list, you'd have to change the fundamental way the parser is put together, unless you want to create numerous hacks. It's an interesting problem, and I'll think about it some more, but it might not be as easy a change as some others have been!
Mareus
06 Jun 2014, 13:44jaynabonne wrote:Well, basically, they're completely different parsers with different strategies. I don't think there's a simple solution for what you want (but who knows - I haven't looked totally yet!).
The Quest parser handles an "unresolved object" with something like "I don't see that." The reason why is that the parser makes no distinction between an object (or word for an object) that doesn't exist at all vs one which just doesn't happen to be in the current scope. I suspect that you want it where, if you have an apple in the game but not a banana, if you're in an empty room and type "x apple", it will say, "I can't see that." whereas if you type "x banana", it will response with "I don't know the word 'banana'." You could probably code for that contingency by trying to do a match on all the objects in the game to see if there is one that satisfies the text, but Quest was not coded for that.
Quest is based on pattern matching, not on knowing what various words mean. I think to get the responses you list, you'd have to change the fundamental way the parser is put together, unless you want to create numerous hacks. It's an interesting problem, and I'll think about it some more, but it might not be as easy a change as some others have been!
Ok, what about a compromise solution then? How do I make it so that the (word) appears in the middle of the text and not at the end? This would allow me to form the sentence which is more universal to various situations. For example I want the unresolved response to be: You used the word (X) in a way that I don't understand. Or another universal response could be: I don't know how to use the word (X) in such a way.
PS. I also noticed that the author from the game I mentioned uses words that are directly taken from the text I write and problematic words are marked behind "". Whereas mine are in (). The problem is that sometimes I get a response: I do not know the word (X) and sometimes just I do not know the word
So it looks like the word is missing and I don't know why.

jaynabonne
06 Jun 2014, 18:56This function is where it is printed:
What you can do (untested!) is to replace the code I have delimited by comments with this:
There is no way to do it without hacking the code. To do that, either paste the above code into your game and modify it, or you can check "Show Library Elements" under "Filter" at the bottom left and then find the function "UnresolvedCommand" and copy it into your game using the button at the top right. Then you can modify it.
[Relatively unimportant note: if you got the message "I don't know the word (s***)", then (if I read the code right), it was in a context where there was more than one object, and it printed out the object name to disambiguate. If you replace as I said above, it will cover both cases, but I was wondering what you had typed to get that. Normally it just prints the text without th word in question. But don't worry about that too much. It's not that important to me. lol]
<function name="UnresolvedCommand" parameters="objectname, varname">
// TO DO: Update names below, we don't need these two variables
unresolvedobject = objectname
unresolvedkey = varname
if (HasString(game.pov.currentcommandpattern, "unresolved")) {
if (ListCount(game.pov.currentcommandvarlist) > 1) {
msg (game.pov.currentcommandpattern.unresolved + " (" + unresolvedobject + ")")
}
else {
msg (game.pov.currentcommandpattern.unresolved)
}
}
else {
// Start replacing here.
if (ListCount(game.pov.currentcommandvarlist) > 1) {
msg (Template("UnresolvedObject") + " (" + unresolvedobject + ")")
}
else {
msg (Template("UnresolvedObject"))
}
// End replacing here.
}
game.unresolvedcommand = game.pov.currentcommandpattern
game.unresolvedcommandvarlist = game.pov.currentcommandvarlist
game.unresolvedcommandkey = unresolvedkey
</function>
What you can do (untested!) is to replace the code I have delimited by comments with this:
msg("You used the word " + unresolvedobject + " in a way I didn't understand.")
There is no way to do it without hacking the code. To do that, either paste the above code into your game and modify it, or you can check "Show Library Elements" under "Filter" at the bottom left and then find the function "UnresolvedCommand" and copy it into your game using the button at the top right. Then you can modify it.
[Relatively unimportant note: if you got the message "I don't know the word (s***)", then (if I read the code right), it was in a context where there was more than one object, and it printed out the object name to disambiguate. If you replace as I said above, it will cover both cases, but I was wondering what you had typed to get that. Normally it just prints the text without th word in question. But don't worry about that too much. It's not that important to me. lol]
HegemonKhan
06 Jun 2014, 20:00I'll leave Jay to help you with unresolved responses, as he knows more of how quest's core coding works than I do, but I'll offer this help as well (Credit to Pertex for this stuff):
you can use parameters, so you can then place the variable, ' Attribute (Object.Attribute) ', where you want into the text message, ' print message [EXPRESSION] '
also, when you check text, you have the issues of:
1. does the Object even exist (regardless of #2 and #3 below) ?
2. does the Object's 'NAME (ID)' Attribute match up with what is the typed-in (during game play by an user) input ?
3. does the Object's 'ALIAS' Attribute match up with what is the typed-in (during game play by an user) input ?
an explanation:
typed-in input during game play: HK
<object name="player">
-> <alias>HK</object>
</object>
quest: " is there an Object.Name = HK, ??? ", Answer: No, therefore ( <command>#text# or #object#</command> or ' get input ' Script) the: Variable = null
you would have to type-in ' player ', for it to work.
however, you can get it to work, via these checks, and check-matching-up all the object's (in the entire game) ALIAS with whether one of them matches up with your typed-in input, as example'd below:
for an example:
<command name="fight_command">
-> <pattern>fight #text#</pattern>
-> <script>
->-> fight_function (game.pov,text)
-> </script
</command>
// game.pov -> self // (game.pov = self)
// text -> text_x // (text = text_x)
<function name="fight_function" parameters="self,text_x">
-> enemy = GetObject (text_x)
-> if (enemy = null) {
->-> foreach (object_x, AllObjects () ) {
->->-> if (object_x.alias = text_x) {
->->->-> enemy = object_x
->->-> }
->-> }
-> }
-> if (enemy = null) {
->-> msg ("Bad input, try again.")
-> } else if (not enemy = null) {
->-> battle_function (self, enemy)
-> }
</function>
// self -> self // (self = self)
// enemy -> enemy // (enemy = enemy)
<function name="battle_function" parameters="self,enemy">
-> you_go_first_variable = false
-> if (self.speed_integer > enemy.speed_integer) {
->-> you_go_first_variable = true
-> } else if (self.speed_integer = enemy.speed_integer) {
->-> if (RandomChance (50) = true) {
->->-> you_go_first_variable = true
->-> }
-> }
-> if (you_go_first_variable = false) {
->-> enemy_battle_turn_function (self, enemy)
-> } else if (you_go_first_variable = true) {
->-> self_battle_turn_function (self, enemy)
-> }
</function>
// self -> self // (self = self)
// enemy -> enemy // (enemy = enemy)
<function name="self_battle_function" parameters="self, enemy">
-> // scripts
</function>
<function name="enemy_battle_function" parameters="self, enemy">
-> // scripts
</function>
you can use parameters, so you can then place the variable, ' Attribute (Object.Attribute) ', where you want into the text message, ' print message [EXPRESSION] '
also, when you check text, you have the issues of:
1. does the Object even exist (regardless of #2 and #3 below) ?
2. does the Object's 'NAME (ID)' Attribute match up with what is the typed-in (during game play by an user) input ?
3. does the Object's 'ALIAS' Attribute match up with what is the typed-in (during game play by an user) input ?
an explanation:
typed-in input during game play: HK
<object name="player">
-> <alias>HK</object>
</object>
quest: " is there an Object.Name = HK, ??? ", Answer: No, therefore ( <command>#text# or #object#</command> or ' get input ' Script) the: Variable = null
you would have to type-in ' player ', for it to work.
however, you can get it to work, via these checks, and check-matching-up all the object's (in the entire game) ALIAS with whether one of them matches up with your typed-in input, as example'd below:
for an example:
<command name="fight_command">
-> <pattern>fight #text#</pattern>
-> <script>
->-> fight_function (game.pov,text)
-> </script
</command>
// game.pov -> self // (game.pov = self)
// text -> text_x // (text = text_x)
<function name="fight_function" parameters="self,text_x">
-> enemy = GetObject (text_x)
-> if (enemy = null) {
->-> foreach (object_x, AllObjects () ) {
->->-> if (object_x.alias = text_x) {
->->->-> enemy = object_x
->->-> }
->-> }
-> }
-> if (enemy = null) {
->-> msg ("Bad input, try again.")
-> } else if (not enemy = null) {
->-> battle_function (self, enemy)
-> }
</function>
// self -> self // (self = self)
// enemy -> enemy // (enemy = enemy)
<function name="battle_function" parameters="self,enemy">
-> you_go_first_variable = false
-> if (self.speed_integer > enemy.speed_integer) {
->-> you_go_first_variable = true
-> } else if (self.speed_integer = enemy.speed_integer) {
->-> if (RandomChance (50) = true) {
->->-> you_go_first_variable = true
->-> }
-> }
-> if (you_go_first_variable = false) {
->-> enemy_battle_turn_function (self, enemy)
-> } else if (you_go_first_variable = true) {
->-> self_battle_turn_function (self, enemy)
-> }
</function>
// self -> self // (self = self)
// enemy -> enemy // (enemy = enemy)
<function name="self_battle_function" parameters="self, enemy">
-> // scripts
</function>
<function name="enemy_battle_function" parameters="self, enemy">
-> // scripts
</function>

jaynabonne
06 Jun 2014, 20:07HK, did you respond to the wrong thread?
Mareus
06 Jun 2014, 20:16jaynabonne wrote:This function is where it is printed:<function name="UnresolvedCommand" parameters="objectname, varname">
// TO DO: Update names below, we don't need these two variables
unresolvedobject = objectname
unresolvedkey = varname
if (HasString(game.pov.currentcommandpattern, "unresolved")) {
if (ListCount(game.pov.currentcommandvarlist) > 1) {
msg (game.pov.currentcommandpattern.unresolved + " (" + unresolvedobject + ")")
}
else {
msg (game.pov.currentcommandpattern.unresolved)
}
}
else {
// Start replacing here.
if (ListCount(game.pov.currentcommandvarlist) > 1) {
msg (Template("UnresolvedObject") + " (" + unresolvedobject + ")")
}
else {
msg (Template("UnresolvedObject"))
}
// End replacing here.
}
game.unresolvedcommand = game.pov.currentcommandpattern
game.unresolvedcommandvarlist = game.pov.currentcommandvarlist
game.unresolvedcommandkey = unresolvedkey
</function>
What you can do (untested!) is to replace the code I have delimited by comments with this:msg("You used the word " + unresolvedobject + " in a way I didn't understand.")
There is no way to do it without hacking the code. To do that, either paste the above code into your game and modify it, or you can check "Show Library Elements" under "Filter" at the bottom left and then find the function "UnresolvedCommand" and copy it into your game using the button at the top right. Then you can modify it.
[Relatively unimportant note: if you got the message "I don't know the word (s***)", then (if I read the code right), it was in a context where there was more than one object, and it printed out the object name to disambiguate. If you replace as I said above, it will cover both cases, but I was wondering what you had typed to get that. Normally it just prints the text without th word in question. But don't worry about that too much. It's not that important to me. lol]
Thanks for this, but I don't want to mess up the coding. This just feels a bit more than I can handle atm, since I don't really understand the instructions on how to do what you are suggesting. I'll just use the response: "I don't understand your command. Try rephrasing.", and sometimes I will get the unresolved object in the the () and sometimes not. Its not ideal, but it works from the testing I've done. The only thing that bothers me is the "full stop" before (unresolved object) - and if I erase the full stop, then when the (unresolved object) doesn't show up, then the full stop is missing. Still, its small issue really.
HegemonKhan
06 Jun 2014, 20:20No. I responded correctly to this thread.
I was added in the coding that you suggested might be needed on top of unsolved responses:
"I suspect that you want it where, if you have an apple in the game but not a banana, if you're in an empty room and type "x apple", it will say, "I can't see that." whereas if you type "x banana", it will response with "I don't know the word 'banana'." You could probably code for that contingency by trying to do a match on all the objects in the game to see if there is one that satisfies the text, but Quest was not coded for that."
(see my previous post)
" Though, upon further thought, that won't work either, as you could type "take eat", and it would not find an object called "eat" and so say it doesn't know the word, when it does - as a verb."
you could further expand 'my' (Credit to Pertex) previous post's coding, to include checking for if it's a 'verb' or 'command'
" and all the exits names, and... It's just not made to do that. If you designed it to do that, it would be easier to code."
and again, you could further expand 'my' (Credit to Pertex) previous post's coding, to include checking for if it's an 'exit' or whatever else, too.
----------
sorry, Mareus, I forgot to explain how parameters will allow you to put your input into the middle of a message:
<command name="message_command">
-> <pattern>greetings</pattern>
-> <script>
->-> msg ("Who do you want to say 'hello' to?")
->-> get input {
->->-> text = result
->->-> message_function (text)
->-> }
-> </script>
</command>
<function name="message_function" parameters="text">
-> object_x = GetObject (text)
-> if (object_x = null) {
->-> msg ("You can't say 'hello' to " + text + ", because it doesn't exist, silly.")
-> }
</function>
I was added in the coding that you suggested might be needed on top of unsolved responses:
Jay wrote:The Quest parser handles an "unresolved object" with something like "I don't see that." The reason why is that the parser makes no distinction between an object (or word for an object) that doesn't exist at all vs one which just doesn't happen to be in the current scope. I suspect that you want it where, if you have an apple in the game but not a banana, if you're in an empty room and type "x apple", it will say, "I can't see that." whereas if you type "x banana", it will response with "I don't know the word 'banana'." You could probably code for that contingency by trying to do a match on all the objects in the game to see if there is one that satisfies the text, but Quest was not coded for that. Though, upon further thought, that won't work either, as you could type "take eat", and it would not find an object called "eat" and so say it doesn't know the word, when it does - as a verb. So then you have to search through all the verbs and commands as well, and all the exits names, and... It's just not made to do that. If you designed it to do that, it would be easier to code.
"I suspect that you want it where, if you have an apple in the game but not a banana, if you're in an empty room and type "x apple", it will say, "I can't see that." whereas if you type "x banana", it will response with "I don't know the word 'banana'." You could probably code for that contingency by trying to do a match on all the objects in the game to see if there is one that satisfies the text, but Quest was not coded for that."
(see my previous post)
" Though, upon further thought, that won't work either, as you could type "take eat", and it would not find an object called "eat" and so say it doesn't know the word, when it does - as a verb."
you could further expand 'my' (Credit to Pertex) previous post's coding, to include checking for if it's a 'verb' or 'command'
" and all the exits names, and... It's just not made to do that. If you designed it to do that, it would be easier to code."
and again, you could further expand 'my' (Credit to Pertex) previous post's coding, to include checking for if it's an 'exit' or whatever else, too.
----------
sorry, Mareus, I forgot to explain how parameters will allow you to put your input into the middle of a message:
<command name="message_command">
-> <pattern>greetings</pattern>
-> <script>
->-> msg ("Who do you want to say 'hello' to?")
->-> get input {
->->-> text = result
->->-> message_function (text)
->-> }
-> </script>
</command>
<function name="message_function" parameters="text">
-> object_x = GetObject (text)
-> if (object_x = null) {
->-> msg ("You can't say 'hello' to " + text + ", because it doesn't exist, silly.")
-> }
</function>

jaynabonne
06 Jun 2014, 20:30Ok, I see now. I had no idea where you were suggesting that code you posted would actually go. 


jaynabonne
06 Jun 2014, 20:32Mareus, would you be able to post what you have, along with the commands to see what you're seeing? I could modify your doc and post it back to you as well. (If you don't want to do so here for any reason, you could always email me.)
Mareus
06 Jun 2014, 20:36jaynabonne wrote:Mareus, would you be able to post what you have, along with the commands to see what you're seeing? I could modify your doc and post it back to you as well. (If you don't want to do so here for any reason, you could always email me.)
Hey, that is very nice of you. Sure

PS. If you notice anything is off, you can change that too. I don't mind as long as it improves the game.

jaynabonne
06 Jun 2014, 21:17Attached is your file with the above change made to it (with some minor tweaks like the wrong wording I had and some quotes added around the word). See if it works the way you want. And don't overwrite your original game file until you're sure. 

Mareus
07 Jun 2014, 01:43jaynabonne wrote:Attached is your file with the above change made to it (with some minor tweaks like the wrong wording I had and some quotes added around the word). See if it works the way you want. And don't overwrite your original game file until you're sure.
I am really grateful for your effort Jay. It works, perfectly. Btw, if you tried out my game and you have any suggestions, I am all ears.