I6: Switch Second for Noun in AskFor

Does anybody know how to make this work?

In a routine like AskFor it has a noun and a second, with the second being parsed as a topic. But is it possible to change the second to the noun and have it parsed?

The grammar would look like:

Verb 'ask'
    * 'for' scope=TopicScope   -> AskForTopic;

  [ AskForTopicSub;
        <<AskCreatureFor caveTroll>>;
  ];

Then in the caveTroll’s BEFORE:

AskCreatureFor:
    if (self.switched) {
        self.switched = false;
        second = noun;
    }
    switch (second) {
        t_grub:
              "~Mine!~";
    }

Obviously this doesn’t work, but that’s the idea I’m trying to figure out.

I’ve also tried reading NextWord() and setting that to the second, but it doesn’t like that either.

Any ideas? Thanks - D

Do you mean having a verb which allows the noun and second noun to be switched?
So you could have a verb which understands “show sword to troll” and also “show troll sword?” If so, then you just need to end the grammar line with the word “reverse” so:

Verb ’show’ ’present’ ’display’
* creature held      -> Show reverse
* held ’to’ creature -> Show;

where the asterisk substitutes for the words “show”, “present” or “display”.

I’m not sure if this is quite what you want, but I did a similar thing recently by extending the grammar for ‘ask’ as follows:

Extend only 'ask' first
  * 'about'/'for'/'to' topic -> VagueAsk
  * creature 'for' topic -> Ask;

In this way, ASK TROLL ABOUT APPLE and ASK TROLL FOR APPLE are synonymous. VagueAskSub is a custom action handler that just reminds you that you need to provide a subject.

In your example, there is no provision for a second noun in the grammar, so you won’t be able to exchange noun for second anyway.

It sounds like you’re wanting the opposite of GIVE. With GIVE, you give something to an animate object (using the creature token). It sounds like you want to get something from an animate object. In this case, the grammar would be the same as above, except that Ask would be AskFor. This is a custom action that does whatever you want.

Because you’re directing the command to an animate object, you should handle the specific overrides in a life rule by providing the following in AskForSub:

  if (RunLife(noun, ##AskFor))
    rtrue;

Then your life rule would be something like:

life
[;
  AskFor:
    if (second == 'whatever')
      ! Do something
],

This is the easiest way to do it. Apologies if this is not quite what you want. If it’s not what you want, perhaps you could be a bit more explicit with a couple of transcript examples.

@Dizzydonut Yeah, I never thought about using REVERSE. It sounds like a good idea. But what I’m doing is suck a mess, I decided to break it all out.

@Warrigal Yeah, my problem is I’m using scope=TopicScope instead of topic. If I use topic I can break everything out using NextWord. Then read the second that way. I would rather use a list of Topics, but I’m not sure it can be done like that.

Thanks for the help, I just did it the hard way. :slight_smile:

If you want to use a list of topics, you can still do this as follows (assuming continuation of the previous example):

life
[;
  AskFor:
    switch (second)
    {
      'big', 'bad', 'wolf':
        ! Do something
      'little', 'red', 'riding', 'hood':
        ! Do something else
    }
],

Easy peasy. second will just match the first word it encounters from the list. In most cases, this is good enough without mucking about with NextWord() and so forth.

If you want to use topic, you use consult_words and consult_from. Here’s an example of how I use it for a ‘say’ verb:

! This is the specific action
  after
  [;
    Say:
      wn = consult_from;
      if (consult_words == 1 && NextWord() == 'your_word')
      {
        ! Do something
      }
  ],

! This is a print rule that echoes what you said
[ consultWord word i;
  for (i=0:i<WordLength(word):i++)
    print (char)WordAddress(word)->i;
];

! This is the grammar 
Extend only 'say' first
  * topic -> Say;

! This is the generic action
[ SaySub i;
  if (consult_words == 0)
    "You have nothing to say.";
  print "~";
  i = consult_from;
  print (consultWord)i++;
  while (i < consult_from + consult_words)
    print " ", (consultWord)i++;
  print "~^^";
  if (AfterRoutines())
    return;
  "Nothing happens.";
];

I’m sure you can adapt this.

The whole thing is, I’m trying to use Topic Objects that are scoped, like this:

  Object  Topics "conversational topics";

  Object  -> t_yes with name 'yes' 'please' 'ok';
  Object  -> t_no with name 'no';
  Object  -> t_hi with name 'hi' 'hello' 'hola' 'greetings';
  Object  -> t_thanks with name 'thank' 'thanks';


Verb 'ask'
    * creature 'about' scope=TopicScope             -> Ask
    * creature 'for' scope=TopicScope               -> AskFor;

  [ TopicScope;
	    switch(scope_stage) {
	        1: rfalse;
	        2: ScopeWithin(Topics); rtrue;
	        3: "At the moment, even the simplest questions are confusing.";
        }
  ];

But trying to add:

Verb 'ask'
    * 'for' scope=TopicScope                         -> AskForTopic;

Isn’t going to work. Not with a scoped topic. Not the way I’m trying it.

So yeah, I went with using topic instead. I never thought of checking the second, I just went right for grabbing the NextWord after consult_from. I might have to try that in another game. Too much grabs NextWord right now.