Allow a command to require object1 for an action on object2

jef

OK, I’ve scoured the tutorials and forums for days, because it seems like this should be a common issue, but I can’t figure out how to do it. (FYI: I’m using the offline editor and am more comfortable with the GUI than the Code view.)

My game requires the use of certain objects in order to complete certain actions. As written, the game more or less works, but the human playing would have to hit on the exact phraseology in order to succeed. I would like to allow multiple ways for them to input those directives. For example, I want the player to be able to climb a tree, but for them to have to get a specific object first (call it “climbingapparatus”) in order to do so. Here is what I have done:

  1. Create the objects “tree” and “climbingapparatus” (DONE)
  2. On the Verbs tab for the object “tree”, create a Verb “climb” and select “Require another object” (DONE). Now the player can select “climbingapparatus” from a menu if they have that object but “climbingapparatus” doesn’t appear in the menu if they haven’t found it yet.
  3. Create a bunch of if-thens giving responses for various things the player might try (e.g., attempting to use the wrong object) (DONE)

So this method of “Require another object” within a specific verb works OK. But I want the human to be able to input “climb” (by itself) or “climb up” (without specifying the object) or maybe other things like “go up the tree” or “scale the tree” or who knows what else, instead of only allowing for the exact phrase “climb tree”. But I can’t figure out how to implement that. (Note: I am open to re-working the whole thing and ditching what I have done above in order to achieve the desired results. In fact, ideally all the synonymous ways a person could input their instructions would all point to the same section of code (whether that be a Command, a Function, a Verb, or what have you) and if I wanted to modify it later I would only have to change it in one place. (While we’re changing everything anyway, I would probably prefer it to ask for an open-ended response than ask the user to select from a menu, though it would be nice to learn how to do both anyway.) Here is what I have tried:

  1. I have created the command “climb” and added synonyms to it (separated by semi-colons in the “pattern” box). (DONE)
  2. I put an if-then in there so that, for example, the command “climb” will only work when the “tree” is reachable. (DONE)
  3. I made the command “climb” call up a function “climbing” (DONE) … I don’t know if that is necessary or helpful; it can be removed.

In other words, I can take several different user inputs and make them do the same action, as long as that action is defined in a Command or a Function. But I can only figure out how to “require another object” using a Verb. I can’t figure out how to allow for synonyms and still allow the user to input or select the object they want to use for the action.

From what I’ve been reading in the tutorials, guides, and forum discussions, I’m thinking that the answer is going to be one of these functionalities: either I need to use parameters somehow (I still haven’t found a clear enough beginner-level explanation of how to do that), or maybe “Run object’s script attribute” (again, even after reading everything I could find, I still haven’t been able to use that successfully) or maybe “Ask a question” (such as “What object do you want to use?”) or “Show menu” (which may in turn require setting up a list for them to choose from – it would just be reachable objects, probably -- and again I’ve been reading and trialing and erroring and I still can’t figure out how to create a list like that). Etc.

If this seems like a lot of work just so they can say “climb” (by itself) as well as “climb tree”, it’s really more than that, because I want to figure out how to do this for not just this one action, but pretty much every major action in the game. Say I want the player to have to use a hammer to break open a closed box. I would like a variety of human inputs (hit box; use hammer; hit box with hammer; smash box; break box; break open box; use hammer on box; hit hammer against box; etc.) to either succeed (if they've specified the right object) or ask them to specify which object they want to use. Ideally I would want to spell out all the if-thens (for what happens when the person tries various ‘incorrect’ objects on the box, etc.) only one time in the program, and then have all the synonyms point to or call that function (or access that script, or whatever the appropriate terminology is).

Thanks in advance.


I think the easiest way (any/all 'if'/programming is a lot of work: computers are stupid, programming, even the best/perfect code design, still takes many more lines than it does between how humans communicating with each other) would be to have two (or rather 3) custom Commands of your own:

(in my example, I use the '#text#' type Parameter, but you can use '#object#' type Parameter too, either and both-together can work, but they require a bit of different and/or tricky scripting)

<command name="no_input_climb_command">
  <pattern>climb</pattern>
  <script>
    // it sounds like you understand the scripting needed to handle all of this, but if you need any help, let me know
  </script>
</command>

<command name="input_climb_1_command">
  <pattern>scale #text#</pattern> // I'm using 'scale' as there might be issues with the parsing of the patterns of these 3 Commands
  <script>
    // it sounds like you understand the scripting needed to handle all of this, but if you need any help, let me know
  </script>
</command>

<command name="input_climb_2_command">
  <pattern>ascend #text_1# with #text_2#;ascend #text_1# using #text_2#;etc etc etc</pattern> // I'm using 'ascend' as there might be issues with the parsing of the patterns of these 3 Commands
  <script>
    // it sounds like you understand the scripting needed to handle all of this, but if you need any help, let me know
  </script>
</command>

how the Command's Parameters (#text# and/or #object#) work:

in the Command's 'Pattern' text box, to use the Parameters, you have to have:

#text# or #textXXX# or #object# or #objectXXX#

quest recognizes the Parameters via their first part:

#text
#object

after this you can add whatever you want onto it (my 'XXX' representation), for example:

#text_1
#text_2
#textfakljdklasjdlkajdkl // though never do this, lol... make it more readable for yourself --- but hopefully you get the idea I'm trying to convey
#textppppppppppp

#object_1
#object_2
#objectkdfljjfoiefkn
#objectwwwwwww

and then lastly of course you need to add the ending '#' to it:

#text_1#
#text_2#
#textfakljdklasjdlkajdkl#
#textppppppppppp#

#object_1#
#object_2#
#objectkdfljjfoiefkn#
#objectwwwwwww#

you also do NOT have to add anything to it if you're just using a single Parameter of each type (adding to its name is really just required when you want/need to use multiple Parameters):

#text#
#object#


the '#....#' tells quest that this position/segment in the entire/full input by the person playing the game is to be used as an input (via storing/setting it to the Parameter) by the Command's scripting.

However, the Parameter Variable itself (what is used in the Command's scripting) is with OUT the '#s', for example:

<command name="kiss_command">
  <pattern>kiss #text#</pattern>
  <script>
    msg ("You kiss the " + text + ".")
  </script>
</command> 

// input: kiss frog
// output: You kiss the frog.
// so what is going on:
// 'kiss' is the what I call the 'indicator/activator' word/term/command/string (the first word/term/command/string in your pattern), as it tells the parser what command you want to be doing: meaning that every command needs to have a different first word/term/command/string for their pattern to identify them from each other.
// then after the (space), we got the specified position of what will be used (stored/set'ed/saved within) by the 'text' Parameter Variable, which in this case is 'frog', see below:
// text <==== #text# <===== "frog"
// text = #text# = "frog"
// text = "frog"
//
// and now within the Command's scripting, our 'msg' Script is using our 'text' Parameter variable, to give us the result/output:
// You kiss the frog.

let's look at a more complex Command, so you can see how everything works:

<command name="mix_command">
  <pattern>mix #text# #text_1# #text_2# #textABC# #object# #object_1# #object_2# #objectABC#</pattern>
  <script>
    msg (text)
    msg (text_1)
    msg (text_2)
    msg (textABC)
    msg (object.name)
    msg (object_1.name)
    msg (object_2.name)
    msg (objectABC.name)
  </script>
</command>

<object name="room">
</room>

<object name="player">
  <attr name="parent" type="object">room</attr>
</object>

<object name="apple">
  <attr name="parent" type="object">room</attr>
</object>

<object name="orange">
  <attr name="parent" type="object">room</attr>
</object>

<object name="banana">
  <attr name="parent" type="object">room</attr>
</object>

<object name="grape">
  <attr name="parent" type="object">room</attr>
</object>

// input by person playing game: mix red blue yellow green apple orange banana grape
// output:
red
blue
yellow
green
apple
orange
banana
grape

--------------------

notice the difference required for using the '#object#' vs using '#text#

-----------------

for #text# to an Object:

my_object_variable = GetObject (text)

or

foreach (object_placeholder_variable, AllObjects()) {
  if (object_placeholder_variable.alias = text) {
    game.my_object_attribute = object_placeholder_variable
  }
}

-----

for #object#:

this only looks for if the Object is in the same room as you, so if you want to use an Object not in the same room as you, then you got to use that 'foreach (placeholder_variable, AllObjects())' shown above (though with some small tweaking as you're working with #object# and not #text#)

You could try
verb: "climb tree"
if: player is carrying object: climbing apparatus.
and then add in the subsection of that the script Move object: player - to object/room: treetop.
Or something like that. Then no matter what they type, it will only work if they have that object in their inventory.
Hope this helps, and that I understood the problem correctly. This would be in the web version, but I imagine the same could be done in a similar way for the offline version.


You can allow for synonyms with verbs, too, in the same way you add synonyms for the commands. If this helps.

You can also use 'fancy' commands like:

^(pour|dump|add|empty|put|use) (the |)(bottle|water|bottle of water) (on|over|into|onto) (the |)(seedling)

Obviously, this is an example only. Just put the verbs and nouns in as you need them. =)

Note: I am no expert on this. It is basically a copy-paste job from The Pixie (I think) from many moons ago. =)
This will save you some trouble with duplicate command entries. I found this very helpful when I was doing similar stuff.


This is not straightforward.

I would do this as three separate commands, one with no nouns (CLIMB, etc), one with one (CLIMB TREE, etc.) and one with two (CLIMB TREE WITH CLIMBINGAPPARATUS, etc.). In addition you might also want to do USE CLIMBINGAPPARATUS...

For each one you need to check the relevent objects are present and, for some, that the right object has been used in the command. If all is okay, have them all call a function, and have the function handle the actual response.

You might want to look at this:
https://github.com/ThePix/quest/wiki/Using-Complex-Commands


jef

Thank you everyone for your replies.

Pixie, I discovered your Complex Command page just after I posted the original question, and found it extremely helpful. In case you're curious, I was initially confused by your statement that "Quest will already have assigned values to two special variables, in this case called object_cord and object_hook. We do not know specifically what they are" and it took me some trial and error to figure out how the computer assigned objects to those variables. I think the names object_cord and object_hook threw me off, because I was expecting them to be the cord and the hook. But they weren't necessarily. And you said we didn't know what objects the computer assigned to those variables (!). So they could be anything? It confused me for a while. But now I get it, and it seems obvious in retrospect: they are whatever the person typed into those places when they input the command. (HK, in retrospect, it looks like you were explaining that, but my eyes must have glazed over before that the first time I read your response. Sorry.) Anyway, overall, like I said, very helpful, I've had the tab open all week referencing that page.

ScaryCat, thanks, I am sort of using your method but I would still like to improve it (see below).

HK, thank you very much for your detailed response. It's still above my level of comprehension, but every time I read through it I understand a little bit more. For all I know you've solved my problem completely, but if so I haven't understood it yet. But I especially appreciate the explanation of Parameters, because I didn't know what those were at all, and now I kind of do.

XanMag, your brief reply was the most helpful so far. I didn't know verbs could have synonyms; that's one big reason I was trying to use commands and functions. So thanks for that. Related to that, I'm just going to put a note here for future reference of myself or anyone else with the same issues, according to what I've figured out:

  1. you can edit the consequences of a verb on the Verbs tab of a specific object, but you can't add synonyms there; you have to do that when you first create it, or do it to the whole verb by clicking on it in the Verbs section of the tree on the left. Best I can tell, the Pattern field can be filled in with synonyms like a Command can, whereas the Attribute is the unique identifier, like an object's "Name".
  2. synonyms that start with the same word (like "climb" and "climb up") won't work right if you put the shorter one first (Command Pattern: climb; climb up), because if the person types "climb up tree" the program will match it to the verb (or command) "climb" first and then it will think "up tree" is an object (which it doesn't recognize) but if you put the shorter one last (Command Pattern: climb up; climb) then it will work right (at least so far, for me) because it will try to match "climb up" before it looks at "climb", so it will recognize "tree" as an object of the verb "climb up" instead of trying to make "up tree" into an object of the verb "climb". Or at least, I assume that's what it's doing; either way, it seems to be working that way.

But I'm still not sure about this part:
How can I prompt the user to input the object they want to use, if they don't choose an object. On one of the required actions in my game, I kind of have it set up the way ScaryCat suggested, where if the player has the right object then the action works and if they don't then it doesn't. But what I would like to happen is for the computer to prompt the user to input the object they want to use. To stick with the climbing example, here is what I would like to happen:

  1. If the user types "climb tree with climbingapparatus" then it should work; they have specified both necessary objects. I can do this with Commands thanks to your previous responses and Pixie's tutorial.
  2. If they just type "climb tree" (specifying only one of the necessary object: the direct object of the verb) then I would like them to be asked which object they want to use to climb it. (This can be done easily with a Verb by selecting Require Another Object, and now that I know Verbs can have synonyms then that solves a lot of my problem because I didn't want to set up the same list of objects and results for a whole mess of different verbs, but still, see below.)
  3. If they type "climb using climbingapparatus" (specifying only the second [indirect?] object) then I would like it to work -- because the tree is the only climbable thing around -- instead of requiring them to get the wording exactly right by specifying the tree. (Again, I can now make a Command incorporating an object like this, thanks to you all.)
  4. Here's where I'm struggling: If they just type "climb" (without specifying any objects) then, like option 2 above, I would like them to be asked what they want to use to climb and let them input a response. Since they did not input an object, it seems this cannot be a Verb, it must be a Command. And there doesn't seem to be a Require Another Object option for Commands. So... how can I prompt them to input an object, and then use their input to drive different consequences. (Right now I have it set up with just a message like "How do you want to climb?", but it's just a message and their response is in no way related to previous inputs or outputs, so they would have to retype the whole directive (including the word "climb"), instead of just answering a question like "Which object will you use to climb?" and they can literally just say "climbingapparatus" (or some other object, which won't work).)

Note: In situations where they have not specified the object to use, I am willing to settle for a popup menu where the user selects from the objects available -- but in a perfect world, I want my human player to have to come up with the idea of using that object themself, not just pick it from a list. This is because in the game the thing we've been calling "climbingapparatus" is not actually an item traditionally used for climbing trees, although it will get the job done. But I want the player to think of it. If when they type "climb tree" they are presented with a list of objects to use, they may just try all of them until they hit the right one, and again, it doesn't really require the human player to figure anything out. Or, using ScaryCat's idea (and I have one set up that way now), if I make it so climbing is successful just by the mere fact of them having the object, then, again, they can succeed without necessarily figuring out the puzzle; they could just go around and collect all the objects and then type "climb tree" and succeed without actually coming up with the correct idea for how to climb it. I would like them to have to have the idea of using that object as a method of climbing a tree, and tell the computer to do that. And that applies equally whether they type "climb tree" or just "climb".

Thanks again, everyone.


prompting (displayment/output for the) person playing the game is via the 'msg' Script (GUI/Editor: run as script -> add new script -> 'output' section -> 'print a message' Script -> [MESSAGE]:text/string ONLY, or, [EXPRESSION]:"TEXT/string only" or VARIABLE only or "TEXT/string"+VARIABLE, script options)

http://docs.textadventures.co.uk/quest/scripts/msg.html

you can also use other built-in Functions too, which do/have prompting as a part of them:

'show menu', 'ShowMenu', 'ask', 'Ask', etc etc etc


there's only two ways to get typed-in input from the person playing the game:

  1. the 'get input' Script/Function (GUI/Editor: run as script -> add new script -> 'output' section/category... I think -> 'get input' Script)

  2. Commands (the 'Command' Element: http://docs.textadventures.co.uk/quest/elements/command.html )


for example:

msg ("Object for climbing the tree?")
get input {
  // quest, for 'get input', 'show menu / ShowMenu', and 'ask/Ask', automatically (hidden from you) sets your input to the built-in 'result' Variable:
  // result = YOUR_INPUT
  // which, you can then use 'result', such as seen below:
  if (GetObject (result) = climbingapparatus or climbingapparatus.alias = result or result = "climbingapparatus") {
    // your climbing the tree scripting/script(s)
  } else {
    msg ("That object doesn't work and/or wrong input")
  }
}

you also may need to use this design, and/or you can jsut study it (ask me if you aren't able to understand it):

(from my old combat code, but the Credit goes to Pertex for this code, as he/she helped me with my combat code)

<function name="battle_system" parameters="self,text" type="boolean">
    enemy = GetObject (text)
    if (enemy = null) {
      foreach (obj,AllObjects()) {
        if (obj.alias=text) {
          enemy = obj
        }
      }
    }
    if (enemy = null) {
      msg ("There is no " + text + " here.")
    }
  }
</function>

actually, this might be a good way of doing it (if it works, here you go, it's more powerful/versatile/scalable than what you wanted for your game design, should you want to use a more complex game design in the future, otherwise it still works fine for what you want now --- again if it works, lol):

(Credit also goes to you, for your discovery/testing of how the parsing works, as I've used that in/for its pattern, hehe)

<command name="climb_command">
  <pattern>climb with #text_2#;climb using #text_2#;climb #text_1# with #text_2#;climb #text_1# using #text_2#;climb #text_1#;climb</pattern>
  <script>
    if (text_2 = null) {
      if (text_1 = null) {
        msg ("Climb what?")
        get input {
          if (Contains (player.parent, GetObject (result)) and GetString (GetObject (result), "type_of_object") = "tree") {
            msg ("Climb tree with/using what?")
            get input {
              if (result = "climbingapparatus") {
                if (Got (GetObject(result))) {
                  // your able to climb tree's script(s)
                } else {
                  msg ("You need to be carrying that Object in your inventory in order to be able to use it here")
                }
              } else {
                msg ("Wrong input")
              }
            }
          } else {
            msg ("wrong input")
          }
        }
      } else if (Contains (player.parent, GetObject (text_1)) and GetString (GetObject (text_1), "type_of_object") = "tree") {
        msg ("Climb tree with/using what?")
        get input {
          if (result = "climbingapparatus") {
            if (Got (GetObject(result))) {
              // your able to climb tree's script(s)
            } else {
              msg ("You need to be carrying that Object in your inventory in order to be able to use it here")
            }
          } else {
            msg ("Wrong input")
          }
        }
      } else {
        msg ("Wrong input")
      }
    } else if (Contains (player.parent, GetObject (text_1)) and GetString (GetObject (text_1), "type_of_object") = "tree") {
      if (text_2 = "climbingapparatus") {
        if (Got (GetObject(text_2))) {
          // your able to climb tree's script(s)
        } else {
          msg ("You need to be carrying that Object in your inventory in order to be able to use it here")
        }
      } else {
        msg ("Wrong input")
      }
    } else {
      msg ("Wrong input")
    }
  </script>
</command>

// example of the design concept (you have to have your climb'able tree Objects have (add/create) a String Attribute named 'type_of_object' with their string Value as 'tree' --- see my 'tree_type' Object Type / Type below the 'ogre_1' Object, below):

<object name="room_1">
</object>

<object name="room_2">
</object>

<object name="room_3">
  <inherit name="shop_type" />
</object>

<object name="tree_1">
  <inherit name="tree_type" />
  <attr name="parent" type="object">room_1</attr>
</object>

<object name="tree_2">
  <inherit name="tree_type" />
  <attr name="parent" type="object">room_2</attr>
</object>

<object name="orc_1">
  <inherit name="monster_type" />
  <attr name="parent" type="object">room_1</attr>
</object>

<object name="ogre_1">
  <inherit name="monster_type" />
  <attr name="parent" type="object">room_2</attr>
</object>

<type name="tree_type">
  <attr name="type_of_object" type="string">tree</attr>
</type>

<type name="monster_type">
  <attr name="type_of_object" type="string">monster</attr>
  // blah Attributes (life, condition/dead, damage, defense, fight, etc etc etc)
</type>

<type name="shop_type">
  <attr name="type_of_object" type="string">shop</attr>
  // blah Attributes (buy, sell, etc etc etc)
</type>

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

Support

Forums