I’ve made some commits to MonkeyBrains: moved some stuff on a different package (monkeystuff) and stripped some functionality from the Agents.
The old functionality is preserved on the new BluePillAgents. I’ve named them this way because I think it conveys my intention: the “blue pill” is the usual way, they are well documented on the wiki and they should work with the current examples.
Since there is a “blue pill”, there is going to be also a “red pill” that is going to be a bit different. I’m not an expert in AI, I’m just wanting to adventure in this aspect
The “red pill” will be built around the needs of my game, so yes, I will actually eat my own dog food (monkey food?).
Regards libgdx-ai migration… Such idea is quite attractive at first but i think libgdx-ai library also quite wraped around 2d and the “actor” model - core concept of libgdx .
I also write a few games with libgdx using steering and fsm module. They’re well written, however it’s quite basic to make use in bigger game such as a 3d rpg for example.
About MonkeyBrains, i don’t know if I should throw some ideas and pull requests to improve it or make an open-source lightweight AI library my self. As said in the other thread, the abstraction should be super thin. And for the utilities, we can use well made library like Guava or RxJava.
The effort saving is huge and the possibilities are incredible too!
Yes, it’s me @atomix
I could not make the old account work so I started a new one, fresh and clean.
I think MonkeyBrains concepts should be carefully pick to make it clean and abstract as much as possible. Later extensions can be built around its core. The layer that adapt to JME architecture also should be thinner (a solid AppState is likely enough)…
For the plugins: I can contribute the triggers, finite state machine, fuzzy logic and the goal driven with DSL that I wrote (with dependency in Guava and RxJava). They are good enough to be logic bricks to build various kind of game.
As scripting over that AI lib, I used Groovy but Lua or Jruby should work fine also.
I also don’t want to make another library but in fact the abstraction is super thin (like 6-7 interfaces or so). That’s nothing compare to the utilities that wrap around it and the plugins. That’s the point.
@erlend_sh The goal for MonkeyBrains is to make library that will enable programmers to make good AI without a lot of effort. An abstraction that will enable programmers to make AI with use of Neural Networks without of knowledge of different neural structure. They are distraction for game programmers and they should be done by someone that knows about those. The logical questions for reader of this statement are why aren’t they Neural networks in MonkeyBrains, or that kind of super awesome AI stuff, and there are codes for weapons, inventory and as such. The answer is simple: they are not part of AI, but that kind of data is more than needed for good AI planning. Should NPC attack, or go collect some items…
The awesome AI stuff is not complicated as much is making good framework for them to be used modaly and to be reusable. And for now I get most of complains how the framework is too complicated.
Current MonkeyBrains structure is based on JADE. It is more generic, but I think it does not enable programmers to build easily good AI.
@atomixnmc If you think there is better structure than this one, I am open to discussion. I am still searching for the flexible enough. When the foundation is completed, the main focus will be on implementation of AI techniques, but for now main focus is to be flexible enough to support real time actions and strategies and turn-based games.
@Pesegato I saw the changes that you have made and they will crash MonkeyBrainsDemoGames.
The idea of rootNode in MonkeyBrainsAppState is too have one common Node for all AI. Yes, I said you can remove it, but you will have to have Node in MonkeyBrainsAppState, just set one Node for them to which their spatial will be added. This is must do, because respawn logic can not be added later without this.
Why did you remove inventory? I am strongly against it. Without it steering behaviors will be useless and they are so non-intrusive, they will do nothing if you don’t implement them…
I think that agent class should be final. If you need extending, generic model is there.
I’m totally into making it as flexible and useful as possible. That’s two sides of a coin.
By flexibility I mean what I want is an unopinionated solution, the framework part does not make any guess or force you to use a single method, and the library part make it possible to do things fast and reliable… My experience and background tell me that I should make a “compose-able framework” that user can adapt, build their own parts and contribute back. And as Java developer I think it’s fair enough to use other libraries as well!
Regards the current design, in the API suggestions thread I said: -“Game” and “Team” concepts are quite overwhelm the framework. As Java we have generic collection which doing just fine for Team. And the “Game” should be separate into two mechanisms : Event broadcasting and Space partitioning that link Agents together. -Behavior as Control is also a misleading implement that suggest solid implementation at concept level. I still think Behavior should be nothing but an interface or as generic as a Signal where Signal is a arbitrary event mechanism (EventBus or Backboard, Agent Per to per, or what ever…)
It’s not a “1 to 1” mapping from “concept to implementation” because we using Java and make this AI library for games. I saw some part of the current MonkeyBrains code base ignore the fact we are using Java, or ignore the fact there a lot of genre of Games.
It’s nice to see all this feedback! First of all, I’d like to show the “red pill” design:
My idea is to introduce (yet) another virtual space: the AI Space. On this space there are the “AI Items” which have a Vector3f (position) and some semantical Tag: Friend, Team_A, Food, Obstacle… whatever you want.
Then we have the “Brains”. The brains have “Senses” attached to them, which periodically scans the AIspace and process the information to the “Upper” part of the brain.
The brain receives these “stimuli” and makes decision: fight or flee? stay or move?
This is a very game-specific part, and should be somehow scriptable; probably with decision trees.
Then the “Lower” part of the brain executes them; for example must go to point A: then choose the best path.
Some considerations: there is no rootNode at all, and is intended. The AI can exist even on a console game, without the 3d scene graph. Plus there may be Spatials that are irrelevant for AI (for example: a cloud or a tree), and there may be AI items that do not have a corrisponding Spatial (for example: an invisible ghost that can be “perceived” but not seen).
The RedPillAppState can be run about every 100ms (which is roughly the average reaction time for humans).
The “RedPill” is an option. This design may or may not fit the developer needs, and that’s why I’d like both pills to coexist.
With that said, let’s catch up with the feedback
As I said I would. As stated above, I’m a bit agains an “absolute approach” (like: you must do it this way). Therefore I’ve created the “BluePillAgents” which mantains the old functionality, and “Agents” that are lighter. The MonkeyBrainsAppState and Agents were quite complex (and in fact, some game specific logic was leaking there), so I started to put them on a diet
The steering still works (on my game at least )
The “respawn logic” is a game-specific rule, and I think should not be AI’s responsibility.
The fact that an Agent should have an Inventory is debatable; however as I said the naming is important. Like this:
Agent: just the bare minimum
BluePillAgents: also have Inventory and Spatial
SuperAgents: also have super powers
Just to throw in my ten cents worth … and I am probably barking up the wrong tree … but I was discussing designing AI for my game with a friend, a while ago now, and he suggested I look at the Drools library. Admittedly it is for business decision making, but it is scripted (I think) and seems fairly adaptable. At the time, I thought it had some promise of being useful.
Regards the Behavior Tree (BT) of libgdx-ai . Yes, it’s well written I have to say. Even if I’m not a big fan of BT in general because I like more the reactive manner of AI (or half scripted, half reactive), or goal driven… BT AI modelling’s hard to make a realistic AI, because they are too “sharp” or too “case-study”, at least from my experience and what I’ve read.
libgdx-ai has a handful of utilities and they even introduce a DSL to make BT, which is nice but after looking at the code, I saw concepts spread over the places and force user into their way of thinking instead of provide a “library” or “framework”.
My revision of Behavior composing (not just tree but a graph of Behaviors). Keep them as DataStructure if it’s possible. Don’t bring BlackMagic into Data.
Task for example are very common in AI field but will be too generic for an imperative language like Java. Task should be just a wrapper of Runnable or Callable like in Java utils. An Game AI framework may let Task has two more characteristics:
Update let Task hook to update beat of the game. Decompose let the Task expose its internal logic in monotholic way. So any kind of Agent, Rule or Scheduler can run task, evaluate task, judge its complexity.
The Tree stand along as an generic DataStructure.
The Visitor is also an interface to travel the Tree (the Graph).
MetaTask can take any valid description (script) to procedure a Task.
ChainedTask allow to compose task together, the process of compose ChainedTask is opposite with decompose a normal Task.
Now because all the above it just like organize data in well defined data structure, if I want to:
execute a Task in the Tree, I visit it by ExecuteTaskVisitor and let them roll. Those visitor is likely an AppState in JME3 code.
Evaluate a Task, use EvaluateVisitor which take a single node or a Whole into account.
As if I have another Tree ( Tree of Spatial for example) which matched the structure of my TaskTree in someway, I may also visit them asymmetrically and calculate the result! This is the main idea under the hood by using well-defined structure: Divide to Conquer.
For example: visit the behavior tree at the same time with visit the dialogue tree. You can see it as I decompose a thing into two! In a lot of framework they tend to make it like this:
For DSL, I use Groovy! to save my self in hell of problems later.
As an DIY version, you can introduce a MetaEvaluator or ScriptEvaluator depends on what you want in a Behavior Composing system, some of those listed below which Groovy can feed you well:
interfere/invoke real java object’s attribute and method
decomposable into small piece by meanings (human- read write -able)
Regards Drools, I don’t think it’s well adapt to game neither. It’s big and over complex subject to make simple rule or action that your “common” game need.
I like idea of behavior trees, if you look at demo games, that was the idea of making AI in games. As for AI items, I made for GameEntity class. That class should represent all entities relevant to AI.
I don’t like how the name BluePillAgent as it doesn’t describe what is difference between Agent and BluePillAgent. When I made this I was primarily focused on FPS games, but to make it more flexible, we can make Agent class really and have his extension for different games RealTimeAgent and TurnBasedAgent as first big different agents an then build a tree.
Ok. I think we should remove Node from MonkeyBrainsAppState.
Actually the whole gdx-ai framework is dimension independent. Thanks to the use of interfaces and generics both steering behaviors and pathfinding API work with 2D and 3D because is the developer’s responsibility to provide the actual implementation of the model. Also, about “actor” model I don’t really get what you’re talking about. If you’re referring to something scene2d-related, well, I think you misunderstood the API.
Behavior trees have proven to be a real mean to implement complex agent’s behaviors. Think of games like Halo 2 whose AI heavily relies on behavior trees.
Don’t get me wrong. I said your library is well-written. Of course you did abstract out the dimension by generic wrapper. The problem of 3D is: it’s not “2D with Z”!
I don’t say JME is for making 3D game, but as I wrote my AI lib for example, I try to bring all the case spanning in 3D space first, but not try to wrap my mind around 2D space and leverage with a Z axis…
Also, I DID try to integrate libgdx-ai to JME and in fact in my code base of Atom I have all the utils package of libgdx including Vector math, Array an such… So it’s not a big deal to integrate it to JME anyway… what is the problem? It’s there anything in between make me feel uncomforable to use libgdx-ai in my JME project (yes, mine only).
2D or 3d: There is no Physics constraints, there is no Floor, there is no Mesh? This is the main point of tell your library wraped around 2d. Or at least you are not thinking in 3d dimension firstly. What physics really relate to AI after all? Let say your Steerable after calculation introduce a Vector that force toward the ground (dig through the ground). This situation will not happen in almost 2d game but really common in 3d games, because there are floors! Then this in turn hand out to user to solve. When it come to physics, steerable will hit harder then a WeightedBlendSteering or PiorityBlendSteering. I suggest to add PhysicsBaseSteering and FloorBaseSteering to treat those situations. Another thing is Graph but not Mesh, you properly know about NavMesh in detail. Your framework introduce a handful of graph utilities but not Mesh. Mesh is an extension of lattice graph that also have concern about its Cell, which is the area between non overlap vertex. Mesh is a big deal in 3d AI. In fact, I will never back to use a Node base pathfinding but a Mesh base pathfinding… It’s cleaner, faster and much easier to control. But that’s another story.
MessageDispatcher: Why I need a MessageDispatcher. Because of “actor”. You may not see because the assumption is hidden here. MessageDispatcher assume that the “actor” don’t delivery the “message” themself but pass to another system to handle this job. In turn, MessageDispatcher join the AI framework just to delivery handful of un-categorized or even un-ralated to AI messages. As a system designer, I really against this idea. I want a GenericMessageDispatcher to delivery anything (but I already have it), and I want specific and ManagedSpecificMessageDispatcher to handle well-defined scope messages (like AI telegram). You may see the point… You framework don’t intend but introduce handful of ultilities that let user do “bad practice” by it.
Edited: (I think I have to make my self clearer at this point)
I suggest making TelegraphMessageDispatcher an interface instead. And for a solid implementation with libgdx utils as DefaultMessageDispatcher (or MessageManager).
I think Telegraph should be eliminated (or at least become internal API) because people will going to bring various classes extends Telegraph and they think they have to depends on it every where. This will make your Telegraph the “blackhole” because everything have to go through it and bottleneck will soon be seen!
Telegram should be an util class, which immutable and should not be extend in anyway. Telegram is what I called Signal in my concepts (you know i’m not a native speaker)
Here we are talking about Agent framework
which not really introduce the concept of message delivering but it’s belong to per implementation.
Scheduler: This is util and I’m not too much against it but I think I may use better library for this job. Introduce too much utils is not really awesome if the user comeback and complain about it later.
As I said, it’s look promising and also nice write up. I used it in my soon release game But it still against my philosophy of writing a framework. Introduce too much concepts
It’s like you map “1 to 1” concept from AI field into a solid Java class or interface. As implement in Java, you may know that we already have a handful of interface in Java util that written 14 year ago and proved by millions of users? To write another one that look exactly the same or somewhat extendable from the old one, I think we should carefully decide. You know, as the official AI lib of libgdx, your lib going to have million users soon. That’s just my opinion, one of your user!
Signal is immutable, clonable and let the world know about how it’s look, what weapon it have, where is it.
Let Agent has any “property” as mutable Java attribute/ reference will cause concurrent troubles later!
In BluePillAgent (should you change the name to be more specific, like PropertyAgent), the Agent that “store” the some "item"s inside, forming an “inventory”; it may provide signal about its “inventory” and let those “observer” look at it continously.
The big question is: do we really need to introduce a solid concept of “property” for “agent”. Do agent really need to touch other’s item to think?
What I suggest above is: let introduce a minimum Java implementation: as an interface, or as an immutable final util class to represent this concept. Or suggest the user of the library that they should implement so call “property” that way.
Just done the first small commit of RedPill, with AISpace and a basic Sight
The naming (red/blue) is hopefully provisional, just for keeping it consistent with this discussion. Once we have settled things, we may opt for cooler names.
Glad to have you on board!
To me this doesn’t look like a disadvantage. Physics isn’t used everywhere, and an AI for spaceship doesn’t need Floor either. On the other hand, we could write a specialized AI with these constraints, and that’s why I’d like the AI modules to be somehow pluggable.
Well, I didn’t understand if you are suggesting improvements to gdx-ai or if you are describing how MonkeyBrains should be written
So far, even with the faults(?) mentioned by @atomix,I think that MonkeyBrains could leverage libgdx-ai (probably by means of a libgdx-ai-monkeybrains-bridge). I don’t want to reinvent the wheel myself.
But also I don’t want to force design decision! Since @atomix is so much passionated about this, and if @Tihomir agrees, I’d gladly allow him to put his code on the repo.
About steering behaviors and full 3D did you read this? Steering Behaviors · libgdx/gdx-ai Wiki · GitHub
Extending the API to support full 3D for those behaviors having an angular component is not so hard.
You just need to use vector and quaternion in place of scalars for angular acceleration and orientation. Of course the 4 behaviors mentioned there need an additional implementation that uses full 3D math. However, 2.5D geometry covers likely more than 90% of games out there, so I thought that support for full 3D steering was not a priority when I wrote the API. It will be added if/when people will ask for that.
About physics, I think it’s an added value that the framework doesn’t impose physics. You are free to implement your model with the underlying physics engine you prefer or any physics at all. It’s totally up to you. That’s one of the reasons why I call gdx-ai a framework instead of a library.
About the message system, there’s nothing in the framework forcing you to use it in your game. It’s just a simple and well-established technique that you are free to use if you want.
Finally behavior trees, they are nothing more than a formalism. All formalisms introduce some kind of concepts by nature. As such you have to learn those concepts in order to use btrees at their best and appreciate their expressive power.
Also, since you are comparing java classes with btrees concepts ask yourself “Are all game designers able to modify source code?”… You know, luckily a team is made up of many people with different skills and roles. Ideally, a game designer should be able to change the AI of an agent without having to modify and compile the source code if possible.
Anyways, if you want to contribute or concretely share your knowledge I’ll be glad to discuss things with you.
Of course if you decide to use gdx-ai in your engine I’ll be glad to provide all the support you might need.
I’m open to API changes and extensions if required. Just let me know.
That’s definitely a road I would personally like to see us go down eventually. But for now, I fear I might have brought gdx-ai into the discussion prematurely. MonkeyBrains was in the midsts of a new iteration, and I feel like I contributed to making that transition harder by adding yet another factor into the mix.
@Tihomir and @Pesegato have enough on their plate for now just figuring out amongst themselves how to further MonkeyBrains as-is.
As for jME and gdx-ai, I would love it if someone (@atomix maybe? it’s hard to determine where you stand! ^^) took it upon themselves to use gdx-ai as another alternative AI engine for jMonkeyEngine. I don’t see that as as a loss for MonkeyBrains, since there are already enough “chefs” involved And honestly I would be kind of bummed out if someone introduces Yet Another AI Library at this point.