Global Unthing

Tangential to the Unthing vocabulary backstop here, suppose you want a more nuanced vocabulary handling? Instead of a canned ‘cannot see that’ message for all invocations, suppose you want some different messaging or even verb handling for absent but game-implemented items? There are a few challenges to this, the biggest being Unthing has location like any other object and most physical verbs precondition that the actor must see the item.

As an example, let us suppose that we are implementing a camera, but also implement a variety of “pictures” throughout the game. If a physical picture is present, we want to prioritize that for verbs, but absent a physical picture we would like ‘>TAKE PICTURE’ to remap to using the camera. First we need to Globalize the Unthing as follows:

// globally 'visible' item
class GlobalUnthing : Unthing
// mimicing NOTHEREMSG on purpose, for most verbs we want this.
// note usage model requires redundant vocabulary to other objects
// and UNTHING base ensures it only resolves if no others present
    notHereMsg = 'You see no <<origText>> here.  '
    origText = gAction.dobjMatch.getOrigText()
;
modify Actor
    canSee(obj) {
        if (obj.ofKind(GlobalUnthing)) return true;
        else return inherited(obj);
    }
;
modify TAction
    objInScope(obj) {
        if (obj.ofKind(GlobalUnthing)) return true;
        return inherited(obj);
    }
;

Now we have a globally visible item, that only manifests if its vocab does not resolve to another immediately present object. All that’s left is to use it!

picForTaking : GlobalUnthing 'pic/picture/photo/photograph'
    dobjFor(Take)
        maybeRemapTo(camera.isIn(gActor) &&
            rexMatch(R'take*', gAction.getEnteredVerbPhrase()),
                     Snap, camera)
;

The rexMatch is only there to ensure >GET PHOTO doesn’t take a picture. You get the idea. For this example, you would probably want to add some clarifying text if a physical picture is also present, letting the player know how to use the camera instead if that’s what they wanted.

There is also the question of global smell and sound sensing, if that makes any sense for the object in question, not covered above.

Would love to hear if anyone else went down this path, and how they managed it? So far, this is working for me!

3 Likes

The newbie extension for adv3Lite has an elegant solution for printing a canned message if the player tries to reference a body part in a command (code trimmed for concision):

bodyParts: MultiLoc, Unthing 
    'body; (my) (your) (his) (her) (this) (left) (right); head hand ...' 
    
    notHereMsg = 'Generally speaking, there is no need to refer to your
        body parts...'
    
    initialLocationClass = Room
;

The trick here is to make a MultiLoc Unthing and have it located in every Room in the game. This doesn’t solve all the problems that you’re describing for >TAKE PICTURE, but does solve some of them.

Another Unthing trick: If you place an Unthing in the player’s inventory, it won’t be listed with the >INVENTORY command, but is always available to them when referred to directly in a command. This is useful for abstractions or concepts the player knows or learns over time. (This is similar to what you’re describing about taking pictures as well, but perhaps less involved if you don’t have to worry about ambiguities between an abstraction and a present physical representation.)

2 Likes

I considered that too, but somehow that felt clumsier to me? I am revisiting that close minded thinking. Though wouldn’t you want to have it in BasicLocations to avoid awkward Booth situations? ie

initialLocationClass = BasicLocation

Lol, this I REALLY like, might play with that just for fun…, just have to consider other actor implications (which rarely are an issue for me).

2 Likes

I was also going to suggest whether sticking the Unthing in the PC like a barnacle would accomplish what you’re wanting…

2 Likes

A possible gotcha is that if a custom TAction doesn’t call inherited in its objinscope method, that action won’t honor your globalunthing…

2 Likes

Scoping rules should handle this situation. In adv3Lite a Booth is simply an enterable Container. (Hence, the “lite” in adv3Lite.)

2 Likes

Ok, I officially like this best:

Streamlined the code tremendously:

class GlobalUnthing : MultiLoc, Unthing
    // if apropo could make initialLocationClass = Actor
    locationList = [me]
    // from a previous code theft
    suppressAnnounceAmbig = true
    // not strictly necessary, I just like this better than default
    notHereMsg = 'You see no <<gAction.dobjMatch.getOrigText()>> here.  '
;

Stolen code from here, thanks again JZ!

2 Likes