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?
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.
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.)
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).