Annotated objects which drive behavior

Started by
85 comments, last by bishop_pass 20 years, 4 months ago
"What makes the difference is the NPC motivation. The Caveman NPC has no interest in wealth. When he comes through, he''s not looking to accrue any wealth (he probably doesn''t even know the concept), but he IS trying to survive most likely."

Agreed MadKeith, and if you read my post that is exactly what i''m saying.

"What an NPC can do with an object has more to do with the functions of the object than the knowledge of the NPC. "

A farmer cannot wield a sword as well as warrior. That is a function of the NPC''s skill and knowlege not the objects. Lets take the caveman example: Caveman picked up a sword, and has to fight with it. Unless caveman cuts himself or somebody else by accident, my guess is that the caveman would be clubbing people with it. So do you want your caveman slashing people like a pro the first time he picks up a sword?

As to efficiency look at Diodor''s message conversation for the get the diamond situation, then think about what I said. One message is passed, a couple of pushes and pops and a couple of checks thats pretty much it. Look at the power of the container objects controlling broadcasts. Reducing broadcast will reduce unessary processing, as will letting the NPC handle what to do. Because what it wants to do with the object has more to do with the current situation which is NPC based. Also look at it like this, if you broadcast every possible action an object could perform that means the objects have to broadcast messages even if the action only happens once in the game or even on a "weekly" basis. Understand i''m not sugesting you hardcode behavior into to source code. The class definition and Level of NPC''s will bear on its abilities. But can also be extended by a character database that could be cached based on visibility or activity in the storyline, or an event object. This will allow chosen NPC''s to get smarter as the game moves on.

Comments/suggestions

-potential energy is easily made kinetic-

-potential energy is easily made kinetic-

Advertisement
quote:Original post by Infinisearch
Agreed MadKeith, and if you read my post that is exactly what i''m saying.


That''s not what I understood from your post: you said that, for instance, a horse, would know nothing aside from it being something of the type "horse". It would be up to the NPC AI to "know" what a horse is. That''s backwards. A horse is a horse The information about what a horse does, how it acts, should be stored with the horse, not with the NPC AI.

quote:Original post by Infinisearch
A farmer cannot wield a sword as well as warrior. That is a function of the NPC''s skill and knowlege not the objects.


But, you agree with me that most likely both the farmer and the warrior recognise the sword as a weapon? The sword affords fighting, or even more detailed, the sword affords slashing. Nothing is being said about the actual slashing - the action slashing can be performed with a sword, with certain modifiers based on the qualities of the sword (within the sword) and certain qualities of the user. Affordances do not change that at all.

quote:Original post by Infinisearch
Lets take the caveman example: Caveman picked up a sword, and has to fight with it. Unless caveman cuts himself or somebody else by accident, my guess is that the caveman would be clubbing people with it. So do you want your caveman slashing people like a pro the first time he picks up a sword?


The caveman would not recognise the sword as a weapon, and thus NOT pick it up to fight with. Or, in a detailed example, may find the sword looks somewhat like a club, and indeed try to club with it - which is a different action altogether, where again the caveman would not be swordfighting like a pro, but clubbing like a pro with a sword

Your argument about efficiency, I will skip, because the whole implementation of a system like affordances is something that I''m still working on. There are some very interesting possibilities, such as "affordance inheritance", which may lead to more complex "logic" on the part of NPCs, even though they have only a rudimentary AI.

It's only funny 'till someone gets hurt.And then it's just hilarious.Unless it's you.
For my "annotated cellar" thread, I have been working out some details, as of yet unposted. Here is what I am coming up with:

The data structures are broken down into actions. Ignore the low level details of how the data structure is setup for the time being. Just follow along.

We might have the following data:

ACTION: {
action: "inspect [ME] to learn Russian geography"
object: "Russian map"
goal: "Learn Russian geography"
suggestIf: agent(sees, object) or agent(knowsAbout, object)
meetsWhimIf: agent(is, scholar) or agent(is, cartographer) or
agent (hasTrait, curious)
beforeDoing: ...
whileDoing: ...
afterSuccessful: ...
afterFailure: ...

}


Now, for the processing loop...


// query the world with the agent's parameters to see which
// objects are broadcasting to him. Take into account what
// objects are visible and what objects the agent has remembered.
// The objects which broadcast will be based on whether the
// agent's goals are satisfied with using the object or
// the object meets a whim of the agent's.
// Put the suggestions in a list called agentSuggestionList.

getSuggestions (agent, agentSuggestionsList);

// pick a suggestion for something to do. Take into account
// that which is most important based on a basic priority of
// things such as survival and so forth.

toDo = pickSuggestion (agent, agentSuggestionList);

// once something to do has been selected, have the agent
// do the action listed in the beforeDoing field. This might
// be verbal direction and/or changing the game state.

doBeforeSuggestion (agent, toDo);

// Now check to see if something has changed the agent's
// decision to do what it is he was going to do. Perhaps
// the player character has advised him not to. Depending on
// his personality or relationship with the player character
// or another character, he may still do it though.

if (toDoNotNegated (agent, toDo)) {
doIt (agent, toDo);
if (successful (agent, toDo)
doAfterSuccesful (agent, toDo);
else
doAfterFailure (agent, toDo);
}




___________________________________



Edited by - bishop_pass on January 22, 2002 11:44:23 AM
_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.
As for chaining together a sequence of actions to create a sort of planning agent, I was thinking like this:

ACTION: {
object: "broom"
action: "get [ME] to use [ME]"
}

ACTION: {
object: "broom"
action: "use [ME] to push [OBJECT]"
}

ACTION: {
object: "trapdoor"
action: "push [ME] to open [ME]"
}

ACTION: {
object: "trapdoor"
action: "open [ME] to exit [cellar]"

ACTION: {
object: "cellar"
action: "exit [ME] to enter [living room]"
}


Now, in order for that to work, you have to adopt a unifying set of commands that are consistent.

Let's say the agent has the goal to "exit [cellar]". One of the above actions satisfies that. In order for that to work, the trapdoor must be opened. Assuming the trapdoor is not open already, the agent now has the goal to open the trapdoor. So, the objects broadcast their functionality to the agent again, and one of the actions will satisfy the goal of opening the trapdoor. In this case, it is: "push [ME] to open [ME]".

Now, I have left out the simple way of doing this, which is simply to push it with your hand, because that way is going to fail. Let's say that was there as an option and it did fail. But, there are other alternatives. The agent now sees a solution with the broom: "use [ME] to push [OBJECT]". Now, the agent has the goal of using the broom. So, lastly, the agent sees that to do that he must "get [ME] to use [ME]".

A chaining process works here, where the right hand side of the action string is matched to the left hand side of an already existing goal to derive a new goal.

___________________________________



Edited by - bishop_pass on January 22, 2002 11:43:21 AM
_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.
quote:Original post by MadKeithV
1. Object Exceptions: In a "magical" world, a conflict can exist between one object''s basic properties and the objects to which it applies.
An example: say you have a normal game world, with mirrors. After using it for a while, you decide to introduce a new NPC class into the game: vampires. However, you run into a problem, because all your mirrors have been programmed to reflect whoever looks into them. You have no means to override this behaviour for Vampires.

Solving this problem is actually quite easy. If you make the mirror an object that can detect characters within it''s visual range and area, then it queries the NPC whether or not it wishes to be reflected, upon which the NPC can be programmed to reply yes or no. This could also be used for games that involve character invisibility. When the character is invisible it can switch to telling the mirror "don''t reflect" instead of "yes, reflect me". I''m not saying this is the best solution, but it certainly works for more than one situation, and I''d call that pretty valuable.

As for the whole caveman thing, he should recognize it as a weapon from the object''s broadcasts. Like Madkeith said, you can use modifiers in the sword object to look at its wielder and take into account the damage done per hit. So a Caveman would do little or no damage due to improper handling while a Swordsman would inflict much more damage due to his level of skill. The point is that the Sword, or the object, is what determines this, not the NPC directly.

_________________________________________________________________

Drew Sikora
A.K.A. Gaiiden

ICQ #: 70449988
AOLIM: DarkPylat

Blade Edge Software
Staff Member, GDNet
Public Relations, Game Institute

3-time Contributing author, Game Design Methods , Charles River Media (coming GDC 2002)
Online column - Design Corner at Pixelate

NJ IGDA Chapter - NJ developers unite!! [Chapter Home | Chapter Forum]

Drew Sikora
Executive Producer
GameDev.net

quote:Original post by Infinisearch
The problem Diodor proposes can be solved with a stack based "things to do" list and allowing the announce message to say "I'm in this object".


Initially, it might appear that a stack is necessary to keep track of chained goals. However, I think an agenda based system would work better. An agenda is a list of goals to accomplish, and any item on the agenda can be selected at any time.

An agenda could be organized as a conjunction of disjunctions. Only one item in each line is necessary to satisfy that line in the agenda.

Agenda {
1: do A or B or C
2: do F to do A
3: do H to do A
4: do G to do B or C
5: do X or Y
6: do Z to do Y
7: do J to do H
}


Here the agent wants to ultimately get A or B or C done, and he also wants to get X or Y done.

To satisfy (1), he must do F and H, or if possible, he can just do G to do B or C instead. To do H, he must do J. Simulataneously, he wants to do X or Y. To do Y, he must do Z.

By using an agenda, he can work on multiple goals at the same time, and select whichever item on the agenda is most convenient at the time or has the highest priority. If any disjunction on any agenda item becomes satisfied, he can forget about the other items in the disjunction and he can then forget about any subgoals of that item.

Stacks might work also, but they seem to be more linear and focused only on the one element of the stack and lose track of the big picture.

___________________________________



Edited by - bishop_pass on January 22, 2002 1:01:24 PM
_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.
quote:Original post by Infinisearch
A farmer cannot wield a sword as well as warrior. That is a function of the NPC's skill and knowlege not the objects...


Here is the way I am proposing it be done, taken in context with what I have posted so far. We have an object, such as the sword. Associated with the sword are possible actions. So we build a data structure using a special and simple language which gives the author director control to the agents. Think in terms of a movie director who has left notes tagged on all of the props in the scene. The author is giving the choices to the actors, but guiding and scripting their behavior based on what they choose.

One of the actions for the sword:

ACTION: {
object: FabulouslyBeautifulSword
action: get [ME]
to: arm [AGENT] with [ME], possess [ME]
suggestIf: agent(sees, me) or agent(knowsAbout, me)
meetsWhimIf: agent(likes, weapons)
beforeDoing: if (firstTime) && agent(likes, weapons) ->
say "That is a truly beautiful sword."
WhileDoing: if agent(strength, weak) -> say "Oh, that is heavy!"
}

ACTION: {
object: FabulouslyBeautifulSword
action: arm [AGENT] with [ME]
to: slash [OBJECT] with [ME]
suggestIf: agent(faces, foe) && (agent(sees, me) || agent(knowsAbout, me)
}

ACTION: {
object: FabulouslyBeautifulSword
action: slash [OBJECT] wtih [ME]
to: wound [OBJECT], kill [OBJECT]
suggestIf: agent(faces, foe) && (agent(sees, me) || agent(knowsAbout, me)
}


Now, let's say the agent faces a foe. Every cycle the agent sends out the getSuggestions () function. These are added to a activeSuggestionList. Those which are reasonable are added to the agent's agenda list.

So, let's say the agenda now has this item:
1) slash Troll with FabulouslyBeautifulSword.

This instantly chains with "arm [AGENT] with [ME]" because it was also suggested and it hooks up with agenda item #1.

Anyway, ultimately, we get this on the agenda:
1)slash Troll with FabulouslyBeautifulSword.
2)arm [AGENT] with FabulouslyBeautifulSword to do #1.
3)get FabulouslyBeautifulSword to do #2.

Other items might be on the agenda also. They stay on the agenda until they either have been done, or they are no longer necessary.

Anyway, I know this all needs work an the syntax and all of that is not worked out exactly, and it is just one way of doing it among many other possible ways. But to satisfy the goal of giving agents their own intentionality and planning capability coupled with a knowledge structure which focuses on the objects themselves plus the added benefit of being able to give authorial control or guidance to the agents, I think it has merit.





___________________________________



Edited by - bishop_pass on January 22, 2002 2:04:41 PM
_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.
Satisfying multiple goals simultaneously and efficiently

Ok, let's say we have objects suggesting their use to our agent character based on his goals. For example, an agent wants to accomplish a goal: A. An object suggests that its use will accomplish A. But to do so requires D to get accomplished, based on the information included with the annotation of the object. So, the agent also wants to accomplish D.

After some processing, an AGENDA is built. Let's say it looks like this:

1) do A.
2) do D or H to do A.
3) do E or G to do D.
4) do B.
5) do H to do B.
6) do I to do H.
7) do J to do I.
8) do K to do I.
9) do C.
10) do L to do C.
11) do I to do L.
12) do M to do L.


The program puts this into graph form which is an evolving and changing data structure called the AGENDA. It looks like this:



Notice that there are three top level goals: A, B, and C. The agent desires to accomplish all three of these goals at this time. Later, due to changing events, the agent may decide it has no need to accomplish C, but that is not the case right now.

The first step is to tag the subgoals with a recursive tree walk identifying how many higher up goals are dependent on them. This is really simple:

      // walk the tree from each top goal and tag the nodesfor (each top level node N)     tagNodes (N);void tagNode (node N){    N->tag += 1;    for (each child C)         tagNode (C); }      


Look at node H in the graph. After tagging, it should have a count of 2, because two higher up goals depend on it.

The second step is to sum a cost for completing every node in the graph. Nodes which branch with 'or' sum the children by taking the minumum of their value. Nodes which branch with 'and' sum by taking the total sum of all the child values. Let's assume that each node has an individual cost or time factor to complete.

Notice that A can be completed by doing D which can be completed by doing E or G. This is a pretty simple and inexpensive solution to completing A. However , it is wasteful if we also want to complete B and C, because there are alternative solutions to completing A which help to complete B and C as well.

This is where a priority of top level goals help the agent to decide which course of action to take. If A absolutely needs to be done as soon as possible, then if the summed total to complete A via doing D and E or F is less than the other solution, then the agent should do E or F and D. Then the agent can concentrate on doing B and C. But, if A does not have a higher priority than B and C, then the other path to complete A should be chosen, because it ultimately leads to more efficient multiple goal satisfying.

___________________________________



Edited by - bishop_pass on January 22, 2002 7:18:17 PM
_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.
Bishop i understand what you guys have been saying, but i''m suggesting that u consider the overhead associated with what u are proposing before you code. In the context of one NPC and/or a couple of objects, what u propose doesn''t seem that bad. But when u start talking in the context of a game with multiple NPCs lots of objects your CPU is going to choke on all u are giving it. I do like the idea but i''m saying you have to implement it with same funtionality in a different way. I wasn''t clear I realize in the previous two posts as to what I''m proposing in terms of implementation. In the context of ''real life'' do u agree with the statement I made previously:
"A farmer cannot wield a sword as well as warrior. That is a function of the NPC''s skill and knowlege not the objects."
Now in the context of what you are saying it is the opposite. What i''m suggesting is a hybrid, where objects anounce presence, and the NPC code checks for usability againt a central ''object use''s database''. It just saves space and message passing overhead... but its seems to me it is still the same as the idea in your initial post. I say this because actions are still bound to the objects but it is acomplished through a central store and it is active instead of passive. It would also allow for your vampire problem because the property is in the realm of data and could be put in the central store. Remember that with a central store you can save space through inheritance trees. Shield, big shield, little shield... If you still feel this doesn''t reflect the same functionality as the context as what has been said by everybody else, could u please point out to me why?
I agree with u about the agenda based system, but i only mentioned the stack portion of what i was thinking. I wasn''t thinking the conjunction of disjunctions, but just a list of current "super agendas", with a stack for each "super agenda". Your method seems more flexible, and could easily be converted to a priority tree if necessary.

-potential energy is easily made kinetic-

-potential energy is easily made kinetic-

quote:Original post by Infinisearch
Bishop i understand what you guys have been saying, but i''m suggesting that u consider the overhead associated with what u are proposing before you code. In the context of one NPC and/or a couple of objects, what u propose doesn''t seem that bad. But when u start talking in the context of a game with multiple NPCs lots of objects your CPU is going to choke on all u are giving it. I do like the idea but i''m saying you have to implement it with same funtionality in a different way. I wasn''t clear I realize in the previous two posts as to what I''m proposing in terms of implementation. In the context of ''real life'' do u agree with the statement I made previously:


I am sorry, but I absolutely disagree with what you are saying. So, far, everything I have proposed can be calculated in about 1/10,000th of a second (a guess, but probably not far off the mark) with today''s or even tomorrow''s machines. I am not of the opinion that dynamic construction of trees, string hash functions, or other forms of processing are extremely expensive computationally.

Furthermore, my interest has always been with attempting to create realistic behavior which is interesting to the player. That means focusing and using CPU cycles for NPCs which the character is interacting with. I personally don''t see the value in highly simplistic algorithms which can simulate 1,000 NPCs with little realism.

I truly have little interest in developing algorithms which will effectively simulate masses of cardboard cutouts on Pentium 90mhz machines. What disturbs me the most among these boards is the constant refusal to seek newer and more complex algorithms under the mistaken belief that a little complexity means the macine will slow to a crawl. Do not shy away from a little complexity! You would be surprised at the horsepower available in today''s machines. One and two gigahertz is almost unimaginable.

So, although you believe I am dreaming up incredibly complex and CPU hogging algorithms, I am under the impression that I am formulating elegant authorial tools which have the capability to create interest from the player''s view that the agents in the world are behaving realistically and in an entertaining manner all while harnessing the power in today''s computers, but not demanding as excessive an amount of CPU cycles that you might think.

quote:Original post by Infinisearch
"A farmer cannot wield a sword as well as warrior. That is a function of the NPC''s skill and knowlege not the objects."
Now in the context of what you are saying it is the opposite. What i''m suggesting is a hybrid, where objects anounce presence, and the NPC code checks for usability againt a central ''object use''s database''. It just saves space and message passing overhead... but its seems to me it is still the same as the idea in your initial post. I say this because actions are still bound to the objects but it is acomplished through a central store and it is active instead of passive. It would also allow for your vampire problem because the property is in the realm of data and could be put in the central store. Remember that with a central store you can save space through inheritance trees. Shield, big shield, little shield... If you still feel this doesn''t reflect the same functionality as the context as what has been said by everybody else, could u please point out to me why?
I agree with u about the agenda based system, but i only mentioned the stack portion of what i was thinking. I wasn''t thinking the conjunction of disjunctions, but just a list of current "super agendas", with a stack for each "super agenda". Your method seems more flexible, and could easily be converted to a priority tree if necessary.


Then we have no argument!

___________________________________

_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.

This topic is closed to new replies.

Advertisement