Jump to content


Community Members
  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by agentx

  1. Thanks to you! I saw your list yesterday in the trac timeline and directly started reading at 0fps.net. Keep on curating!
  2. Two links from the leisure department showing genetic algorithms at work. The first tries to make a bunch of shapes walk the second drive. All happens in a physical world using the box2d engine. http://rednuht.org/genetic_walkers/ http://rednuht.org/genetic_cars_2/ Have fun!
  3. agentx


    Hmm, at 17:00 with cart in mainland I was at 44 female, 164 in total. Had 4 barracks in town phase.
  4. Have a look at the charts mod thread: http://www.wildfiregames.com/forum/index.php?showtopic=18763&hl=charts and the StatistiksTracker: http://trac.wildfiregames.com/browser/ps/trunk/binaries/data/mods/public/simulation/components/StatisticsTracker.js Should give you an idea where to grab the data and may even help to connect your code to the game. There is quite a wealth of data available.
  5. Thanks. 1) Basically all I use from the API is in m.BaseAI.prototype.Init() + Events + TechTemplates. I know this involves in some cases deep access to data which definition may change. But I make sure to not have more work then changing the API. Performance wise there are only spikes forced by map analysis. I've set myself a limit to stay below 100ms per tick in any case and so far there is lots of room. OTOH the test with 8 Hannibals throwing 2000 units into battle has still to run. But there is also the option to think less or less often if needed. I think time is just another resource like wood and stone and there are budget limits and a bot has to deal with. 2) Yes, I needed to separate group logic from API logic visibly and semantically, it really helps me thinking how a group should solve problem X. Hannibal will consist of two parts: A set of groups + the rest/runtime. Everybody is free to take the rest and author his own set of groups and call it a bot, but not Hannibal There will even be kinda packager that renders all code into one xyz.js which goes with metadata and folder structure into a zip + readme.txt. So yes, Hannibal is a Bot Development Kit and a mod and you can make a bot mod mod. Today I worked a bit on moving units around and started a "dance" group whose units run in circles. This is the relevant code: function launch (w, config) { // stringify group position var path, pos = w.group.position[0] + " " + w.group.position[1]; // pick some citizens w.units = ["exclusive", "food.grain GATHEREDBY"]; w.units.size = 9; // move path 70m north and create circle with radius 10 path = w.units.size + "; translate " + pos + "; translatep 0 70; circle 10"; w.path = ["path", path]; w.path.size = w.units.size; w.nounify("units", "path"); w.path.on.request(); }function interval (w, tick, secs){ // if complete and all idle, rotate path and redistribute units w.units.on .doing("idle") .match(w.units.count, w.units.size) .path.do.modify("rotate 40") .units.do.spread(w.path) ;}Doing() temporarily filters units by UnitAiState. A path is just an array of [x, z] locations. It can be used to send units to each point (spread) or make them walk from one to the next (move). 'translatep' translates the path by polar coords, where north is 0° and points from CC to center of the map. I hope human opponents will accept bots celebrating victory, too
  6. Once you have a list of wall corner positions, look here: http://trac.wildfiregames.com/browser/ps/trunk/binaries/data/mods/public/simulation/helpers/Walls.js
  7. It's not really blood just red pixels. And the units are not dead, they will be reanimated once you train more.
  8. @Teiresias: I think your first observation is understandable if you see devs as limited resource. From a certain point 2 devs working on 2 bots is a waste of time and energy. However on the long run I perfectly agree with your tendency, mainly because 2 or more bots fighting each other bring up issues very fast and reproducible. The triple store is basically a replacement for the entity collections and their filters. "food ACCEPTEDBY" may yield a farmhouse, a dock or a centre. The group can work with any outcome, so authors won't deal with different mods, civs, costs, templates or entities. So far each group's script fits in one short file and I like that. And yes, you can contribute to Hannibal by scripting groups. > SDK. Yes and no. The concept is: Every unit is part of an autonomous group for a specific task. If you agree with that, it is an SDK, actually a BDK . If not it is just another bot.
  9. > is compatible with the main bot? What do you expect from compatible bots? Do they they behave different from incompatible bots? If you want to see Petra fighting Hannibal on a map, that'll work. In that sense all 0AD bots are compatible with each other.
  10. > smart or realistic? Depends on the group script author. He/she may use: w.units.do.format("Testudo"). Same for stances: w.units.do.stance("standground") PS: I've kept this intro simple, but I'll try to make some tests and showcase some battlefield tactics soon. In short groups can communicate with each other, keep a specific/flexible distance and have verbs like move, stance, format which can also be queued. But these are the essentials every human player has too. Not much of Hannibal, the API provides that.
  11. I think, I'm getting really close to finalize the domain specific lanaguage (DSL) used in Hannibal's groups and want to ask for some feedback, because this what this bot is all about. The idea is only groups talk to the engine. Some unit should gather a field, there is a group for that. Want to build houses - launch a builder group. Need resources, give the supplier group some entity ids of trees, mines or whales. Groups are the building blocks of the behavior of Hannibal, everything else is low level or services. If something is going wrong a group is probably missing or not properly programmed. Actually you can think of Hannibal as a bot framework with groups as the user interface. Let's say you want an anarchy bot, but don't want to deal with map analysis or the 0AD bot API, all you need to do is fork Hannibal and define new groups with new behavior. How does it work? Well, technically the DSL works by chaining JavaScript methods. Here is a trivial example: array .sort() .filter(item => item > 5) .forEach(/* do stuff */);That works because both sort() and filter() return an array. Fortunately JavaScript's automatic semicolon inserter doesn't kick in. Hannibal's DSL looks similar, but it adds another level. Let's start with the most important group, the base of any village, the grain pickers. I'm going to challenge your imagination, but give it a try: Assume YOU are that little female unit contracted to do nothing but gathering food. Still here? Ok, what is your job description? Basically: Stay alive and gather food. What are your options to stay alive? Let's say, if you got hit seriously flee and search for shelter. If the attacker is gone try to heal. And to gather? Well, that's simple: Gather food and carry it to a dropsite. OK, may be I should order a field if there is none. And even a dropsite, if all others are to far away. You see a gather-food-unit only needs a very simple mind. That's the concept of Hannibal: Give units a simple job description so they never go idle and group similar jobs together. From there complex bot behavior will follow/emerge. I now hear objections: You can't win a game with female food gatherer only! That's right. And I must say I haven't seen attacking units so far with this concept. So here is what I'm going to implement: The job description of a military is actually close to the above, stay alive and do damage. If you are successful move forward otherwise move back to a more secure place like a fully garrisoned fortress of a tower triangle. Hannibal's job is to provide this information, the attacking unit's job is to use it wisely. Can you now imagine a horde of cavalry keeping the right distance avoiding suicide attacks, never going idle and heal if exhausted? Back to the DSL, a group's scripts are triggered by events only. There is a one time event when the group launches, another when Hannibal assigns an asset (read entity, e.g. unit, field, house, dropsite), when the group got attacked, an asset got destroyed or a timed event. Here is the list: launchassignattackdestroyintervalObviously launch is kinda initialization. The group declares what assets are needed and presumably orders the first one. This is the grain pickers launch script: function launch (w) { w.units = ["exclusive", "food.grain GATHEREDBY WITH costs.metal = 0, costs.stone = 0"]; w.field = ["exclusive", "food.grain PROVIDEDBY"]; w.dropsite = ["shared", "food ACCEPTEDBY"]; w.units.size = 5; w.field.size = 1; w.dropsite.size = 1; w.nounify("units", "field", "dropsite"); w.dropsite.on.request(); }The assets are defined using the internal query language, they all need a size and then the definition gets 'nounified'. All left is requesting a dropsite which sooner or later triggers the assign script. The DSL has kind of a grammar consisting of sentences, nouns, subjects, objects, verbs, attributes and modifiers. w.dropsite.on.request();Above is a sentence. JS experts see property chaining works too. 'w' is the world the language is defined in. Each group acts in its own world. 'w' is always the first parameter in script call. Whenever something is nounified it is available either as subject or object. Here is what in this sentence happens: w // each sentence starts with the world .dropsite // dropsite is picked as current object .on // the current object is picked as subject .request() // the current subject fires an action, amount defaults here to 1; // sentence doneSo, in plain English it means: Dear Hannibal, I desperately need a dropsite for food. As most maps have a civic centre as start up building this command is actually a no-brainer. Probably already the next tick calls assign. If Hannibal can't provide a dropsite the map is probably un-playabale, because of lack of resources or whatever. Now things get a bit more complicated, the group may get assigned a dropsite, a field or an unit, so a filter is needed. function assign (w, item) { w.objectify("item", item); // got dropsite, requests unit, exits w.dropsite.on .member(w.item) .units.do.request() .exit ; ...Here dropsite is first selected as object, then as subject and then a member check follows. If that check fails all the rest of the sentence is ignored. In case of success units is selected as subject (do) and a unit is requested. 'exit' means all the rest of the whole script is ignored, think of 'return' in a JS function. It should be clear what comes next - a sentence for a new unit: // keep requesting units until size is metw.units.on .member(w.item) .lt(w.units.count, w.units.size) .request();'lt' - less than - compares 'size' as defined in launch with the actual amount of units. You miss the field? // the first unit requests field, exitsw.units.on .member(w.item) .match(w.units.count, 1) .match(w.field.count, 0) .field.do.request() .exit;Still the units do not gather, the script makes sure through the order of requesting there is a dropsite and units and a field. // got the field foundation, all units repair, exitsw.field.on .member(w.item) .match(w.item.foundation) .units.do.repair(w.field) .exit;Here is another modifier 'match' just checking whether a attribute is true. There are two more sentences, the whole thing is currently here: https://github.com/agentx-cgn/Hannibal/blob/master/source/simulation/ai/hannibal/grp-harvester.js#L61 For sure this is just the beginning, beside grain-picker, miners, lumber jacks, builders more is needed to support a village or even launch an attack. For example there will be a scout group having an object called scanner which scans the terrain and Hannibal transforms this information into a potential field needed to tell attackers which region is safe or not, thus giving the direction of forward or back. If at this point you think - wait stop - I have some sentences in mind for another group, you're welcome. Please, let me know or even better paste them below. This is the purpose of Hannibal, it let you try out in a simple way how an AI can work. All you need to do is put yourself into the position of an 0AD unit and determine your options. That's it. I nearly spend a year getting this idea running and actually see now units building villages, powered by groups scripts. I hope, I could understandably layout the potential. Now, my target is to release a sandbox (no attacks) version within weeks, showcasing this concept. Follow this topic for breathtaking videos PS. Developers may have all alarm clocks ringing because of performance, but keep in mind the scripts are fired on events only, there are not that many groups needed and so far none took longer than a millisecond. PPS: Ok, another one. A unit of your group got killed, what's the sentence? function destroy (w, item) { w.objectify("item", item); // lost unit, request another w.units .member(w.item) .request() ;}
  12. @Teiresias: Actually I meant a documentation is the base for any following step. @Stan: I document everything stable in the github wiki. I think the code is mostly self explaining if the concepts used are familiar. And Hannibal is not ready, I hope to have a sandbox release in about 3 month.
  13. > there is no viable defense strategie... It depends, if there are more than 10,000 stone available early I tend to build (double) walls and about 12-15 siege just to defend the village. I call it cocooning. However, if all players choose a defensive strategy there is not much of a game.
  14. I've completely underestimated the time it takes to create a framework for a bot. E.g, the economy, which fires commands like train, build, research towards the engine has been rewritten already three times. I've seen recently I wrote the first line of code last February, so, to sum up, I think I spend one month to understand API and Aegis, three to research the things I like to improve and now iterate for 6 months the framework to make the group scripts run on top. I don't know whether a documentation would have cut a lot from the first month, once it clicked that entity ids + tech template names is basically all what's needed to talk to the engine, I'd made progress very fast. I've also thought of publishing here a minimal bot, which trains 1 unit, builds 1 house, researches 1 tech and runs on a given map with everything hard coded. This sounds like a 20 lines of code project and it actually is. However, to make that bot run on *any* map the next hurdle then is making the location of the building soft coded and you are knee deep in map analysis. And that is not trivial at all. I've started a wiki page about: https://github.com/agentx-cgn/Hannibal/wiki/Map-Analysis In short, I think it makes sense to lower the hurdles at the beginning, but after the first month there are still some very huge roadblocks and after that you fight with your own code and are alone anyway. I agree with feneur that an invitation to AI devs needs more than a documentation. Given the recent media coverage in deep learning and other AI topics, it might be an idea to put AI/bots on the road map and reach out. I've seen trompetin17 reactivated the JS debugger, that's a very good start.
  15. Not exactly scholar, but this fresh reddit ELI5: How are video game AIs programmed? Is it a just a long series of "If Then" statements? Why are some AIs good and others terrible? has a very long list of comments with what players expect from an AI.
  16. Good thing jsdoc doesn't document for ... of, slowest loop ever.
  17. > Actually I want to speak about only one AI(singual) and not about many AI's(plural). Actually my error, I should have made clear that an AI might share knowledge only with its own type. Anyway, if you put sync issues aside, what's left it dealing with with either file system or a web service. Happy New Year°
  18. I like this idea. I'd really love to make bots share their "their previous experiences".
  19. > specially designed maps with entities positioned I've stopped that, because I lost overview facing a packed map folder and switched to generating maps on the fly. Have a look at mainland.js or what I did to it https://github.com/agentx-cgn/Hannibal/blob/master/maps/random/brainland.js It only takes around 0.1 secs to create a map like this. > may limit the number of newcomers in this area more and more. I think most players have lots of ideas to improve AIs. There is probably a whole range of ideas, starting with "too many idle units", or "no point in attacking building X" up to "you did that already three times and never succeeded". It should be possible to try out new ideas without coding bots from scratch.
  20. > the hurdles... And there are more to manage after start Currently I think the most time consuming thing is late game debugging. A remote debugger to inspect and change variables would speed up development by magnitudes. Actually writing code, wrapping variables with print(), starting the game and starring at the console feels like web development 15 years ago. I think developers are attracted by IDE's, too.
  21. XMLHttpRequest makes bots more clever, because it connects them to the hive mind.
  • Create New...