Sign in to follow this  

Agent-based vs turn-based game objects

This topic is 4711 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This was part of another thread but I thought I'd clean it up and make it its own topic: It is regarding the difference between having your "game objects" act as either: 1) active 'agents' in your game, acting and responding to the world in a continuous, real time fashion or: 2) running a loop where you sequentially call an 'update' function on each object, allowing it to a) analyze changes in the game's state since its last turn, and b) act / change the game's state in a definite amount of time (ie no 'waiting' for something to happen) Note that by 'game object' i refer to things that exists in your game's world. Not neccesarily an instance of a class. For instance: a character, a sword, a planet, a box I was arguing that while the first approach may be more difficult to implement initially, it allows much greater flexibility when programming your objects, or adding a new object type into the game later. As an active agent, I can act whenever I feel like it, respond to events as they happen, or do a sleep(sleeptime) when I want to delay. I dont have to worry about how this affects the other objects at the code-level, so I can focus on what is happening around me in the game universe. I can start planning and speculating about the future, updating my plans in response to single events I receive as they happen, rather than having to re-analyze the entire state of the world and the multiple changes to it since my last turn. Of course the trick here is, how do you give EVERY object in the game the illusion that it is existing and acting in parallel/real-time with all others. -Multiple threads? -Something else? Or is there some way to alter the sequential/loop version to give that illusion as well? Thought it might be an interesting discussion :)

Share this post


Link to post
Share on other sites
Micro threads might interest you, they provide a cheaper, and less difficult, way to run many threads, as opposed to OS threads. Using a more event driven approach to AI objects might work too.
Game Programming gems 2 has a couple of articles on microthreads and AI game programming wisdom has articles on a state machine language which is excellent.

The microthreads allow you to basically program each "agent" as though it's in it's own thread, with a bit of extra code, whilst the state machine language allows you to easily code up event driven AI.

Share this post


Link to post
Share on other sites
Quote:
Original post by Satook
Micro threads might interest you, they provide a cheaper, and less difficult, way to run many threads, as opposed to OS threads. Using a more event driven approach to AI objects might work too.
Game Programming gems 2 has a couple of articles on microthreads and AI game programming wisdom has articles on a state machine language which is excellent.

The microthreads allow you to basically program each "agent" as though it's in it's own thread, with a bit of extra code, whilst the state machine language allows you to easily code up event driven AI.




I wasnt aware of the concept of micro threading before but it definitely seems like a great way of approaching this issue. I think I may have been considering something similar, allowing multiple agents to share a thread.

is microthreading applicable to .NET ? I only see libraries/info related to C or java ie python

Share this post


Link to post
Share on other sites
The basic problem is that all shared data must be accessed through mutexes and you run the risk of deadlock. Usually game objects are highly interactive and the result is that the code becomes more complicated, not less complicated.

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
The basic problem is that all shared data must be accessed through mutexes and you run the risk of deadlock. Usually game objects are highly interactive and the result is that the code becomes more complicated, not less complicated.


True, but lets assume that all accessing (or updating) of shared data is abstracted out into other sections of code which agents must use to retrieve info about the world (or change it). These sections take care of mutexes/locking/deadlocks. As you code the agent, you dont worry about it, as long as you are requesting information or changes in the 'legal' way

Share this post


Link to post
Share on other sites
Quote:
Original post by whitee115
Of course the trick here is, how do you give EVERY object in the game the illusion that it is existing and acting in parallel/real-time with all others.
-Multiple threads?
-Something else?
Or is there some way to alter the sequential/loop version to give that illusion as well?


Well, the best way I can think of to give that illusion would be to let every object get a chance to act based on the game state at the beginning of the turn, and then only apply all these actions at the end of the turn. That way, they'd all get to act "at the same time" (in the sense that nothing has changed in the game state since the the previous object acted)

Essentially it'd still just be a normal singlethreaded loop, except you don't update the game state until the end of the iteration.

The problem with threads is that you do have to, as you said, "re-analyze the entire state of the world and the multiple changes to it since my last turn.", because you never know how old your data is. If you need to collect two variables (say, your HP and your enemy's) and use them to decide on some action, then you'd prefer that they're both retrieved at the same time. But with threads, you might be paused after you've retrieved one of them, and then only get to run again much later. If one of the variables is 3 minutes old, and the other is up to date, your agent might decide on some very strange actions. ;)
if you want to avoid this, you'll have to write the mutexes into your agent as you code it, which of course makes it awfully complex. YOu can't really abstract those out into other sections of code.

Share this post


Link to post
Share on other sites
Just to clarify, micro threads don't suffer from many of the concurrency problems of normal OS threads. This is because they are usually done as cooperative, not preemtive threads. The only thing you really need to be careful of is dangling pointers, but using handles and doing a test should fix this.

-- some pseudo microthread code
while(not at destination)
{
take one step towards destination

threadSwitch()
}

The threadSwitch function cycles to the next microthread and gives it the CPU. The threads allow you to code near-linearly, without semaphores/mutexes/etc, just make queeries atomic, don't switch threads during the function call. Some care is needed, but it's not like coding with preemtive, ie OS, threads.

As for a .net implementation, if you can use inline assembly and can find out which registers/etc need to be "saved" then it's entirely possible, just remember to save the stack as well. For CLI stuff, there might be differences if you're using other platforms, ie mac/linux.

Share this post


Link to post
Share on other sites

This topic is 4711 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this