[Reality] we're the most frontingest

glyph at divmod.com glyph at divmod.com
Thu May 18 23:45:37 CDT 2006


=== Name Resolution, findProviders(), and the search() for intelligence ===

search() is currently pending deprecation.  In order to make puzzles that are
properly secure, we need to eliminate it and its attendant unnecessary
complexity.

The first thing we need to do is create a "perception" data structure, which
will be stored in the 'intelligence' for a player.

In the case of "purely server-side" UI, like the text server, this is simply a
dictionary mapping names to lists of perceived objects with that name.  Parsing
to actions can then happen entirely in text server UI code; no interaction with
the world object graph is required to identify the user's *intent*, and
formulate an Action instance which represents that intent.  There is already an
API for making sure that users can securely access the objects they are
referring to, 'proxiedThing'.  Since the values in this list are Things
already, they can be passed directly to this existing API.

(Although we'd like to suggest a name change: proxiedThing implies that the
return value is also a Thing, it could be something else, so maybe
'proxyForThing' or 'facetForThing'?)

This parsing separation should then also provide a foothold for disambiguation;
it can reorder and discard from the ambiguous list of potential targets,
eventually presenting the user with a list of long descriptions for the objects
which they might have been referring to, which actually make sense.  Initially
this will simply be reordering based on proximity; eventually, we can add
information to the "perception" object about whether objects are apparently
reachable, actual physical objects or simply concepts (like "the air" or "that
sound") which don't make sense to use as targets for a particular action.  The
menu of available targets for a particular action can be presented also without
interacting with the world's object graph: all information required is present
in UI data structures.

It's important to keep in mind that GUI clients later (the faucet will flow
again!) will use names only *client*-side, which will be represented as
selectable lists of objects, also potentially with names, to provide the user
with a diverse set of input mechanisms.  These names will be mapped on the
client to identifiers which are unique to the session (to make cheating harder
- no reason to allow players to persistently to refer to objects they can't
access from their client).  Ambiguity will therefore be handled *almost*
entirely on the client; for special-case parsing it would be nice to also send
along a string to the server, but in general this will not be used; a
structured expression representing the action will be sent to the server.

    (As an aside about GUI clients, imagine this experience.  You type "get
    qui" and an intellisense-style menu pops down which lists all of the
    objects whose names contain "qui" at a word boundary that are currently
    visible to you.  You select "the quiche I am holding" from a list that says
    "the quiche I am holding" and "the quiche that the baker will immediately
    kill me if I attempt to pick up".  The text field then fills in with the
    full name of the selected quiche, along with an icon and a color indicating
    that it is an *object* with *identity*, not just some crappy string.  No
    menu needs to be presented saying "which quiche?" from the server.)

=== proxy() design patterns, and quantum fronting in Imaginary ===

We are thinking about implementing wearable sunglasses and night-vision
goggles.  We want to implement it by having a IProxy powered up on the player
when it puts on the glasses and powered down when it takes them off.  The
current proxy() system is basically designed right for this with respect to
visibility events, but seems to be missing one necessary feature for it to be
complete.  (I'll get to explaining what that is in a moment...)

As a first step, the implementation of LocationLighting.proxy needs to be
changed to _always_ wrap its contents with an IlluminatedThing wrapper, which
will provide IVisible and have an API for mutating the luminous intensity
associated with it.  (I think that somebody needs to really understand the
difference between luminous intensity and luminous flux in order to determine
what we're actually talking about as our virtual photon makes its way outward
from its source to its observer, but I digress.)

In the case of [un]illuminated environments -- and more generally, in any
implementation of proxy() that might want to interfere with a player's ability
to see or interact with objects -- there are a few general types of
interaction:

    - see an object (.isOrExtends(IVisible))
    - designate an object as a target of some kind (.isOrExtends(IDesignatable))
      two other parent interfaces extend this one:
        - physically interact with an object (.isOrExtends(IReachable))
        - remotely indicate an object (.isOrExtends(IAimedTarget))

I note "isOrExtends" here because in the visibility case as currently
implemented, it is slightly misleading to think there is only one interface we
need to worry about for security reasons; even if a player can't see an object
at a particular time, they might indicate it later in some other way, and the
illumination system needs to deal with their ability to (for example) pick up
an object off the floor when it's dark, that they previously saw when it was
light.  The design for this system, as relayed to me by Chris, is that a roll
will be made vs. a player's perception and orientation stats with the final
perceived illumination level as a modifier.  In the "well-lit" case this check
will always pass, but there is a chance you will or will not be able to pick up
stuff that you have previously seen if a room goes dark or you are blinded.

Note that in the visibility case "IVisible" generally suffices (at least for
now) but in the "pick stuff up" case, you have to be able to substitute "pick
stuff up", "eat", "shoot with a laser beam", or any number of I<X>Target
interface arguments to proxy().

There are some systems (light being the most obvious and one of the more
complex ones) which will need to mutate an object at various points in its
discovery path through findProviders, but not be able to return an object that
actually provides (or rejects) the requested interface until they have actually
reached the end of the path and know who the observer / actor will be.

The proposed solution here is to allow proxy() to return both providers of the
requested interface and providers of a new interface, IWaveform.  IWaveform has
one method: collapse(observer), which returns a provider of the originally
requested interface passed to proxy().  collapse(player) will be called at the
end of the resolve() phase of Action, if the given things do not implement the
interface they are supposed to implement at that point (and, obviously, do
provide IWaveform; otherwise this is simply an error.)

For example, the IlluminatedThing wrapper will implement IVisible and
IWaveform, since it knows what to do in the case of visibility, but it provides
a general "can I reach this" implementation for _all_ tool and target
interfaces, not merely those it can explicitly single out.  i.e., for any
interface LocationLighting.proxy is passed that isOrExtends(IDesignatable), an
IlluminatedThing will be returned, whose collapse() method will make the
appropriate rolls: can I see this?  can I interact with it?  what's the chance
I will hit it if it's an IAimedTarget?  how long will it take to rummage for
it?  (the last only once we implement some kind of actions-taking-time system).





More information about the Reality mailing list