Roger Firth's IF pages

Home

InfAct -- about Inform NPCs

Email
Back up

This casual chatting with your NPC is all very well, but it's a bit, well, passive. There are times when you'd like to have him do as he's told.

Direct orders

The conventional way of getting an NPC to perform some action on your bidding is to use a form like USHER, GO EAST. The NPC's orders property is designed to handle this.

 
Object  usher "gentleman usher" cloakroom
  with  name 'usher' 'gentleman' 'gentle' 'man',
        description "The usher is smartly uniformed.",
        orders [;
        Go:
            "~Sorry - I mustn't leave the cloakroom.~";
        Take:
            if (noun ~= cloak) "~Thank you, but no.~";
            move cloak to hook;  give cloak ~worn;
            "~I'll just hang it on here for you.~";
        Drop:
            move noun to location;
            print_ret (The) self, " drops ", (the) noun, " on the floor.";
        Give:
            move noun to second;
            print_ret (The) self, " hands over ", (the) noun, ".";
        NotUnderstood:
            "~Pardon?~";
        default:
            "~I think not.~";
            ],
  has   animate male;

This code is really a bit too simplistic; for example, there ought to be a check that the usher is actually holding the object before he Drops or Gives it. (The Library doesn't do much validation here; ensuring sensible behaviour is down to you.) However, for our purposes, it's enough to support a little give and take.

 
>USHER,TAKE THE CLOAK
"I'll just hang it on here for you."

>INVENTORY
You are carrying nothing.

>USHER,DROP THE CLOAK
The gentleman usher drops the velvet cloak on the floor.

>ASK USHER FOR THE CLOAK
The gentleman usher hands over the velvet cloak.

If your NPC doesn't have an orders property, or has one which returns false, then the library passes the order to the life property. This is only for compatibility with older games; you're recommended always to deal with orders by providing a comprehensive orders property.

AskTellOrder

The useful package AskTellOrder.h extends the library syntax to encompass orders like ASK USHER TO TAKE THE CLOAK or TELL USHER TO DROP THE CLOAK. Cleverly, it does this by modifying the input buffer so that these two orders become USHER,TAKE THE CLOAK and USHER,DROP THE CLOAK; all you need do is Include the package.

 
>ASK USHER TO TAKE THE CLOAK
"I'll just hang it on here for you."

>TELL USHER TO DROP THE CLOAK
The gentleman usher drops the velvet cloak on the floor.

>USHER,GIVE ME THE CLOAK
The gentleman usher hands over the velvet cloak.

Questions

A natural extension of the orders syntax outlined here is the handling of questions: USHER, WHAT|WHERE|WHO IS A|THE ... One approach to this follows that suggested for conversational topics on a previous segment:

 
Object  Queries "conversational queries";
Object  -> q_cloak      with name 'handsome' 'dark' 'black' 'velvet' 'cloak';
Object  -> q_opera      with name 'opera' 'show' 'performance';
Object  -> q_time       with name 'time';
Object  -> q_bar        with name 'bar';
Object  -> q_foyer      with name 'foyer';

[ QueryScope; switch(scope_stage) {
        1: rfalse;
        2: ScopeWithin(Queries); rtrue;
        3: "At the moment, even the simplest questions are confusing.";
        } ];

[ WhatIsSub; "You seem to be talking to yourself."; ];

[ WhereIsSub; "You seem to be talking to yourelf."; ];

Verb    'what' 'who'
        * 'is'/'are' scope=QueryScope       -> WhatIs;
Verb    'where'
        * 'is'/'are' scope=QueryScope       -> WhereIs;

With the query objects and the grammar in place, the orders handlers are straightforward:

 
Object  usher "gentleman usher" cloakroom
  with  name 'usher' 'gentleman' 'gentle' 'man',
        description "The usher is smartly uniformed.",
        orders [;
            dots
        WhatIs:
            switch(noun) {
            q_opera: "~Don Giovanni tonight.~";
            q_time: print "~It's about ";
                LanguageTimeOfDay(the_time/60, the_time%60); ".~";
            }
            "~I'm afraid you've got me there.~";
        WhereIs:
            switch(noun) {
            q_cloak: if (IndirectlyContains(location,cloak))
                "~Why, here it is!~";
            q_bar,q_foyer: "~It's through there to the east.~";
            }
            "~I'm sorry, but I don't know.~";
            dots
        ],
  has   animate male;

Look at the WhoWhat.h package for further ideas.


In the last segment, we take off the brakes.