Roger Firth's IF pages

Home

InfAct -- about Inform NPCs

Email
Back up

You probably know that the standard library verbs (in Grammar.h) include a number of grammars which include the creature token specifically targetted at NPCs.

 
Verb 'give' 'pay' 'offer' 'feed'
        * held 'to' creature        -> Give
        * creature held             -> Give reverse
        * 'over' held 'to' creature -> Give;
Verb 'show' 'present' 'display'
        * creature held             -> Show reverse
        * held 'to' creature        -> Show;
Verb 'wake' 'awake' 'awaken'
        * creature                  -> WakeOther
        * creature 'up'             -> WakeOther
        * 'up' creature             -> WakeOther;
Verb 'kiss' 'embrace' 'hug'
        * creature                  -> Kiss;

Verb 'ask'
        * creature 'about' topic    -> Ask
        * creature 'for' noun       -> AskFor;
Verb 'tell'
        * creature 'about' topic    -> Tell;
Verb 'answer' 'say' 'shout' 'speak'
        * topic 'to' creature       -> Answer;

In this segment, we'll talk about the first group of actions -- Give, Show, WakeOther and Kiss -- which cover forms of interaction where you don't need to say anything. (A later segment will look at Ask, Tell and Answer.) These four actions, plus Attack and ThrowAt, are passed to an NPC's life property.

 
Object  usher "gentleman usher" cloakroom
  with  name 'usher' 'gentleman' 'gentle' 'man',
        description "The usher is smartly uniformed.",
        life [;
        Give:
            if (noun ~= cloak) print_ret (The) self, " courteously refuses ",
              (the) noun, ".";
            move cloak to hook; give cloak ~worn;
            "~I'll just hang it on here for you.~";
        Show:
            if (noun ~= cloak) print_ret (The) self, " smiles politely.";
            "~I don't think I've ever seen one as dark as that!~";
        WakeOther:
            "~Sorry, I must have dozed off for a minute.~";
        Kiss:
            print_ret "On second thoughts, you don't know ", (ItOrThem) self,
              " all that well.";
        Attack:
            print_ret (The) self,
              " looks startled, but doesn't otherwise respond.";
        ThrowAt:
            print (The) self, " deftly catches ", (the) noun;
            if (noun ~= cloak) " and returns it to you.";
            move cloak to hook; give cloak ~worn;
            " and carefully places it on the hook.^
              ~Things not been going too well today?~";
            ],
  has   animate male;

That's enough to handle some simple actions involving you and the NPC.

 
>SHOW THE CLOAK TO THE USHER
"I don't think I've ever seen one as dark as that!"

>THROW IT AT HIM
(first taking the velvet cloak off)
You take off the velvet cloak.
The gentleman usher deftly catches the velvet cloak and carefully places it on
the hook.
"Things not been going too well today?"

>KISS THE USHER
On second thoughts, you don't know him all that well.

Extending the life property

Suppose you wish to add some extra forms of interaction. For example, you might fancy getting up close and personal with your NPC, specifically distinguishing between hug/embrace, touch/feel/pat, stroke/caress, fondle/grope, and kiss. Some appropriate verbs are already defined, but their behaviour isn't as well-tuned as you'd like. Also, whereas you can trap the Kiss action in your life property, the same isn't by default true for the Touch action. These lines are from Grammar.h.

 
Verb 'kiss' 'embrace' 'hug'
        * creature                  -> Kiss;

Verb 'touch' 'fondle' 'feel' 'grope'
        * noun                      -> Touch;

The matching action routines are in VerblibM.h (for clarity, I've change L__M() calls into plain print statements):

 
[ KissSub;
  if (ObjectIsUntouchable(noun)) return;
  if (RunLife(noun,##Kiss)~=0) rfalse;
  if (noun==player) "If you think that'll help.";
  "Keep your mind on the game."; ];

[ TouchSub;
  if (noun==player) "If you think that'll help.";
  if (ObjectIsUntouchable(noun)) return;
  if (noun has animate) "Keep your hands to yourself!";
  "You feel nothing unexpected."; ];

To achieve the desired effect, we need to do three things:

  1. change the existing library grammar to match the extended verbs
  2. create appropriate new action routines; from examining the KissSub() routine, it's clear that RunLife() is the key to invoking the Life property
  3. extend our NPC's life property to handle the new actions

First, here's a possible grammar:

 
Extend only 'embrace' 'hug' replace
        * creature                  -> Hug;

Extend only 'touch' replace
        * creature                  -> Pat
        * noun                      -> Touch;

Verb 'pat'
        * creature                  -> Pat;

Extend only 'feel' replace
        * creature                  -> Stroke
        * noun                      -> Touch;

Verb 'stroke' 'caress'
        * creature                  -> Stroke;

Extend only 'fondle' 'grope' replace
        * creature                  -> Fondle
        * noun                      -> Touch;

Second, we need action routine which mimic the default behaviours of KissSub() and TouchSub():

 
[ HugSub;
        if (ObjectIsUntouchable(noun)) return;
        if (RunLife(noun,##Hug) ~= 0) rfalse;
        if (noun == player) return L__M(##Touch,3,noun);
        L__M(##Kiss,1,noun);
        ];
[ PatSub;
        if (ObjectIsUntouchable(noun)) return;
        if (RunLife(noun,##Pat) ~= 0) rfalse;
        if (noun == player) return L__M(##Touch,3,noun);
        L__M(##Touch,1,noun);
        ];
[ StrokeSub;
        if (ObjectIsUntouchable(noun)) return;
        if (RunLife(noun,##Stroke) ~= 0) rfalse;
        if (noun == player) return L__M(##Touch,3,noun);
        L__M(##Touch,1,noun);
        ];
[ FondleSub;
        if (ObjectIsUntouchable(noun)) return;
        if (RunLife(noun,##Fondle) ~= 0) rfalse;
        if (noun == player) return L__M(##Touch,3,noun);
        L__M(##Touch,1,noun);
        ];

Finally, the extended life property:

 
        life [;
            dots
        Hug:
            print_ret "You clasp ", (ItOrThem) self, " in a comradely embrace.";
        Pat:
            print_ret (CThatOrThose) self,
                " steps slightly back, eyeing you cautiously.";
        Stroke:
            "Warm, firm, smoothly curvaceous yet pulsing with life.";
        Fondle:
            print_ret "You run your hand through ", (the) self,
                "'s long dark hair.";
        Kiss:
            print_ret "On second thoughts, you don't know ", (ItOrThem) self,
                " all that well.";
            dots
            ],

I'm sure your imagination is sufficient to tell you how this will perform at run-time.

(You could probably achieve much the same effect by using a before property instead of life. However, I'd recommend following in Graham's footsteps and use life for NPC interactions, unless you're sure you know what you're doing.)


Time to start getting vocal.