Equivalent to PreCondition for intransitive verbs in adv3?

Is there anything equivalent to PreCondition that can be used with intransitive verbs? Normally a precondition is invoked via something like:

modify Thing
        dobjFor(Twiddle) {
                preCond = [ isTwiddlable ]
                verify() {}
                action() {
                        defaultReport('{You/he} twiddle{s} the {dobj you/him}.');
                }
        }
;

I’d like to be able to call the same checking logic from both transitive and intransitive forms of a verb. With one or two verbs this can be solved(ish) by just replicating the code or calling it via a shim method, but this gets out of hand if there are a whole bunch of intransitive verbs that want to use the same checks.

Like for example imagine a bunch of driving-related verbs (steer, brake, accelerate, shift, and so on) where you want to do a series of sanity checks and give responsive failure messages for each (you’re not in a car, you haven’t started the car, the car is upside down in a ditch, and so on). For many it makes sense to remap the intransitive verb to a transitive form with an implicit object (>DRIVE mapping to >DRIVE THE CAR, perhaps), but that doesn’t make sense in all cases and seems like it might create hidden gotchas.

I’ve become so focused on adv3Lite that my knowledge of adv3 has become quite rusty, but I’ve just checked the adv3 LRM’s documentation on the adv3 Action class and it transpires that (as I dimly recalled), the Action class (from which IAction directly descends) defines a preCond property for action-level preconditions, so, though I haven’t tested it to make sure, it looks like you should be able to define something like:

class TwiddleAction: IAction
  preCond = [isTwiddlable]
;

The difficultly here, however, is that since there are no (direct or indirect) objects involved in an IAction, it’s unclear to me what isTwiddlable would involve. I suppose it could check whether the current actor was capable of twiddling, or whether the currently actor’s circumstances allowed twiddling (e.g., if you can only twiddle while standing up in a well lit room) or even if there are any twiddlable objects in scope, but it can’t check whether the proposed direct object of the action is twiddlable (because there is no direct object), unless, perhaps, there’s some object that’s clearly implied.

Again my adv3 is quite rusty but on an IAction I think the way to do that might be:

class TwiddleAction: IAction
   execAction()
    {
       askForDobj(TwiddleSomething);
    }
;

Where TwiddleSomethingAction is the corresponding TAction that does take a direct object.

4 Likes

Ha! That works. I hadn’t even thought to just try it, since the prototype for PreCondition.checkPreCondition() requires an object as the first arg and, as you point out, there isn’t one in this case.

It isn’t clear (from the comments in adv3’s action.t) if this is intended behavior or just a happy kludge that just happens to work (as near as I can tell there are no examples in the adv3 code for preconditions that don’t take an object). But working is working.

For posterity, here’s a complete(ish), working(ish) example. It defines two new verbs, the transitive and intransitive form of “twiddle”. All Thing instances are in principle twiddlable, but rooms either allow or disallow twiddling based on whether their twiddleAllowed flag is set:

#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>

// All the twiddle-specific action messages
modify playerActionMessages
        cantTwiddleHere = '{You/he} can\'t twiddle here. '
        twiddleDefault = '{You/he} twiddle{s} nothing in particular. '
        twiddleObj(obj) { return('{You/he} twiddle{s} <<obj.theName>>. '); }
;

// Add a property to Rooms
modify Room
        twiddleAllowed = nil
;

// Precondition to check if twiddling is taking place in a room that allows it
isTwiddlable: PreCondition
        // Verify that the containing room allows twiddling
        checkPreCondition(obj, allowImplicit) {
                local rm;

                // If no object is given, use the actor taking the action
                if(obj == nil)
                        obj = gActor;

                rm = obj.getOutermostRoom();
                if(!rm || !rm.twiddleAllowed)
                        reportFailure(&cantTwiddleHere);

                return(nil);
        }
;

// Intransitive version of the twiddle verb
DefineIAction(TwiddleI)
        preCond = [ isTwiddlable ]
        execAction() { defaultReport(&twiddleDefault); }
;
VerbRule(TwiddleI) 'twiddle' : TwiddleIAction
        verbPhrase = 'twiddle/twiddling'
;

// And the version that takes an object
DefineTAction(Twiddle);
VerbRule(Twiddle) 'twiddle' singleDobj : TwiddleAction
        verbPhrase = 'twiddle/twiddling (what)'
;

// Add twiddle-handling to Things.
modify Thing
        dobjFor(Twiddle) {
                preCond = [ isTwiddlable ]
                verify() {}
                action() { defaultReport(&twiddleObj, self); }
        }
;

startRoom:      Room 'Void'
        "This is a featureless (untwiddlable) void.  The Twiddle Room is to
        the north."
        north = twiddleRoom
;
+me:    Person;
+pebble: Thing 'small round pebble' 'pebble'
        "A small, round pebble. "
;

twiddleRoom:    Room 'Twiddle Room'
        "This is a twiddlable void. An untwiddlable void lies to the south. "
        south = startRoom
        twiddleAllowed = true
;

versionInfo:    GameID
        name = 'sample'
        byline = 'nobody'
        authorEmail = 'nobody <foo@bar.com>'
        desc = '[This space intentionally left blank]'
        version = '1.0'
        IFID = '12345'
;
gameMain:       GameMainDef
        initialPlayerChar = me
;

A thrilling transcript:

Void
This is a featureless (untwiddlable) void.  The Twiddle Room is to the north.

You see a pebble here.

>twiddle   
You can't twiddle here.

>twiddle pebble
You can't twiddle here.

>take pebble
Taken.

>n
Twiddle Room
This is a twiddlable void.  An untwiddlable void lies to the south.

>twiddle
You twiddle nothing in particular.

>twiddle pebble
You twiddle the pebble.
1 Like