Are there variable for the players adverb and noun

If the player should enter "Cook Meat"
Then the adverb would be Cook and the noun is "Meat"

I thought that maybe the players noun would be something like #noun# then I could test if the player is holding the object that the player typed in
for example
if (Got(#noun#)) {
Are there variable for the adverb and noun that the player typed in?

This would be useful for a 'switch' command. So the read pattern could be 'wash #object#' and then I could have messages for any specific object that the player washes


In a grammatical sense, "cook" is a verb.

In Quest's code, "cook" may be either a verb or a command (Quest's verbs are a special type of command, whose behaviour is defined by the object they're applied to)

If you have a "cook" command, then its pattern will probably be something like cook #object#. Within the command's script, you can use the variable object to refer to the object that the player typed.
You can name the variable something else (like #object1# or similar), but it has to start with either object, exit, or text. In the case of text, the variable will be a string containing what the player typed; for object and exit, it will be converted to an object (and Quest will ensure that the player can see the object) before running the command.

If you have a "cook" verb, then Quest will check if the object has a script attribute named cook and will run that. In this case, the object can be referred to as this. If the object doesn't have a cook script (like if the player types "cook table"), Quest will simply respond "I can't cook it."


Thanks mrangel for your reply.

Yes my mistake I got adverbs and verbs mixed up.

I have not tried it yet but from what you have told me the command 'if #noun# = "meat" {' should pass if the player enters 'cook meat'

Looking at verbs is the command 'if this = "cook" {' likely to work?
There are some cases where the player can do many things with an object so rather than have a lot of script commands I was wondering id there was another way with a word pattern of 'this wood' (where 'this' is the verb that the player has typed.
I could have a word pattern of 'paint wood; cut wood; burn wood' but then I would need to know what verb the player typed so I could deal with for example the painting of the wood.


Hi mrangel.

I was thinking that one possible way of getting the verb that the player typed would be to look at the whole text of the players input #text# and then use the instr string function to either search for a certain word or get the first word the player typed.


I have not tried it yet but from what you have told me the command 'if #noun# = "meat" {' should pass if the player enters 'cook meat'

No…
If your script is in a verb then you would need:

if (this = meat) {

(but that's pretty pointless anyway - because the script would be on the meat object's "verbs" tab. That script will only be run if the object is the meat, so there's no need to check for it)

If your script is a command then your command has both a "pattern" and a "script".
If the pattern was "cook #object#" then you could use if (object = meat) { in the script - the object parameter is automatically converted to an object the player can see, that matches what they typed.
If your pattern was "cook #text#" they you could use if (text = "meat") {

Looking at verbs is the command 'if this = "cook" {' likely to work?

Why would you need to?

Every verb has its own script. So if your script is a part of the "cook" verb, it will only be run if the player's command started with "cook".

to look at the whole text of the players input #text# and then use the instr string function to either search for a certain word or get the first word the player typed.

Why? This seems like an awful lot of effort to go to, in order to do something that Quest already does for you.
I can think of a few situations where this kind of code would be useful; but they're all unnusual edge cases, and they would all have to be handled in completely different ways.

You've got these little "if" statements; but where are they? Which script are you putting them in?


Hi mrangel.
Like I said in my first post this would be useful for a "switch" command. I used "if" to indicate what I'm trying to achieve.
In this example the word pattern is dig #object#

switch (object){
case ("carrots"){
msg ("The carrots have not grown big enough")
{
case ("potatoes"){
msg("You don't have anything to cook the potatoes with")
{
etc
I have not tried this code yet. This would save having a script for each vegetable.

If it were possible to work on a verb then I could have a single script for paint wood, burn wood, clean wood and have a message depending on what the player is doing with the wood, using a word pattern such as #verb# wood


If you were using 'if' statements, it would have to be if (object = carrots) {, for example, because the object variable is an object rather than the string typed. (Assuming that there is actually a 'carrots' object which the player can see). But as switch/case converts the variables to strings before comparing them, I think that script should work.

If it were possible to work on a verb then I could have a single script for paint wood, burn wood, clean wood and have a message depending on what the player is doing with the wood, using a word pattern such as #verb# wood

You could make the pattern #text# wood. Then you would have a variable named text whose value is either "paint", "burn", or "clean". In this case, it would be up to your script to make sure that the wood is reachable. Note that the variable name in a pattern must start with either text, object, or exit - this tells Quest whether it should compare the player's input against the list of visible objects before running the command.

You could also use a 'regular expression' type pattern, which is a more powerful kind of pattern, to do something like: ^(?<text>burn|clean|paint|chop) wood$ (or even ^(?<text>burn|clean|paint|chop) (?<object>wood)$ - which would handle the "I can't see that" response automatically if there's no wood around)

Theoretically, you could even have a pattern ^(?<text>\S+) *(?<object>\S.*)?$ which will catch any one-word command followed by an object name, allowing you to neatly handle whatever input the player types (this won't be called for commands which already exist, because if multiple patterns match Quest will pick the one which has the least text captured by variables (seems odd, but there's a reason. I can explain why if you're interested)


Thanks mrangel.

I feel that main problem is that you don't know what the player will type so you need to cover yourself. I like the #object# in the word pattern for that reason. I understand that its not possible to fully cover what a player might type.

If the player typed "paint the wood", "paint the wood red" or "quickly paint the wood" then I'm not certain if the word patterns you suggested would cover for this. The word pattern ^(?

If #text# wood is used then I need a way of separating the adverb from the text or at least get the first wood, would something like if ^(?

If it's not too much work to explain why Quest will pick one that has less text captured by variables for multiple patterns when I'm always interested to learn something new thanks.


It's 3am here, so my apologies if I'm not making much sense.

If it's not too much work to explain why Quest will pick one that has less text captured by variables for multiple patterns when I'm always interested to learn something new thanks.

The case where multiple patterns match is mostly designed for situations where there are one- and two-object versions of a command.

For example, the player types "drop coin in well".

There are two commands this matches, because "drop" is both a command on its own, and an alternative for "put".

So the two patterns that match are (simplified):

  • 'drop' command, pattern:drop #object#. In this case, the variable object captures the input "coin in well", 12 characters.
  • 'put' command, pattern effectively: drop #object1# in #object2#. So the variable object captures the input "coin" (4 characters) and object2 captures the input "well" (4 characters)

The 'drop' command captures 12 characters in its variable. The 'put' command has 4+4=8 characters in variables. In this case, Quest chooses the 'put' command.

If the player types "drop coin in well", they're more likely to mean the command with the pattern "drop #object1# in #object2#" than the command with the pattern "drop #object#".

You'd think that Quest could guess which command is meant because the player isn't carrying an object named "coin in well". But different commands have different scopes, and the disambiguation system means that Quest can't start comparing the object variable to an actual list of object until after it knows which command it's using. So the developers used the fact that the word "in" isn't captured by any variable to draw the distinction. "drop #object1# in #object2#" has more "command" characters matching the players input, and therefore less characters in its variables.

(It's worth noting that Quest checks for "less characters in variables" rather than "more characters matching the command words" - for all the core commands, these two are equivalent; but it's possible to write a regular expression pattern where this isn't necessarily the case. So if you do that, it's useful to know how the system actually works behind the scenes.

For example, you could make a pattern: ^(?<text>put whole pattern here)$ - in which case the text variable captures the whole command, including any text that's also captured by other variables. So this command would have a silly large number of characters in its variables, and would only ever be triggered if no other command matches the player's input.)

(PS: The put command's pattern is actually: ^(put|insert|place|drop) (?<object1>.*) (on|in|on to|in to|into) (?<object2>.*)$ - I simplified it for the example above, in the hope it would be easier to understand)

If the player typed "paint the wood", "paint the wood red" or "quickly paint the wood" then I'm not certain if the word patterns you suggested would cover for this.

Properly parsing every option would probably require the system to understand English grammar; which is currently beyond the capability of any AI (though they're coming close).
For "paint the wood red", you could have a pattern like ^paint (?<object>.+?)( (?<text>red|crimson|green|black))?$ or similar, which ignores a colour at the end of the line. If you know what paint they have available, you could come up with a list of colours they're likely to type. Or if the player actually has paint in their inventory, you might be able to match a second object (although that's hard to deal with)

For adverbs like "quickly", which could be placed just about anywhere in the command, I suspect it might be possible to deal with this by modifying the parser a little. You could just remove these words from the command. However, I think most people playing text adventures wouldn't expect the computer to understand a more complex sentence like that; so are unlikely to try it.
(My thought would be to take out all words ending -ly unless they're found in an object's alias, and put them in a separate variable… shouldn't be hard to do, if you think it would be beneficial)


Thanks mrangel for the information.

Is there anywhere in the Quest Help file that I can find how to create my own custom word patterns such as ^(?


Is there anywhere in the Quest Help file that I can find how to create my own custom word patterns such as ^(?

Regular Expressions are pretty complex (and the full language is way more complex than you need for Quest), but here's some of the basics:

  • Letters and numbers match themselves. So the pattern cow will match any command that includes the word "cow"
    • I think letters are case-insensitive in Quest (most languages make this an option)
  • The characters ^ and $ match the beginning and end of the string respectively. So the pattern ^take would match a command that starts with "take", and the pattern wood$ would match any command that ends with "wood".
  • Special characters \^$[]{}()|.*+? can be preceded by a backslash to make them match literally. So the pattern \^ would match if the player actually typed a "^".
  • The dot . matches any character. So the pattern b.g would match the input "big", "bog", "bag", "b9g", "b g", etc.
  • A question mark makes the previous character optional. So the pattern ropes?$ would match player input ending with either "rope" or "ropes"
  • Parentheses group parts of the pattern together. So the pattern ^look( at)? dragon$ would match the inputs "look dragon" or "look at dragon".
    • Apparently a common mistake: Watch your spaces. If you put ^look (at)? dragon$, the player would need to type "look   dragon" with two spaces, because the spaces aren't part of the optional bit.
  • A question mark at the start of parentheses enables a lot of more advanced features. Most of these, you won't need to use. But:
    • (?<variable name>pattern) matches the pattern inside the brackets, and stores that part of the player's input in a variable for your command to use.
      • In Quest's command patterns, the variable names must start with either "text", "object", or "exit" so that Quest knows whether or not to look up an object before running the command script.
      • When converting "simple" command patterns to regular expressions, Quest converts #object# to (?<object>.*)
  • An asterisk * makes a character optional or multiple. So the pattern ^pet( cute)* cat$ would match the commands "pet cat", "pet cute cat", "pet cute cute cute cute cat", and so on
  • A plus + matches multiple in the same way, but requires at least one match. So the pattern ba+d would match "bad", "baad" or "baaaaaaaaad", but not "bd".
  • A number in curly brackets matches that many times. so the pattern whe{5} matches the string "wheeeee".
    • Two numbers (with a comma) specify a range. So e{3,5} will match "eee", "eeee", or "eeee".
    • Either number is optional. So a{4,} matches 4 or more "a"s in a row, while x{,4} matches 4 or less "x"s.
  • Square brackets match any one of the characters inside them. So b[ao]d matches "bad" or "bod", and [aeiou]{2,} matches any set of at least 2 consecutive vowels.
    • If the first character in the brackets is a ^, it means not. So [^ ,] matches any character except a space or comma
    • A dash lets you match a range of characters. So [^3-8] is the same as [345678] and [^e-i] is the same as [^efghi].
  • A pipe character lets you specify multiple options. red|blue|green will match "red", "blue", or "green".
    • Note that ^pose|dance$ will match a command that starts with "pose" or ends with "dance" - probably not what you want. The coder who does this probably meant ^(pose|dance)$
  • \s matches any whitespace character (space, tab, narrow space, wide space, etc. These will normally only show up in your input if a player is copy-pasting characters from the web or is using a non-English keyboard); \d is any digit; \w is any word character (letters, numbers, or the underscore). \S is a non-space character, \D is a non-digit, and so on. There are also named character classes like [[:letter:]] and [[:emoji:]], but I'm not sure if Quest supports them.
  • \b matches a position (zero characters; the position between characters) where there's a boundary between a word and non-word. So, for example, the\b would match the word "the" in "over the border", or in "the fish", or just "the", but not in "there". Conversely, \B matches a position which is not a word boundary, so the\B would match any words that starts with "the", but not "the" on its own.
  • A \ followed by a digit matches a parenthetical pattern elsewhere in the pattern. So \2 matches a repetition of whatever matched the second pair of parentheses in the pattern.
    • Example: the pattern (bob|steve) and \1's wife will match "bob and bob's wife" or "steve and steve's wife", but not "bob and steve's wife".
    • This is often used in things like (.)(?!\1) - which matches a command which does not contain a double letter. (Oh, I didn't mention (?!pattern), which matches anything that is not pattern.)
  • There are also a couple of weird expressions like (*FAIL) and (*ACCEPT), which are normally only useful inside a construct like (tom|dick|harry).
    • (*FAIL) causes the entire match to fail as soon as it is reached, even if one of the later alternates would match
    • (*ACCEPT) causes pattern matching to end successfully when it is reached, ignoring any other parts of the pattern after it. So the pattern tell (john|bob(*ACCEPT)|steve) to stop$ would match "tell john to stop", "tell steve to stop", "tell bob", or "tell bob he's stupid".

One important thing to note is greediness. An expression with a *, +, or ? in will match as many characters as possible, and then checks to see if the pattern to the right of it will match the remainder of the string. If not, the *, +, or ? will try matching less, until the remainder of the pattern matches.
The corresponding operators *?, +?, and ?? are non-greedy; they will match as few characters as possible in order to let the rest of the string match.

So if your pattern is ^(?<text1>.+) (?<text2>.+)$, the variable text1 will be most of the words in the player's input, and text2 will be the last word (or whatever comes after the last space).
Whereas if your pattern is ^(?<text1>.+?) (?<text2>.+)$, text1 will be the first word and text2 will be the rest of the string.

This becomes relevant if you make a pattern like give #object1# to #object2#, which will use the greedy operators - and will split the string up incorrectly if object2's alias contains the word "to". Making commands like this work correctly is extremely difficult. And note that Quest matches the whole pattern, deciding which command's pattern is the best fit and which parts of the user's input go into object1 and object2, before it tries to convert object1 and object2 into actual objects.

Wow… that took longer than I expected. And that's not even all of it.


Good to know thanks mrangel


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

Support

Forums