Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[INFORM] general NPC discussion

8 views
Skip to first unread message

green_g...@my-dejanews.com

unread,
Sep 16, 1998, 3:00:00 AM9/16/98
to
long time no post :)

I'm starting ANOTHER new game (yeh, yeh, I don't want to hear it), and this
time I'm looking into creating multiple, complex NPCs (that's a dozen or so
fairly normal NPCs that the user can interact with extensivly, not an NPC
with a personality problem - though that would be interesting... hmmm).

I want my NPC's to have a "shared" view of the world (ask any of them and
they will tell you that the stunning set of concrete park benches in the
kitchen was a gift from Aunt Bertha) as well as individual experences (joe
might add that he had thrown his back out trying to pick them up one time)
and opinions (while sally thinks they are horribly ugly).

Anyone out there with experience doing this who is willing chat with me?
E-mail is fine for the shy. Inform programmers preferred - but hey, I'm
desperate.

Thanks,
Kathleen

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum

Michael S Gentry

unread,
Sep 16, 1998, 3:00:00 AM9/16/98
to

green_g...@my-dejanews.com wrote in message
<6tpih9$82k$1...@nnrp1.dejanews.com>...

>long time no post :)
>
>I want my NPC's to have a "shared" view of the world (ask any of them and
>they will tell you that the stunning set of concrete park benches in the
>kitchen was a gift from Aunt Bertha) as well as individual experences (joe
>might add that he had thrown his back out trying to pick them up one time)
>and opinions (while sally thinks they are horribly ugly).


Here's what I'd do:

First, I'd create my list of conversation topics as a series of objects (all
contained within one umbrella object, for ease of organization), like this:

Object topics;

Object -> t_weather "weather" with
name "weather";

Object -> t_benches "benches" with
name "concrete" "park" "benches" "bench";

[etc.]

...and redo the ask/tell grammar so it looks like this:

Verb "ask" "query"
* animate 'about' scope=Conversation -> Ask

[ Conversation;
switch (scope_stage)
{ 1: rfalse;
2: ScopeWithin(topics); rtrue;
3: "At the moment, you can't think of anything intelligent to say
about
that, so you wisely keep your mouth shut.";
}
];

(This is essentially from the Designer's Manual. I couldn't tell from your
post whether you're a beginner or an experienced implementor, so just skip
over anything that bores you.)

(Then again, you mentioned that this is *another* new game, so I guess
you've done this before. Oh, well.)

Anyway, next I would give each conversation topic a description, which
represents the general knowledge that anyone would impart if you asked them.

Object -> t_benches "benches" with
name "concrete" "park" "benches" "bench",
description
[; "~You mean the ones in the kitchen? They're a gift from Aunt
Bertha,~ says ", (name) noun, "."; ],
has pluralname;

Then, I would declare a general property -- let's call it, oh,
"personal_slant". Give each NPC a personal_slant routine, which looks like
this:

Object Joe "Joe" with
name "Joe",
personal_slant
[; switch(second)
{ t_weather: "~Personally, I think it's gonna rain.~";
t_benches: "~Man, those things are heavy,~ Joe adds. ~I threw
my back out once trying to lift one.~";
}
];

Object Sally "Sally" with
name "Sally",
personal_slant
[; switch(second)
{ t_weather: "~But surely it'll stay sunny for the wedding,~
Sally adds hopefully.";
t_benches: "~Just between you and me, those benches are
terribly ugly.~";
}
];

Now, what you do is set it so that whenever you ASK someone ABOUT a
conversation topic, it first prints the general description of that topic
(the knowledge that everyone knows), and then prints the personal_slant. You
could do this by twiddling with the AskSub routine, but it might be easier
just to copy the code into each person's "life" property, like this:

Object -> Joe "Joe" with
name "Joe",
life
[; Ask:
PrintOrRun(second, description);
PrintOrRun(self, personal_slant);
rtrue;
];

So, when the player types ASK SALLY ABOUT BENCHES, the game returns:

"You mean the ones in the kitchen? They're a gift from Aunt Bertha," says
Sally.
"Just between you and me, those benches are terribly ugly."

You'll have to tinker with it some to get exactly right for your game, but
essentially that's how I'd start. The important thing is to set up your
topics as objects rather than just checking the first word after "about",
which is how the libraries are normally set up to handle ASK and TELL. You
get much more flexibility that way.

One thing I just thought of: you'll have to find some way of marking objects
that character's *don't* know about. (As in, >ASK BOB ABOUT BENCHES --
"Never heard of them," says Bob.)

You could make a "known_by" property for each topic, maybe. It would look
like this:

Object -> t_benches "benches" with
known_by
[; if (noun==Sally or Joe) rtrue; else rfalse; ],

...with the name of each person who knows about the topic in the conditional
statement. Then, each person's life routine would look like this:

life
[; Ask:
if (second.known_by()==0)
"~Never heard of ", (itorthem) second, ",~ says ", (name) noun, ".";
PrintOrRun(second, description);
PrintOrRun(self, personal_slant);
rtrue;
],

So if you ASK BOB ABOUT BENCHES, the known_by routine returns false and you
get an appropriate "I don't know" sort of message. Whereas if you ask Joe or
Sally, it goes ahead with the normal answering routine.

I'll post this so that if anyone who's better at this than me happens to
find something really wrong with my code, or knows of a much easier way,
they can say something. If you don't understand any of this, just e-mail me.

And remember...

--M
================================================
"If you don't eat your meat, you can't have any pudding.
How can you have any pudding if you don't eat your meat?"

Mary K. Kuhner

unread,
Sep 17, 1998, 3:00:00 AM9/17/98
to
In article <6tpih9$82k$1...@nnrp1.dejanews.com>,
<green_g...@my-dejanews.com> wrote:

>I want my NPC's to have a "shared" view of the world (ask any of them and
>they will tell you that the stunning set of concrete park benches in the
>kitchen was a gift from Aunt Bertha) as well as individual experences (joe
>might add that he had thrown his back out trying to pick them up one time)
>and opinions (while sally thinks they are horribly ugly).

I haven't tried this, but my first try would be to make a routine
NPC_common_knowledge(foo), and have the conversational routines
for each NPC call it (with an argument of the conversation topic)
before they do their own processing. The NPC_common_knowledge
routine would be a big switch statement giving the things that
everyone knows. Then each NPC could follow up with their own
little switch statement for the things about which they have
individual opinions.

Alternatively, if you want to override the common knowledge in
some cases, start with a switch statement in the NPC and have
it call NPC_common_knowledge only as appropriate.

You will need to pay careful attention to formatting issues when
you put all this stuff together, but I think it should work.

Mary Kuhner mkku...@genetics.washington.edu

Jonadab the Unsightly One

unread,
Sep 18, 1998, 3:00:00 AM9/18/98
to
Michael S Gentry <edr...@sprynet.com> wrote in article

> Now, what you do is set it so that whenever you ASK someone ABOUT
a
> conversation topic, it first prints the general description of
that topic
> (the knowledge that everyone knows), and then prints the
personal_slant. You
> could do this by twiddling with the AskSub routine, but it might
be easier
> just to copy the code into each person's "life" property, like
this:
>
> Object -> Joe "Joe" with
> name "Joe",
> life
> [; Ask:
> PrintOrRun(second, description);
> PrintOrRun(self, personal_slant);
> rtrue;
> ];

One improvement here that would make your life easier would be
to put that in a class (fortunately, life is additive):

Class NPC
with life [;


Ask: PrintOrRun(second, description);
PrintOrRun(self, personal_slant);
rtrue;
];

NPC joe "Joe"
with name "joe",
personal_slant [;
etc...

> life
> [; Ask:
> if (second.known_by()==0)
> "~Never heard of ", (itorthem) second, ",~ says ", (name)
noun, ".";
> PrintOrRun(second, description);
> PrintOrRun(self, personal_slant);
> rtrue;
> ],

Again, though, just put that in the NPC life routine and
have all your non-player NPC characters inherit it.

(Yes, it's deliberate ;-)


--

Dyslexic email address: ten.thgirb@badanoj

Joe Mason

unread,
Sep 18, 1998, 3:00:00 AM9/18/98
to
In article <6tpih9$82k$1...@nnrp1.dejanews.com>,
<green_g...@my-dejanews.com> wrote:
>I want my NPC's to have a "shared" view of the world (ask any of them and
>they will tell you that the stunning set of concrete park benches in the
>kitchen was a gift from Aunt Bertha) as well as individual experences (joe
>might add that he had thrown his back out trying to pick them up one time)
>and opinions (while sally thinks they are horribly ugly).
>
>Anyone out there with experience doing this who is willing chat with me?
>E-mail is fine for the shy. Inform programmers preferred - but hey, I'm
>desperate.

Not this exactly, but it shouldn't be too hard. However you're handling the
conversation (I'll assume with a switch statement and topic objects), have
a property of the NPC class which answers the question in a general way.

Class NPC
with
converse [topic;
switch (topic)
{
ParkBenches: print "~The ones in the kitchen? They were a gift from
Aunt Bertha,~ says ", (the) self, ".";
AuntBertha: print "~She's a little eccentric,~ ", (the) self,
" confides.";
}
];

NPC Joe
with
converse [topic;
self.NPC::converse(topic);
switch (topic)
{
ParkBenches: print " He groans. ~I think I threw out my back trying to
pick them up one at a time.~";
AuntBertha: print " ~I should have killed her when I had the chance.~
He suddenly looks startled, and gives a wan smile. ~Uh, heh heh,
just a little joke.~";
}
];

NPC Sally
with
converse [topic;
self.NPC::converse(topic);
switch (topic)
{
ParkBenches: print " ~I think they're horribly ugly, myself.~";
AuntBertha: print " ~But we all love her anyway.~";
}
];

Notice that none of these print newlines. That's so that if an NPC doesn't
define a converse routine, so that NPC::converse is used directly, there's no
difference: the line ends, without spaces or newlines, right after the text
that's printed. Whatever routine calls converse() (probably Life, but maybe
the "talk about" grammar calls it directly - depends on how you structure it)
would have to print a newline afterwards.

You may also want to make converse return true if something is printed, and
false if nothing, unless the NPC definitely WILL be saying something for each
topic.

Joe
--
I think OO is great... It's no coincidence that "woohoo" contains "oo" twice.
-- GLYPH

0 new messages