NPC conversation ideas

321 views
Skip to first unread message

Marcus Bell

unread,
Jun 16, 2015, 11:36:37 PM6/16/15
to eve...@googlegroups.com
Looking for some group ideas on modeling conversations with NPCs.

Currently, characters have a command 'talk' by which they can initiate a dialog with an NPC but after that I'm kind of indecisive about how to have a rich selection of game topics to discuss without overcomplicating things.

I want my NPCs to have a few topics they are experts on, such as vendors understanding basic commands such as buy, sell, estimate, trade, repair, etc. of course but I also want them to be reasonably educated on game topics that are not directly related to their primary occupation but would be considered general knowledge. Maybe even dynamically updated as the character progresses. 

I think what I need (or want anyway, feel free to suggest a better alternative) is a modal conversation where after greeting a NPC, the normal line by line command entry is temporarily suspended and the player's typed input is interpreted more loosely (where each word or line may not correspond to a command)

Another, possibly more realistic compromise may be to have a command called 'ask',  the target NPC, with a set of optional prepositions eg. about, for, to... then topics.
something like:
ask [NPC|qualifiers] [about|for] [name|quests|equipment|weather|services|help] <- dynamic list of topics NPC knows about

The NPC would then blurt out a single response or list of options, each one of which may have different responses. 'ask Cletus about weather' might simply return a colorful string summarizing current weather conditions.
'ask Cletus about quests' might return a list of tasks. This much is doable already but how would one implement a context sensitive ability to agree to a specific item in the list that disappears after the conversation is ended?

If he responds to 'ask Cletus about quests', he might respond with 'Well, you could help me by: rid my farm of goblins, marry my daughter, or find my lost cow.'

What is a concise way of choosing among these options without unnecessary expansion of commands? If the character just happens to be in same room as Cletus, I don't want any spurious commands accidentally interacting with random NPCs that happen to have a keyword in common with a command intended for someone else.

Marcus







Che Nador

unread,
Jun 17, 2015, 6:42:27 AM6/17/15
to eve...@googlegroups.com

I will try to answer you, but maybe other people can suggest more correct solutions. This is the trace I would follow:

npc.db.topics = {'quest': "I need coal for my forge.", 'armor': evaluate_armor, 'rumors': RUMORS}
# where evaluate_armor could be a method that evaluate the armor
# of the player, and RUMORS a global function (or just a list) that return a random sentence,
# maybe suggesting to talk to some other npcs nearby for quests

class CmdAsk(Command):
    def func(self):
        # error checking and blah blah
        answer = npc.db.topics.get(self.rhs.strip(), "I know nothing about it.")
        try:
            # try as a callable for evaluate_armor and RUMORS
            # both functions should know who is the caller, to answer correctly
            answer = answer(self.caller)
        except:
            pass
        # answer the character

ask blacksmith
Blacksmith says 'Hello, I can talk about quests, armors and rumors.'
ask blacksmith = quest
Blacksmith says 'I need coal for my forge.'
ask blacksmith = armor
Blacksmith says 'Your armor is really good.'
ask blacksmith = rumors
Blacksmith says 'Did you know that Emma lost her cow? Talk to her.'
ask blacksmith = weather
Blacksmith says 'I know nothing about it.'

It's really up to you if using '=' or 'about' to split arguments. Also you have to implement quests in a way or another.

Marcus Bell

unread,
Jun 17, 2015, 8:15:51 PM6/17/15
to eve...@googlegroups.com
Mixing arithmetic and logical operators in commands doesn't appeal to me. I am trying to stick with a natural english (oxymoron?) syntax as much as possible. 
I want a similar play experience to old adventure games, where you had to use coherent sentences to direct your character's actions on screen. 

Most commands that have more than one argument are simply wrappers for invoking external scripts to which I pass a variable number of parameters.
The topics the NPC knows about are stored on the NPC, whereas the grammar is global.

        if utils.inherits_from(npc, NPC) and self.args[1] in npc.db.preps and self.args[2] in npc.db.topics:
            script_args = []
            script_args.append(self.character.location)
            script_args.append(npc)
            script_args.append(self.character)
            script_args.append(self.args)
            npc.invoke_script("ask", script_args)

One thing I really miss about C is the switch statement. To get around needing massive if else scenarios, I have invented an ugly, decidedly unPythonic but flexible system that basically defines valid sequences of words using ordered dictionaries and bitfields that determine at which positions in a command where any one of specific groups/types of words are allowed, (such as nouns, verbs or adjectives), and whether or not a word from that group is optional or required. Partial word matching is built in, as long as all the abbreviated words have a unique match for their positional group, relatively long commands can be typed.
There is a LOT a character in the game can say, just having trouble creating a persistent state between an NPC & player that can be manipulated.

Marcus Bell

unread,
Jun 18, 2015, 8:51:57 PM6/18/15
to eve...@googlegroups.com
Aha, I have an idea... 
Persistence of a conversational context need not be explicitly enforced. 
What if I model a conversation or interaction after a chemical reaction? Where actions have reactions. 
More specifically, PC actions initiate a quantifiable imbalance that NPCs react to, seeking to restore equilibrium by emitting responses of equivalent value...
This way, the NPCs could change internal state based on character commands without necessarily 'waiting' for further interaction. 

I could have a key/value pair, one on the PC, one on the NPC, each of them referring to the other after first interaction. Subsequent interactions increment both values equally by a predetermined amount, while the passage of time, scripts and/or misc game events may alter either individually to simulate various effects. The conversational state can be described as how similar these values are to each other. When they are equal, the NPC will be passive until the PC initiates a new interaction. When inequal, if the NPC's half of the conversational state is less than the PC's, the NPC will attempt to 'catch up' by talking, offering/advancing/completing quests, etc. If the PC's token is less than the NPC's, it means the NPC is awaiting completion of a quest and/or response to a question.

So, conversations can be fairly complex with only 2 character commands: ask & tell.
Ask/tell are nearly identical commands that both echo player entered text that may optionally include references to a subset of character variables, such as name, race, age, etc. 
The most significant difference is that they have mismatched weight in terms of advancing conversations & quests.
Any NPCs close enough to hear either will only act on the info if the value of doing so would minimize imbalance with respect to that PC. 

Here is a hypothetical conversation with a newly encountered NPC. Our convo.key starts at 0 for both. 
I will use even values for questions/answers, odd values for statements. 

>ask female elf for name (this is a question, so increment PC half of convo.key by 2)
The elf turns and looks you over, a warm twinkle in her eyes.  (NPC convo.key is 0, provoking a response.)
"Hi. My name is Aerolyn," she says. "What is your name?" (NPC answered AND asked PC a new question, now she is at 4, 
>tell aerolyn My name is %name.
"My name is Darryl," you respond. (increment PC.convo.key by 1, still short 1.)
"Nice to meet you, Darryl," the sylvan waif replies. (convo.key pair is equal again, so she will be passive now.)
>ask aerolyn may i buy you a drink? (cycle repeats...)

The granting/advancement/completion of quests could be very similar, using different keys.

Well, I think this should keep me busy this weekend, back to work! :-)

Chuggur

unread,
Nov 23, 2015, 4:42:35 AM11/23/15
to eve...@googlegroups.com
Have you considered doing this with evennia's menu utility? I created a conversing_with variable to attach to characters, and came up with this system.

edit to add: I really like this method because it removes the 'key word bingo' element. I just didn't offer any command options in conversations, so players enter numbers to determine what to say.

Griatch Art

unread,
Nov 23, 2015, 5:42:47 AM11/23/15
to Evennia
Looks very cool, Chuggur. :)

I think the original post predates EvMenu, but I agree that avoiding "key word bingo" is a good thing from a user-perspective.
.
Griatch
Reply all
Reply to author
Forward
0 new messages