[Main]
[Previous]   [Next]

Controlling the Action

Before moving on with Heidi's adventures, we should pause to think a bit more about those dobjFor and iobjFor macros we introduced in the course of the chapter, and how they're used for controlling the effect actions have on objects, since this is such a common and essential part of programming in TADS 3.

The TADS 3 library defines a fair number of actions (see the end of the en_us.t library file for their grammar definitions, which will give you some idea of the range of actions available), together with default responses. For some standard actions like TAKE, DROP, EXAMINE, OPEN, LOCK and PUT ON the standard responses are often all you need; for many of the others, such as BREAK, CLEAN, JUMP OVER or POUR the standard response is merely a message saying that the proposed action is impossible or that it has no effect. In either case, as we have already seen, you may often want (or need) to customize the library's default response. This is where the library's
dobjFor and iobjFor macros come in.

Before considering how to use these macros, it may be a good idea to determine what they mean. They are, in fact, macros that define propertysets, which are simply a short-hand device for defining a set of properties which have a common element in their name (e.g. fooTake, fooDrop and fooBar, all of which start with foo). In the case of the dobjFor and iobjFor macros, it's the name of the action (e.g. Take) plus the role of the action (dobj or iobj) that's the common element. So if you write:
 
dobjFor(Take)  
{  
   foo = 'poop'   
   bar() { say(foo); }  
}  
 
This is exactly the same, so far as the compiler is concerned, as if you had written:
 
fooDobjTake = 'poop'  
barDobjTake() { say(foo); }  
 
The above example is not especially useful, since the library makes no use of these property and method names (although you could always define them to do something useful in your own code); the library does, however, call a number of properties and methods on the direction object and indirect object of any action. For example, if the action is TakeWith the following properties/methods will be invoked respectively on the direct and indirect objects of the command:
 
remapDobjTakeWith         remapIobjTakeWith  
preCondDobjTakeWith         preCondIobjTakeWith  
verifyDobjTakeWith()       verifyIobjTakeWith()  
checkDobjTakeWith()         checkIobjTakeWith()  
actionDobjTakeWith()      actionIobjTakeWith()  
 
 
Any of these properties/methods may be defined (or invoked) using these names (and sometimes it may be useful to do so, e.g. if you want to call one action method from another); the dobjFor and iobjFor merely provide a convenient way of defining these properties without having to remember their full names; e.g.
 
dobjFor(TakeWith)
{
   remap = nil
   preCond = [touchObj]
   verify()
   {
       if(heldBy == gActor)
         illogicalAlready('{You/he} {is} already holding {the dobj/him}. ');
   }

   check()
   {
     if(gDobj == poisonousSnake)
       failCheck('You think better of it. ');
   }

   action()
   {  
      "{You/he} take{s} {the dobj/him} with {the iobj/him}. ";
      gDobj.moveInto(gActor);
   }
}

The verify(), check(), action() and preCondition methods are described in some detail in the articles "How to Create Verbs in TADS 3", "TADS 3 Action results" and "On good usage of verify() and check() in TADS 3 games" in the Technical Manual. These are all articles you will want to read sooner rather than later, but for the purpose of following this guide the discussion immediately below should suffice.
 


Getting Started in TADS 3
[Main]
[Previous]   [Next]