AI API changes
#1
Posted 20 December 2011 - 05:54 PM
I would like to have the changes below for qBot, it would be good to have feedback from other AI developers especially, feedback from everyone else is welcome of course. I have tried to mention how juBot behaves where relevant to the extent of my knowledge, I don't know enough about splitBot to comment though.
Core API
I am calling the current system the core api, these changes may break current AI scripts, depending on how they are done.
Running the AI scripts in their own threads. This should improve situations on multi core systems and also stop stuttering of the game when an AI does something expensive.
Storing entity objects persistently rather than constantly recreating them. This is fairly simple and should help the garbage collector mainly (plus a little less overhead creating the objects though this should be pretty cheap). I did a quick test by modifying the current api and have attached the code. It works with JuBot (qBot does some naughty stuff) and there seemed to be some performance improvement but it was fairly minor and my setup for measuring is rather crude, I measured about a 280ms to 230ms change at 10x speed but don't take this as an accurate figure.
Persistent entity collections.
This is what I think will deliver the largest performance increase (qBot currently uses a crude version for this reason), but will require modifying AI scripts to take advantage of them. Based on my testing JuBot spends about 98% of the time filtering through entity collections. Here is my idea of how these should work:
You would create a new entity collection by filtering an existing entity collection (I think juBot does this exclusively). You would give the filter function as an argument (see filters.js in the attachment) and it would be stored as part of the entity collection. Then if you wanted to store the entity collection, you would use some sort of registerEntityCollection() function. From this point the entity collection would be maintained by the API. The filter functions of the parent would be inherited.
(more technical details, can be ignored)
The filter function may depend on a dynamic property, for efficiency I think it would be helpful for the API to be told which it depended on. So you could have player 2's idle units which would depend on the idle and owner properties. The combination of this with the Filter.js file leads to the question of how the dynamic properties would be passed to the entity collection. To keep things neat when using Filters.js putting the function and dynamic properties list into a simple object/array would keep things neat. This makes things more messy for someone making their own filter functions from scratch since they now need to wrap it in an object. I think this method is preferred though. e.g. {'func': filter_function, 'dynamic_properties': ['owner', 'idle']}
Filtering based on position presents a potential performance problem since there can be a lot of position updates every turn, I think for now it would be worth keeping thing simple and not doing anything special and see what happens, it should be able to offload it to a C++ component without any interface changes if it is a problem.
Another possible performance factor would be storing the entity collections in a hierarchy so you could avoid looking deeper in a tree for a lot of events. This should also be possible without any API changes so isn't important as a consideration currently.
(end of technical details)
Other Stuff
Here are other helpful functions that it would be nice to have an interface for in an AI. I have put them in what I think should be their priority.
Accessibility testing, can a unit reach another point on the map from where it is currently? QBot does this already but it is one of the factors causing lag at the start of games and is based on the coarse accessibility map which has caused some issues. Also qBot's version is not dynamic for performance reasons.
UnitAI state. It is nice to know whether a unit is walking, attacking, woodcutting...
Map manipulation functions see http://www.wildfireg...89 for details. Also see map.js in qBot.
Fairly low level pathfinding access or some terrain analysis functions. See terrain-analysis.js for a rough idea of what I want to be able to do. More fancy stuff would be good as well. On a basic level giving a pathfinder using a specified custom map to route over (basically adding some more inaccessible areas).
Edit 06-04-2012: Now the code is in svn
Jonathan Waller [ aka quantumstate ]
Wildfire Games AI Scripter
Contact me: jonathanmarkwaller at gmail dot com
Support Wildfire Games!
#3
Posted 24 December 2011 - 12:31 PM
Berkley Overmind -- the Starcraft AI -- used this approach.
#4
Posted 08 January 2012 - 04:40 PM
Echelon9, on 24 December 2011 - 12:31 PM, said:
We chatted about this on irc a while back. Basically the outline above will create a potential field, non round threat hulls would be useful to have, and should be easy to add.
Also I have extended my prototype code, now I have updating entity collections working (I think, I didn't test thoroughly though). I am still a bit unsure about the interface, my function names could be improved and the grouping of filters and dynamic properties still feels a bit messy.
It almost maintains compatibility with juBot, changing line 65 of gamestate.js to
return this.ai._ownEntities;makes it work. No performance benefit is achieved without changing lots of code though. Having ownEntities as a special case makes less sense with this new code, my new code just registers it as an updating EntityCollection and lets the standard code handle it from that point. I think it should be removed and left to individual AI's.
A usage example is:
if (!this.allWorkers){
var filter = Filters.or(Filters.byMetadata("role", "worker"), Filters.byMetadata("role", "militia"));
this.allWorkers = gameState.getOwnEntities().filter(filter);
}
Metadata updates instantly affect the entity collections. For efficiency, metadata filters use "metadata.{key}" as the dynamic property, using just "metadata" is supported and will catch all metadata changes.
Deleting metadata is unsupported currently, also saved games are broken.
Jonathan Waller [ aka quantumstate ]
Wildfire Games AI Scripter
Contact me: jonathanmarkwaller at gmail dot com
Support Wildfire Games!
#5
Posted 02 February 2012 - 10:03 PM
What I missed in SplitBot
- persistance for the EntityCollections
- ability to put metadata on a building when you start to build it (like you do it when you start to produce a unit)
- an easy way to detect if a place is buildable with a given unit at a given position and orientation
- an easy way to detect if there is water between a unit and a position
What would really have helped me is an event system. To be able to give a callback and arguments in these cases:
- when you start to build an entity or produce a unit: onBuildComplete and onBuildStoped
- when you send a unit somewhere: onUnitArrived, onUnitBlocked
- when you send a unit to harvest, onStart, onUnitBlocked, onResourceEmpty, onDropResource, onResourceIsFarAway...
- ...
Just in case it is useful to you : in SplitBot have filtered the entities in this arrays and used a kind of "cache" system to compute the array only one time per tour :
I think that the "Filters.byMetadata" thing would make my life easier, would it be fast if done with a C function?
And last thing : I do not think it is necessary to have the {'func': filter_function, 'dynamic_properties': ['owner', 'idle']} argument to keep a selection up to date. It can be done by hand easily if there are events.
#6
Posted 03 February 2012 - 07:22 PM
lexa, on 02 February 2012 - 10:03 PM, said:
What I missed in SplitBot
- persistance for the EntityCollections
- ability to put metadata on a building when you start to build it (like you do it when you start to produce a unit)
- an easy way to detect if a place is buildable with a given unit at a given position and orientation
- an easy way to detect if there is water between a unit and a position
What would really have helped me is an event system. To be able to give a callback and arguments in these cases:
- when you start to build an entity or produce a unit: onBuildComplete and onBuildStoped
- when you send a unit somewhere: onUnitArrived, onUnitBlocked
- when you send a unit to harvest, onStart, onUnitBlocked, onResourceEmpty, onDropResource, onResourceIsFarAway...
- ...
Just in case it is useful to you : in SplitBot have filtered the entities in this arrays and used a kind of "cache" system to compute the array only one time per tour :
I think that the "Filters.byMetadata" thing would make my life easier, would it be fast if done with a C function?
And last thing : I do not think it is necessary to have the {'func': filter_function, 'dynamic_properties': ['owner', 'idle']} argument to keep a selection up to date. It can be done by hand easily if there are events.
The main thing is basically persistent entity collections, along with a group of preset filter functions which make it easy to use. This would be done in javascript initially, I think performance should be good enough. For performance though, the dynamic properties are important because without the automatic updating we are in exactly the same situation as now, and there are lots of position changes every turn so performance will be poor without filtering by dynamic property.
Metadata on buildings makes sense, I think we should do that.
The water information is linked to accessibility testing and pathfinding. It would be helpful to have, I think it would be best to leave this until Philip has finished the current pathfinding stuff and then come up with a decent AI interface for the whole section.
Buildability should be fairly easy to expose.
An event system would be a pretty big change. I currently can't see much use for it in qBot, but i haven't given it much thought. It should be possible to implement in the common-api code which would make it fairly straightforward to add, it would just run events at the start of your AI's turn.
Jonathan Waller [ aka quantumstate ]
Wildfire Games AI Scripter
Contact me: jonathanmarkwaller at gmail dot com
Support Wildfire Games!
#7
Posted 03 February 2012 - 11:11 PM
but for the "automatic updating" of entity collections, I believe that it is better to have an event system which lets you update your model (keep the collections up to date), than to have this "binding"-like functionality
just because in javascript and web languages it is much more common / standard
and as far as I'm concerned, after a long time of practicing this languages for building complex web applications, I even prefer the callback version. the addEventListener version of an event system has a good point : you can add several listener, you will not prevent a callback to be called. but the problem is that at the end, it is much harder to debug. and also, callbacks force you to have a cleaner and simpler architecture.
finally the preset filter functions should be useful. in splitbot i used a helper class to access these collection with a "cache" mechanism
public static var myEntities:EntityCollection;
public static var myPeopleUnits:EntityCollection;
public static var myBuilderUnits:EntityCollection;
public static var myBuildingStructures:EntityCollection;
public function getMyEntities():EntityCollection
public function getBuilders(entities:EntityCollection):EntityCollection
public function getWorkers():EntityCollection
public function getFondations():EntityCollection
public function getBuildings(allowedTemplateNames:Array<String> = null):EntityCollection
public function getResources(entities:EntityCollection, type:ResourceSupplyType = null):EntityCollection
#8
Posted 03 February 2012 - 11:29 PM
lexa, on 03 February 2012 - 11:11 PM, said:
just because in javascript and web languages it is much more common / standard
and as far as I'm concerned, after a long time of practicing this languages for building complex web applications, I even prefer the callback version. the addEventListener version of an event system has a good point : you can add several listener, you will not prevent a callback to be called. but the problem is that at the end, it is much harder to debug. and also, callbacks force you to have a cleaner and simpler architecture.
Sorry, I'm not quite sure what you mean by this. Could you elaborate a bit?
Jonathan Waller [ aka quantumstate ]
Wildfire Games AI Scripter
Contact me: jonathanmarkwaller at gmail dot com
Support Wildfire Games!
#9
Posted 04 February 2012 - 12:44 PM
quantumstate, on 03 February 2012 - 11:29 PM, said:
You mean the event thing to update the collections?
For example, let's say you have a collection of all of your workers. Each time you build a unit, you would provide a "onBuildSuccess" callback. And in this callback, you could get the unit as a parameter. Anyway you could maintain the collection of your workers up to date in the code of the "onBuildSuccess" callbacks..
I hope I was more clear this time...
#10
Posted 05 February 2012 - 12:05 AM
Adding some form of notification about changes would be useful. Currently there is the array of events for this, but it is fairly limited.
The game is built on a turn based system so I think the AI's will always be restricted to a turn based system like they are now. Callbacks are still workable though. There are some things which you would need to consider though. The main thing is that the games' state will have changed by the time the callback is called so this might cause issues with specifying parameters for the callback.
Jonathan Waller [ aka quantumstate ]
Wildfire Games AI Scripter
Contact me: jonathanmarkwaller at gmail dot com
Support Wildfire Games!
#11
Posted 05 February 2012 - 08:16 AM
I quite agree with the other changes though.
Wildfire Games Programmer, AI developer, auxiliary map designer, dealing with anything water.
Contact me: wraitii@wildfiregames.com
Also the world's only three-dimensional poodle.
#12
Posted 05 February 2012 - 07:46 PM
The events are clearly a better way to go for me, because it is much more natural/standard and easy to use in javascript. And often I would use it without having a collection to update.
#13
Posted 05 February 2012 - 11:13 PM
lexa, on 05 February 2012 - 07:46 PM, said:
Wildfire Games Programmer
Contact me: ben@wildfiregames.com
#14
Posted 07 February 2012 - 09:26 PM
#15
Posted 18 February 2012 - 02:39 PM
lexa, on 07 February 2012 - 09:26 PM, said:
Indeed it would be good just as an extra option for the AI developers.
I'm interested in creating AIs, but i know little of the API and i'm not much familiar with Javascript (even though it's similar to Java). When you guys get these changes done, i'd like to see the new API and try to do anything, so please post a link on this topic to it.
Latin: Petrus Falco; Literally means 'Stone Hawk'.
English equivalent: ' Peter ';
Undergraduate Computer Scientist by UFCG
Shotokan Karate Adept, 3rd Kyu (Green Belt) & Muay Thai initiate
#16
Posted 18 February 2012 - 04:16 PM
Pedro Falcão, on 18 February 2012 - 02:39 PM, said:
I'm interested in creating AIs, but i know little of the API and i'm not much familiar with Javascript (even though it's similar to Java). When you guys get these changes done, i'd like to see the new API and try to do anything, so please post a link on this topic to it.
Erik Johansson [ aka feneur ]
Wildfire Games
Contact me: feneur@wildfiregames.com
Support Wildfire Games!
#17
Posted 19 February 2012 - 10:24 AM
(I'm thinking for example some sort of A* function that would return a path, possibly every x "cells" or at each turn.)
I forgot about the UnitAI stuff. It would really be useful, particularly to know which unit is attacking who.
Edited by wraitii, 19 February 2012 - 01:56 PM.
Wildfire Games Programmer, AI developer, auxiliary map designer, dealing with anything water.
Contact me: wraitii@wildfiregames.com
Also the world's only three-dimensional poodle.
#18
Posted 05 April 2012 - 08:47 AM
#19
Posted 05 April 2012 - 09:28 AM
Jonathan Waller [ aka quantumstate ]
Wildfire Games AI Scripter
Contact me: jonathanmarkwaller at gmail dot com
Support Wildfire Games!
#20
Posted 05 April 2012 - 11:48 AM
Edited by Almin, 05 April 2012 - 11:48 AM.
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users












