![]() |
|
Threaded concurrent AI? |
J-Gamer
Member #12,491
January 2011
![]() |
I'm thinking of a project in which the AI might take many cycles to complete its thought process. The problem is that I'll have to be able to get player input(without any lag) while the AI is thinking. I already thought of just doing a full AI cycle each timer tick, but then I got a thought about threads. What if I would declare a thread in which the AI does its thinking, and use the main for user input handling/rendering(or split it up even further). Couldn't this result in much cleaner code? I have a few questions about this:
I'm open to any programming paradigms you might throw at me. I'm someone who wants/likes to learn the right way of doing things " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
AMCerasoli
Member #11,955
May 2010
![]() |
If you want something more complicated, elaborated, etc... check out Peter Wang´s ex_thread files... The tutorials in the wiki give you the concept so you can get it faster, then you can complicate you code all you want. J-Gamer said: How well does timing work when using multiple threads? I want to be able to limit the amount of cycles the AI can have per second. Peter's examples shows you that you can create events inside a thread. you can do whatever you want inside a thread. But you must be very carefully with data exchanging. Insted of a int main(){} you have a static void *thread_func(ALLEGRO_THREAD *thr, void *arg){} Quote: Lastly, should I even be using threads for this? If not, what do you need them for?
You could do it, but I think that instead of making clearer your code, could make it more complicated if you're not careful, since you're going to need to exchange a lot of data, depending on your game of course. To me, a thread for just the AI is too much, but I may be wrong.
|
Matthew Leverton
Supreme Loser
January 1999
![]() |
I've used threads for AI before. It works well. For fun, you can even have the AI simulate key presses as a second player would. Thus the AI is just another person pressing buttons to your game. (Depends on the type of game if that makes any sense.) I don't know if Allegro event queues are thread safe. Timing should work just fine in multiple threads. |
Thomas Fjellstrom
Member #476
June 2000
![]() |
Matthew Leverton said: I don't know if Allegro event queues are thread safe. Yeah, they are afaik. Thats why they were designed to be so annoying. Events are coppied into each queue, etc. But when I last looked at it, it was thread safe. -- |
Matthew Leverton
Supreme Loser
January 1999
![]() |
Well there are two different things to worry about:
|
Thomas Fjellstrom
Member #476
June 2000
![]() |
Matthew Leverton said: can the same event be registered to queues in different threads? I assume yes. Quote: can the same queue be accessed by different threads? Each event source at the very least has a mutex/lock. I'd think the event queue may as well. I'd have to check. -- |
Sirocco
Member #88
April 2000
![]() |
Matthew Leverton said: For fun, you can even have the AI simulate key presses as a second player would. Thus the AI is just another person pressing buttons to your game.
That's how I handled things in my last project. Whether it's you, a bot, or a remote player, all input gets funneled into the same handler. That really simplified things in the long run. Then you can also do neat stuff like simulate mouse movement and make it look like the bot is "playing" the game on the same screen, complete with the occasional bit of random cursor movement --> |
gnolam
Member #2,030
March 2002
![]() |
You also only have to save/load inputs to make a replay function (assuming the rest of your game is deterministic). -- |
J-Gamer
Member #12,491
January 2011
![]() |
Thanks for the advice AMCerasoli said: check out Peter Wang´s ex_thread files I sure will(as soon as my exams are finished, which is next Wednesday) Matthew Leverton said: I've used threads for AI before. It works well.For fun, you can even have the AI simulate key presses as a second player would. Thus the AI is just another person pressing buttons to your game. (Depends on the type of game if that makes any sense.) The AI will actually be doing the exact same thing as the player: solving a minesweeper field, so that approach should be possible. Sirocco said: That's how I handled things in my last project. Whether it's you, a bot, or a remote player, all input gets funneled into the same handler. That really simplified things in the long run. Then you can also do neat stuff like simulate mouse movement and make it look like the bot is "playing" the game on the same screen, complete with the occasional bit of random cursor movement
Nice gnolam said: You also only have to save/load inputs to make a replay function (assuming the rest of your game is deterministic). Yeah, that might come in handy when testing and understanding my own AI's behaviour when it gets more complicated ^^ " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
axilmar
Member #1,204
April 2001
|
J-Gamer said: I'm open to any programming paradigms you might throw at me. You need the Active Object pattern. I have attached a sample implementation that solves the Dining Philosophers problem very elegantly. |
J-Gamer
Member #12,491
January 2011
![]() |
The wikipedia page about it is more of a stub than something else... But it seems promising, so I'll see if I can find a book about it somewhere " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
axilmar
Member #1,204
April 2001
|
J-Gamer said: The wikipedia page about it is more of a stub than something else... But it seems promising, so I'll see if I can find a book about it somewhere Basically, concurrency comes down to state isolation: you can have as much of a concurrent state as you wish, as long as it is isolated from the rest of the world. So, the Active Object pattern doesn't do anything groundbreaking: it just offers a way to isolate state: each active object instance is the only instance that can manipulate its state; all other active objects (i.e. all other threads) must issue a request to that object in order to modify state. But the good thing with this is that state can be shared if state is an active object! you can have active objects passed around to other active objects, as if you were passing normal objects around, but you would not have concurrency issues. If you check out the code I posted, feel free to ask questions. |
J-Gamer
Member #12,491
January 2011
![]() |
I already thought of something like that: both players(AI or human) has to have the ability to look at the whole playing field(both his own and the other ones minefield). So I make a separate Map data class, so that I could pass that to the other player as soon as something changes. I want to do this so that the AI can get desparate while comparing both fields as you are almost finishing his " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
axilmar
Member #1,204
April 2001
|
J-Gamer said: I already thought of something like that: both players(AI or human) has to have the ability to look at the whole playing field(both his own and the other ones minefield). So I make a separate Map data class, so that I could pass that to the other player as soon as something changes. I want to do this so that the AI can get desparate while comparing both fields as you are almost finishing his So you have 3 objects from the above description:
If you make the objects active, then you can pass the map object to both the human player and the AI player. And then you can make the AI player 'think' for as long as it likes, being a separate thread, while the AI player modifies the map in parallel. |
J-Gamer
Member #12,491
January 2011
![]() |
I'll look in the details of implementation later ^^ I just wanted to be sure it was possible to do this with threads, which it apparently is Thanks to all(now I'm wishing I had put something other in the "kind of question" box... I could've given you all cookies " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
wombat
Member #12,961
June 2011
|
Not sure if I'm too late to the party on this thread but I thought I'd add my thoughts on this Putting AI into a separate thread is a perfectly reasonable thing to do. In fact, it almost makes sense because it means the computer is now "thinking" separately to player input and the responses may be more natural. The last project I worked on was a flight simulator for one of the big defence corporations. Our design had every flight system running as a separate process. There were never any issues in terms of timing or coordination of the AI between CSCIs (NB: this wasn't a personal project, it was my normal job). It was a multi-process simulation, not multi-threaded, but the paradigm of separating the logic processing performed by CSCIs was the same. I did the flight model and weapon systems for the simulation and having them in separate processes meant the weapon systems couldn't "cheat" by directly accessing exact environmental data. They had to go by the data the instrumentation CSCIs fed them. The AI for the enemy craft went into the tactical CSCI, which was run on a separate machine altogether. This kept the CSCIs for the enemy AI totally separate from the CSCIs that the pilot/player controlled. This flight simulator cost $30 million to make. If putting AI processing in separate CSCIs is good enough for that it's certainly good enough for small personal projects. |
Jonatan Hedborg
Member #4,886
July 2004
![]() |
The drawback of using a threaded system might be increased complexity and changing behavior depending on how many cycles the AI thread gets.
|
axilmar
Member #1,204
April 2001
|
Jonatan Hedborg said: The drawback of using a threaded system might be increased complexity and changing behavior depending on how many cycles the AI thread gets. I think those problems are alleviated by using the right abstraction. For example, active objects. The Dining Philosophers problem is used as an instructional tool for the complexities of using threads, demonstrating how easily potential dead-locks, live-locks and data races can be introduced by using mutexes, semaphores and wait conditions; however, by using the Active Object pattern, I managed to write an example implementation of it effortlessly, without using any synchronization mechanism, and the result (seems to) not have any of the aforementioned problems. I am a great believer in this pattern. I've used it quite successfully in many projects that required multitasking. I have yet to find another pattern that allows multithreaded programming to be as easy as non-threaded programming. |
J-Gamer
Member #12,491
January 2011
![]() |
axilmar said: I have yet to find another pattern that allows multithreaded programming to be as easy as non-threaded programming.
You probably won't " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
axilmar
Member #1,204
April 2001
|
J-Gamer said: ou probably won't And the good thing with the active object pattern is that you can add as many features as you want, but concurrency will not be affected. |
|