This one starts out from what I said at
http://planeshift.oodlz.com/wbboard/thread.php?threadid=11448&boardid=11&styleid=3&sid=90365f71c4344c72c9c96c243feb6f92 but is augmented by having read the code in ./src/npcclient/npcbehave.h
The fact that the ideas are so similar to what I already posted was what prompted me to start this thread, since I figure that if we are already thinking that much along the same lines that my ideas will hopefully be a fairly logical extension of what you are already doing.
The initial topic was about NPC AI and how its realism would make a big difference to how the game plays.
Looking at the code, there is a similar basic idea that NPC\'s can have behaviour types and motivations (needs) but the empahsis here, I think, is a bit different. The behaviour I am talking about is not so much how the NPC model is animated as what the Pattern of behaiour that it will exhibit of its own volition or in reaction to the environment around it.
What occurred to me when I read the source was that though it would implement AI to a certain extent, it would end up falling down pretty heavily because of the inflexibility of the general mechanism when it comes to getting NPC\'s to shift from one behaviour to another.
So let me rehash a bit more clearly what I posted earlier ...
Take the idea that people\'s behaviour tends to depend on where they are and what they are already doing. If we are eating dinner, we are unlikely to suddenly get up and start a fight all at once.
This sort of circumstance, where our reactions have a limited but predictable relism under particular types of situation is what I will be calling context.
When we are eating dinner that would be one context, with a set of likely behaviours, and when we are standing watch at the village gates that would be another context with another set of likely behaviours.
The way I see it, you would get a much more flexible system if you had a class called npcContext that had the behaviour class as a fundamental structure within it.
So now, supposing that we are defining our NPC class description and one part of that class contains a list of contexts. We might have several typical types of context within the game that nearly every NPC would have defined as part of their description. For example:
Combat
Patrol
Lounging
Hunting
pcInteraction
npcInteraction
pcFollowing
npcFollowing
There could be dozens of these, but in any one of those contexts, there are going to be a limited number of likely behaviour types, ie a limited number of things that the NPC is likely to do of their own accord if they are not interrupted by some event external to themselves.
Simplistically, each thing that they might be doing could be assigned a probability of them deciding to do from one moment to the next. So we could assign each type of behaviour a percentage likelihood of being what the NPC will decide to do at the next tick.
In the case where an NPC is Lounging about with a bunch of compatriots, we might have something like ...
0-10 Stroll about
11-20 Decide to have a nap
21-30 Decide to have a chat with one of the others
31-40 Decide to go have a look at some relevant object / person etc
41-50 Decide to have a look beyond their immediate surroundings
51-60 Decide to leave their immediate surroundings
etc
Some of those things would clearly involve the NPC switching from one context to another. If the NPC decided to leave their physical surroundings they would literally be in a differnt physical context and so would be likely to perform a completely different set of actions.
But the idea of a table of rolls is obviously too simple on its own. If we checked the table every server tick, we would almost certainly see our NPC\'s starting to do one thing and then changing to do something else a few ticks later. So we need something to counter that.
Normally, we oppose distractions to and disturbances to completing or continuing what we are currently doing with our level of incentive to keep doing it. This is pretty much like the idea of needs that is defined in the npcbehave.h file.
In this case though, we are not talking about what will prompt us to undertake some action to begin with, but our natural inclination to keep doing it once we have started.
So, as well as having a roll level that decides what we will do when we do decide to do something else, we also have an incentive level for each type of behaviour that tells us how likely we are to keep doing that once we have started.
One way to implement that incentive level might be to have a starting value that decrements with every tick, thus making it more likely that we will be willing to do something else after we have been doing what we have been doing for a certain amount of time.
Effectively:
Start doing something.
At the next tick decrement our incentive to keep doing it
Roll to see if we keep doing it or stop of our own accord
Roll to find out what other activity we might be doing and ...
Consider how urgent that new thing is. This is a bit more like the need rates defined in the npcbehave.h file. If the thing is urgent enough, then it may overcome our incentive to keep doing what we are already doing.
For example, if we suddenly need to go to the toilet, that might take precedence over having a seat at the camp fire.
Then again, we might be cooking dinner at the camp fire and going to the toilet might have to wait a bit. The incentive to finish cooking dinner might well be greater than the urgency of stopping to go to the toilet.
Whichever the case, at this point we want to check to see how urgent the new demand on our attention is and stop doing what we are doing if our incentive to keep doing it is less.
We have two issues we have to consider at this point. Is what we are doing something we will want to go back to after we have done the other thing and will we still want to go back to it if the other things takes a long time or has the sort of critical urgency level that means that everything else gets thrown out of the window?
So we need to keep track of whether or not our behaviour is one that we might return to and we need to keep track of whether or not what interrupts us will overwrite any desire to do that.
Obviously we could simply decide that, if any interruption was sufficiently more urgent than our remaining incentive to complete our current activity, then we would scrap that activity even if we would normally go back to it.
So far all of this is within the range of likely types of self initiated behaviour in a particular context. But what happens when someone or something comes along and intrudes on our self contained context?
This is not so different from what happens when we check to see if our next possible activity is more urgent than our incentive to keep doing what we are already doing.
In fact we can elegantly resolve parts of the evaluation of each type of situation by having a method that we call upon the NPC that is something like
NPC->newEvent(evSource, evDescription, evUrgency)
and which results in us simply checking to see if our NPC is willing to leave off what they are currently doing to do whatever the newEvent requires.
This is where the idea of contexts becomes powerful because when the event causes us to switch contexts we can move to a completely new set of behaviours that are completely relevant to and consistent with that context.
Where\'s the difference between doing things that way, and just setting up a list of all the possible behaviours that an NPC might get invoved in?
To begin with, if you already have basic definitions of how NPC\'s react in a certain context then you can inherit those definitions more easily than defining them from scratch.
Better still. If every orc, for example, inherits a certain set of basic contexts that they might act within and every scout inherits a set of contexts that they might act within, then you can define an orc scout\'s basic behaviour pattern by simply inheriting both contexts.
More flexibly still, with a bit of ingenuity parts of the scout context can moderate parts of the orc context andor vice versa, so that an orc scout would be markedly different from a human scout in the way it behaves with very little effort required from the programmer.
But that is only the half of how flexible using a context class could be. You could also implement contexts that were specific to the local surroundings and that endowed every NPC existing within or entering them to inherit that context\'s pattern of activities and behaviour.
By having context supersets for different types of NPC you could have an extremely flexible, easy to implement system for realistic a diverse behavioural patterns in different types of NPC.
Orcs might have a whole set of default modifiers on inherited behaviour types that applied maximum and minimum limits on how much they might exhibit a type of behaviour and proportional or additive modifiers that directly affected the behavioural contexts that they inherited.
The same might be applied to scouts, warriors etc so that you could have a set of contexts with default parameters that were dynamically affected by a variety of aspects of the NPC\'s type, each of which applied its own modifiers to that NPC\'s patterns of behaviour in different contexts.
eg a Female, Orc, Cleric, Towndweller might have each of those attributes triggering modifications to the basic behaviour contexts that they inherited and so behave in a completely different way to a Male, Human, Barbarian, Plainsman inheriting the same basic context data and starting out in identical circumstances.
Try to visualise how all of that would work in the setting of a bunch of orcs around a campfire being observed by an unseen PC.
One orc is on patrol and is circuiting the boundary of the area. Another is simply walking about stretching his legs.
Another is sitting by the fire when he feels an irresistable desire to get up and go to the toilet. On the way to a darkened spot, he is intercepted by another orc who has had a sudden desire for conversation, but the first orc is caught up in the urgency of the need to relieve himself while the talkative one is equally caught up in the need to say what he has to say. Having relieved himself, the first orc finally responds to the second.
Because we are not programming a set sequence of actions but instead a pattern of possible actions, every time the server is reset, that campfire scene will look different and the game will get a very natural, realistic and atmospheric quality.