Looking for Text Parser to Ignore *All* User Input Except for Specific Words

Started by Sir_Blirmp, Thu 28/05/2020 23:45:26

Previous topic - Next topic

Sir_Blirmp

Hello Everyone!

I have a text parser up and running in my small "learning AGS" test project. I am trying to recreate something like the old-school World Builder games from the Macintosh Classic days, so I have two GUIs: one that 'narrates', i.e. tells the player where they are, what's going on (text adventure style); and one for entering in commands. I have both GUIs visible at all times. Things are working as expected, but I feel like I'm on the wrong path here with the scripting. I am finding I must be very specific regarding what the player inputs â€" Instead of telling the parser to look for certain key words, no matter how they were entered, it appears that the key words must be parsed in an exact order/combination. I must be doing something wrong.

For example, in my test room I have a paperclip on the floor. There is a locked door. I have successfully created a brief script where the user can type "take paperclip", and the paperclip object 'leaves' the scene and is added to the player's inventory. However, I also want the same script to be executed if something unpredictable like, "go over and take the stupid metal paperclip which I will then use to pick the lock on the door" is entered. From my understanding, in order for that line to be parsed correctly, there would need to be a line in the script that looks something like: if (Parser.Said("anyword take,get,grab anyword anyword paperclip rol")). If I don't have a line like that, then even entering "take the metal paperclip" would result in the parser halting.

Obviously I can't predict everything that someone is going to try and type. In the days of World Builder, I just scripted something like IF{TEXT=take}AND{TEXT=paperclip}, and it would cover any amount of random gibberish the player typed. As long as the words "take" and "paperclip" appeared somewhere in the input, the code would proceed.

Given what I'm looking to do, should I be using the parser at all? Should I instead be using something that checks the content of Strings? Also, I know text parsers are old news these days, but I have a huge soft spot for them and I think they add a lot to game play.

Thank you all! I have been looking at AGS for years now and finally decided to take the plunge and learn this.

Here is my parser in global script:

Code: ags

function txtUserInput_OnActivate(GUIControl *control)
{
  String input = txtUserInput.Text;
  Parser.ParseText(input);
  CallRoomScript(1);
  if (Parser.SaidUnknownWord())
  {
    lRoomDescription.Text = ("Huh?");
  }
  txtUserInput.Text = "";
}


And here is my code in the room:
Code: ags

function on_call (int value)
{
  if (value == 1)
  {
    if (Parser.Said("take,pick,lift anyword paperclip rol")||(Parser.Said("take,pick,lift paperclip rol")))
    {
      if (player.HasInventory(iPaperclip) == false)
      {
        if (doorlocked == true)
        {
          oPaperclip.Visible = false;
          lRoomDescription.Text = ("You now have the paperclip.");
          player.AddInventory(iPaperclip);
        }
        else
        {
          lRoomDescription.Text = ("The paperclip is stuck in the door handle. You cannot retrieve it.");
        }
      }
      else
      {
        lRoomDescription.Text = ("You already have the paperclip.");
      }
    }
  }
}

Khris

This
"go over and take the stupid metal paperclip which I will then use to pick the lock on the door"
is two commands, the AGS parser isn't really built for that.

But let's say you have
"go over and take the stupid metal paperclip"

If you add "go", "and" and "stupid" to the ignore list, then that line will match
"take,pick,lift anyword paperclip rol"

Sir_Blirmp

Thank you for the quick reply, Khris! I'm afraid I may have given a poor example of the issue I am facing. I didn't mean to imply with my first example that I wanted the parser to allow for two actions with one command input. I was just trying to think of some crazy thing someone might type in. The only action that I want is for the player to pick up the paperclip. I am aware that I can add tons of words to ignore in the parser, but it just seemed to me like that was way more work than is needed â€" is there no way to create a script so that the parser looks for only the words I specify and ignores everything else by default?

Let's say I have a scene with a big apple tree. In my description, it says something like "A colossal, twisting apple tree sits before you, its branches teeming with bright green Granny Smith apples." If the player wants to take an apple, all that's really needed to understand the player's intent is for her text to contain "take (or any synonym)" and "apple". But let's say the player is so immersed in my wonderful apple game that she writes "climb twisted tree and take a delicious, bright green Granny Smith apple" (maybe she's in a goofy mood). Isn't there a way for the script to move forward without me trying to think of any combination of words a player might use and either scripting 40 lines or adding tons of words to ignore in the parser? I understand that most people wouldn't write like this and I'm really stretching possibilities here, but I'm trying to cover my bases. I also understand that it's the nature of a text-based game that the parser won't understand everything, but I want it to be as easy as possible for a player.

Also, what if the player wants to "take" something else, even objects I can't predict? What is the least amount of scripting to tackle a player entering "Take branch" and having my description window say "You can't have the branch"? In the old Mac days I would just script something that says:

if text = "take", then
     if text = "apple" then
          display: "You now have the apple"
     if text = "branch" then
          display: "You tug at one of the branches but are unable to pull it from the tree."
     display: "You can't take that"
end

(bear in mind this is not actual script, just something to explain the gist)

That type of scripting (roughly what I used to do in World Builder), would cover the two most likely objects a player would want to take from the scene, and also cover any other random thing a player could think of (e.g. "take bark from tree" would end with "you can't take that"). Would I need separate lines for each possible scenario in AGS? One for "take apple" specifically and one for "take branch" specifically, and then one for "take anyword"?

Thank you much for your help. I am trying to understand the fundamentals of how the parser works in AGS. If I need to add a billion words to ignore in the parser, and then script several lines of possible text input, I'm prepared to do so! But I wanted to make sure I was approaching this the correct way from the get-go.

**Edit**
I've just realized I can put the if (Parser.Said("take" anyword")) in the global script after the CallRoomScript line and it will respond to any input correctly. I've also discovered that "anyword" accounts for more than just one word. I think I'm like 90% there. Looks like I just need to add some filler to my ignore list.

If there's any additional insight to what I've posted, however, I would love to hear it!

**Edit Edit**

Okay, looks like I might have been wrong about anyword accepting more than one word.

Khris

Ah, I didn't know that  anyword  matches more than one word, that's good to know (and makes sense).

It would be awesome if Parser.Said() could be called with a token string like "{verb} anyword {noun}" but you have to state each synonym individually, yes.

Sir_Blirmp

Dangit, after testing more I think I was wrong about "anyword" accepting more than one word. I used multiple words that I added to my ignore list in the parser which is why it worked. Further testing seems to indicate that anyword overlooks only one word. Would be nice if it skipped anything until the next scripted word!

SMF spam blocked by CleanTalk