Becoming someone else

Hi! I’m trying to write a command "become " that changes the player to that character. I have the following code, which doesn’t work, I think because I don’t understand how “understand” works:

(understand [become | $words] as [become $person])

(prevent [become $thing])
 ~(animate $thing)
 You can't become that!

(prevent [become $myself])
 (current player $myself)
 You are already (name $myself)!

(peform [become $person])
 (select player $person)
 You are now (name $person).

I get the following message:

> become NPC
You're not aware of any such thing!

(Where NPC is a person that is in scope.) Any idea what I’m doing wrong?

peform must be perform ?

Oh, that is a typo, thank you; fixing it doesn’t seem to make the code work though.

EDIT: I found the solution; for understand I needed the following:

(understand [become | $words] as [become $person])
 *(understand $words as single object $person preferably animate)

Just discovered that my current implementation doesn’t work when the target person-to-become is in another room; obviously the problem is that the person isn’t in scope, I’m not sure how to use the (add $ to scope) predicate to only be true when performing a “become” action though (I don’t want the player to be able to perform other actions remotely). Hmm.

Unfortunately I don’t think that’s possible.

Inform 7 has the “[any thing]” token, which does the parsing without any scope checks for a particular grammar line. Dialog could potentially do the same, but it would somehow have to propagate that flag down into (parse object name $Words as $Result $All $Policy), and I’m not nearly confident enough at my Dialog skills to try to make a change like this.

(Maybe this could be connected to the policy system somehow? Either make “in scope” the default policy, or make it so that passing a special “any” policy turns off scope checking for that particular noun? As before, not nearly confident enough at my skills to do something like this.)

~(refuse [become $])

This will disable the built-in check that all nouns in an action are in scope.

Huh, does that work? I thought the scope check happened within (understand…), which would fail before it ever got to the (refuse…) stage.

~(refuse [become $])

This doesn’t seem to work when I try it.

It may only be part of the solution. I’m still learning all this.

Both @Draconis and @hlship are right here. You’d have to 1. make the parser “see” objects that are out of scope, and 2. disable the default behaviour of refusing actions that involve unreachable objects.

For 1, some kind of “any thing” rule clearly needs to be added to the library interface. In the meantime, have a look at “FIND” in the standard library. Here is a simpler variant:

(understand [become | $Words] as [become $Person])
        (filter $Words into $Filtered) %% removes of/the/this/that
        (determine object $Person)
                *(playable character $Person)
        (from words)
                *(dict $Person)
        (matching all of $Filtered)

And then you declare your become-able objects as (playable character $). The problem with this simplified variant is that you can’t “become him” (which should work if “him” is bound to a playable character), and you can’t “become table” (which should parse, but then lead to an error when the action is attempted). So the FIND code may be better.

For 2, do what @hlship suggested, but also make sure to handle the error cases in some other way:

~(refuse [become $])

(unlikely [become $Obj])
        ~(playable character $Obj)

(prevent [become $Obj])
        ~(playable character $Obj)
        As intriguing as that perspective might be, you can't play as (the $Obj).
1 Like

I’ll take a look at FIND and try to understand it! Thank you.

it’s a context in with out-of-scope is to be expected (the classical “activating gizmos in very different places” puzzle) ?

Best regards from Italy,
dott. Piergiorgio.