Search the Community
Showing results for tags 'ai', 'api3' or 'entity template'.
-
In yesterdays IRC I mentioned about using jasmine tests for AI development and the topic was considered as maybe of interest to others. So I hereby provide a trimmed-down demonstrator on how a test suite can be set up. The attached zip archive contains a copy of the API3 AI high-level interface with two test cases (one of them discovered the problem discussed here), plus the necessary infrastructure (jasmine 3.6.0 release and driver html page). To execute the test cases, just extract the zip content to some directory and load the common-api/jasmine-runner.html file into a scriptable webbrowser. Said html file is commented to show how the jasmine framework, the API3 under test and the test files interact. Items to consider: For the demo, I used the official jasmine standalone release which contains a version number in its path. In "production use" I rename the directories to get rid of the version number so no changes are needed when upgrading jasmine. It is also possible to execute the unit tests via the SpiderMonkey js shell by loading all of the scripts and running the jasmine bootstrap code. I also managed to connect the jasmine test suite to the JSCover code-coverage measurement tool, but this requires a more complicated setup, i.e. a list of all source and test case js files plus a platform-dependent batch job and a hacked-up JSCover driver js script. I can provide a demonstration if there is interest. Any comments welcome. jasmine-demo.zip
-
Hi again, this is my second contribution to the 0ad game, but a big one for me As I promised on the ArchMod, I've developed a new AI architecture by modifying the original Petra bot. After a long (nearly 2 months) and exhausting development and testing period, it is now ready to be shared with the fans of 0ad. I have to say that AI development is really a serious job and I have a full respect to the developers of the Petra AI. Thank you very much for your efforts to develop the Petra AI. Arch AI Pack Arch AI bots are distributed as a pack that consists 9 Arch based and 4 Petra based bots. Arch Based AI Bots Arch based AI bots use Arch AI architecture. Admiral Capitalist Communist Imperialist Mason Mercantilist Patriot Theocrat Unitary Petra Based AI Bots Petra based AI bots use the original Petra AI architecture. Imperialist Patriot Single Based Unitary Initial Release Bonus: Naval Attack + Mauyran AI can produce Support Elephants and use them effectively. Capabilities: Arch AI can defeat Petra Bot except Very High Starting resources. Arch AI can start naval attacks. Best faction for Arch AI: Mauyrans (Main faction for Arch AI development) Tips: I advice to play with ArchMod. In ArchMod, you can set handicap levels for AIs. In addition, you can start with zero resources and play different game modes. ArchMod Difficulty Support: Arch AI supports Archmod harder AI levels (Insane I-X) that are harder than Very Hard AI level. Github page of the Arch AI: https://github.com/eserlxl/Arch-AI ( I'm waiting your bug reports and feedback ) Challenge: Play against Mauyrans faction with Very Low or Zero ( ArchMod ) starting resources. Installation: You can download the latest Arch AI Pack from here. Extract the release version and copy the ArchAIPack directory to the mods directory ( ../0ad/data/mods/ ). P.S. to Developers: If you give file read/write ability to the AI like readJSON/writeJSON access from the Engine, I can develop a learning AI. I hope you will enjoy when playing against Arch AI bots
-
I tried playing around with the AI API3 and set up my own entity template. Thereby I noticed an interesting behavior of the API3.Template.cost() function. I extracted a demonstrator for it: If you execute the following snippet (function (){ var rawTemplate = { "Cost" : { "Resources" : { "food" : 1, //"wood" : 2, "stone" : 0, "metal" : 4 } } }; var fakeSharedAI = { "_templatesModifications" : {} }; var testee = new API3.Template( fakeSharedAI, "someTemplate", rawTemplate); warn("Costs are " + uneval(testee.cost())); })(); in the content of an AI script (e.g. inject it into petras start-up sequence), the 0AD log receives the following entry: Note the NaN in the second property. So it seems template instantiation accepts skipped resource definitions gracefully, but I do not understand the behavior on "stone":0. Am I doing something wrong? I imagined something like "{food:1, stone:0, metal:4}" to build up.
-
Hi, I'd like to modify Petra bot to make the first AI house to be built within Civic Center range. I think the code to manage it is in this part in queueplanBuilding, but it seems to have no impact on the game. Here's the code: if (template.hasClass("House") && !alreadyHasHouses) { // try to get some space to place several houses first bestTile = placement.findBestTile(3*radius, obstructions); if (!bestTile.val) bestTile = undefined; } I tried modifying the radius multiplier to 6, 2, even 0.5 but it seems that they always end up building it outside of CC's perimeter, sometimes even at the edge of territory. I tried to find findBestTile code but to no avail. I believe findBestTile prevents any building to be built inside CC's range. Does anyone might know about this findBestTile script? Thank you.
-
Because the documentation of the AIs are not so much, i want to create a litte tutorial with the first steps to develop a new AI while i develop my own AI. Execuse me for my english, I am from Germany and my english is not the best. At first you must create the following directory structur in the directory <Install Path>/binaries/data/mods, if it does not exists. <Module Name> simulation ai <Your AI Name> In this directory you add a new file data.json with the following text: { "name": "<AI Name>", "description": "<AI Description>", "moduleName" : "<Module Name>", "constructor": "<The Constructor Method>", "useShared": true } My data.json hast the following content: { "name": "NewAI", "description": "newAI", "moduleName" : "NEWAI", "constructor": "NewAIConstruct", "useShared": true } After this we create a new javascript file _init.js, if you want to use the common-api module (optional), with this module you dont have to develop the AI from low-level. AegisBot use this common-api too. Engine.IncludeModule("common-api"); This line loads the common-api module, which can be founded in the mods/public/public.zip/simulation/ai/common-api, but you dont have to copy this module, the game find this module in the public.zip, which is in this directory by default. After this we create a new javascript file, called as your modulename, e.q. "newAI.js" and must contains the constructor method in an anonymous function, saved in a var. var NEWAI = (function() { var m = {};//an empty object //your code must be placed here //return the module object return m; }()); This constructor method must return the module AI object! ---------------------------------------------------------------- This tutorial hasnt finished yet! I want to edit this post to append new steps.
- 35 replies
-
- 2
-
- ai
- development
-
(and 1 more)
Tagged with:
-
When a force of enemy troop try to capture my Civic Center, they couldn't capture it because of the number of garrisoned defenders. So, the attackers switched from capture to attack instead. Very nice. @mimo May have been in the logic for a long time, but it really showed this time. They would capture it by about 5% but my defenders capture it back to 100% every 5 seconds or so. The attackers were all like, "Screw this!" and switch to destroy instead. Very nice, something a human player would do.
-
So, playing agains the AI, I have realized something. It never makes champs. No matter how much time I give it to build up it just upgrades its citizen soldiers. I know the AI has a lot of metal, food, and population so why doesn't it make champions? It spams citizen soldiers non-stop.
-
I had an AI opponent that walled off an area with barracks and houses but in the process trapped itself. Due to the terrain where the wooden wall was made up of short zig zags that were all too short for a gate. It had a huge army but they could not participate in the battle until I used a ram on the palisade wall. Then I got owned by the avalanche of angry units. I won in the end. It was clear that the AI could not detect that it was trapped and delete the wall. A sally port might be a solution. A port one wooden wall unit wide with limited unit rate. If this is a duplicate move it appropriately. I found nothing in a search but then I may have had the wrong terms.
-
I created this post for discussing #4395 In Aok, you have like 3 kinds of scenarios: Build and Destroy, Fixed Force and RPG. Then you would have some subtypes: Defend only (hold the ground), Destroy/assault with timer, tug of war, scripted mission with triggers (like 1rst mongol scenario) -Specific commandos: defend this unit, area. Attack this unit/area. Wait until X for other commandos or strategy. Repair never/when possible. Don't train units -Specific strategy: Only rebuild existing units/buildings, but don't expand. Don't attack, only defend. Never or always defend the ally. Forbid some units/buildings. With this I would say that there's a good basis for starting scenarios and campaigns. What do you think?
-
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() ;}
-
Hi guys. AI is back to its old trick of putting all defense tower toward top of map:
- 15 replies
-
- 1
-
Hello guys In headquarters.js is a function named "buildDefenses". In this function is the line: queues.defenseBuilding.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_defense_tower")); In this way I can tell the AI (_petrabot.js) to build defens towers, but what about walls? Does anyone know a way to do this or have any idea? Thanks for your time and attention.
-
I've found random trigger maps are superior to manually designing maps for bot testing. I can easily change number of bots and civs from the commandline without editing XML files. But that's the random map part. With the trigger part I even managed to change the resources before bot initialization and force research of technologies at game start. So a bot can build fortresses right away from start instead of collecting all needed resources and raising a town first. I'm sure I'll detect more useful possibilities soon and add them to 'brainland_triggers.js' as from trigger map code the simulation is available and Hannibal's groups scripts will make it a good choice for smarter map natives. If interested grab the files from git: https://github.com/agentx-cgn/Hannibal/tree/master/maps/random
-
I've collected quite some papers about RTS bots. From time to time I'll present here either a recently published one or one otherwise interesting. Research on agents in RTS games is very active, because the time constraints and the broad range of needed AI technologies is challenging. Doesn't doing science by playing RTS games sounds like an acceptable job description? I'll start with the 100 page thesis BDI agents for Real Time Strategiy games It is about an 0AD bot written by Andrea Dallatana. Unfortunately he no longer works on the bot. He describes in detail the mechanics of his bot. One idea I especially like is the job market to avoid units standing around doing nothing. Here is the module structure of ABot: Currently discussed at HackerNews is A Survey of RTS Game AI Research and Competition in StarCraft (2013), 19 pages. The authors specifically analysed bot versus bot games and state: ... the top three ranked bots in the competition (Skynet, Aiur and UalbertaBot) do not change their strategy at all depending on their opponent. For example, the Skynet bot (both in 2011 and 2012), always uses the same opening (two gates), except when playing a Terran opponent, when it uses nony. This reflects the trend that the performance of bots is still more dependent on carefully handcrafted and non-adaptive behaviors, ... The paper includes and describes a long list of detected bot strategies. Might be interesting to some human 0AD players too. Very technical is Kiting in RTS Games Using Influence Maps. Kiting is a trick bots can do easier than humans, because the micro management is overwhelming. In short a unit does a ranged attack on another unit and flees out of the range of the attacked unit before it reacts. I'm eager to implement this in Hannibal. Have fun reading!
-
If i want to develop an new AI, how must i do this? I have seen your little documentation at http://trac.wildfiregames.com, but how can i add the AI to the game? I added an directory simulation/ai/myAI in the directory mods and added a data.json, but why does the game not load the AI, if i want to create a new game? EDIT: It works!
- 4 replies
-
- ai
- develop ai
-
(and 1 more)
Tagged with:
-
Currently, humans and bots have almost no way to work as a team. Maybe if the human typed something like "I am attacking Purple", the AI might find that it has enough men for an attack and say "I will join". This would require some basic natural-language processing to recognize some simple statements. I came up with a list of some statements that should be looked for: "Can I have <NUMBER> <RESOURCE>?" - The AI will check if it has at least 2*NUMBER, and then tribute it if it does "Help me attack <PLAYER>?" - AI will attack PLAYER if possible "Help me!" - AI will help defend the player's base "Get off my land!" - AI will stop building Likewise, the AI could do the same and ask the human for help. Please give me your feedback and insight into implementation of this feature.
-
At game start or load a bot is thrown into cold water. He might discover a very hostile environment in terms of resources, units, buildings and enemies. Interestingly game start and end can be very similar, meaning eveything is low, if the human opponnent has victory within his grasp. But a bot doesn't give up, as long there is a small chance of success - he takes it, right? What is the worst case? Let's say no civic centers. That's close to ground zero in 0 A.D., because without CC you lack the territory to build any other structure. So, naturally the very first questions in this case are: Can I build a CC? And if not, what can I do at all? It turns out, these are very complex questions. Let's start with some simple conditions: has only resources -> whiteflag has only buildings -> whiteflag has only units -> whiteflag or fight like hellOk, that's not so difficult. And it looks translatable into straight forward JavaScript, too. Here comes the next level: has buildings, units, no resources has no CC has no CC builder can not train CC builder -> whiteflag or fight like hell can train CC builder -> gather resources -> train CC builder -> construct CC has CC builder -> gather resources -> construct CCActually that's only the surface. It assumes the units are not champions and the needed resources are available. Here are a few more: and finally: has units, resources, buildings has no CC has CC builder -> construct CC has no CC builder can train CC builder -> train builder -> construct CC can not train CC builder -> whiteflag or fight like hellCan you imagine how many conditions the bot has to check just to find out he has definetly lost? Now add more edge cases, mixin technologies, multiply with all buildings and all factions and you'll end up with tens of thousands lines of code, hard to read, difficult to maintain and taking months to write. That's where planners jump in. They know which conditions to check and how to answer them. Ontop they come up with a list of actions leading to your goal or none if your goal is unreachable. HTN (hierarchical task network) planners are conceptually fairly simple, but extremely powerful. They define a state, that's the starting point, a goal and operators and methods, the latter are just functions. Operators can change the state and methods result in more methods or operators. So, you initialize a planner with a state, your goal and then call the first method. From there it tries to decompose the problem until only an ordered list of operators is left - that's your plan. 0 A.D example: state = { resources: {food: 300, wood: 300}, entities: { structures.athen.civil.centre: 1 }, technologies: [phase.village]};goal = { resources: {}, entities: { structures.athen.field: 1}, technologies: [gather.wicker.baskets]}The goal basically says: I don't care about resources and the civic centre, but in any case I want a field and foragers better equipped. Do you see the two traps? Here's the plan: HTN: SUCCESS, actions: 8, 1 msecs op: 1, train_units ( units.athen.support.female.citizen, 1 ) op: 2, wait_secs ( 10 ) op: 3, build_structures ( structures.athen.farmstead, 1 ) op: 4, wait_secs ( 45 ) op: 5, build_structures ( structures.athen.field, 1 ) op: 6, wait_secs ( 100 ) op: 7, research_tech ( gather.wicker.baskets, 1 ) op: 8, wait_secs ( 40 )See how the planner automatically found out he needs a builder for the field and the farmstead for the technology. And the final state: resources: { food: 250, wood: 150, time: 195, metal: 0, stone: 0, pop: 1, popmax: 300, popcap: 20 }entities: { structures.athen.civil.centre: 1 units.athen.support.female.citizen: 1 structures.athen.farmstead: 1 structures.athen.field: 1}technologies: [phase.village, gather.wicker.baskets]... which can be used for your next goal. HTN Planners are well used in RTS games. The link finds a a few interesting presentations. Some games have highly optimized ones, checking hundreds of plans each tick, looking for the optimal strategy to keep the human opponent entertained. So far Hannibal's planner lacks a few features, he needs a better awareness of time e.g. calculate how long it takes to get a given amount of resources and more challenging learns the concept of parallel tasks. I'll continue when it produces heros. PS: Did I mention that's probably the first JS planner ever written for an RTS?
-
This is a little Hannibal spin-off, a bot which does nothing except logging some stats about other players. Currently it uses print() and dbgView is one way of capturing the output. It probably needs some cleansing by hand. It should look like this: time;id;name;civ;phase;food;wood;stone;metal;tresaure;unitsLost;unitsTrai;bldgsCons;bldgsLost;techs;popcnt;popcap;popmax;explored;kills0.6;1;Player 1;brit;village;300;300;300;300;0;0;0;0;0;2;9;20;300;8;00.6;2;Cleopatra Selene;ptol;village;300;300;300;300;0;0;0;0;0;1;9;20;300;8;02.2;1;Player 1;brit;village;300;300;300;300;0;0;0;0;0;2;9;20;300;8;02.2;2;Cleopatra Selene;ptol;village;300;300;300;300;0;0;0;0;0;1;9;20;300;8;03.8;1;Player 1;brit;village;300;300;300;300;0;0;0;0;0;2;9;20;300;8;03.8;2;Cleopatra Selene;ptol;village;250;300;300;300;0;0;0;0;0;1;10;20;300;8;05.4;1;Player 1;brit;village;300;300;300;300;0;0;0;0;0;2;9;20;300;8;05.4;2;Cleopatra Selene;ptol;village;200;300;300;300;0;0;0;0;0;1;10;20;300;8;07.0;1;Player 1;brit;village;300;300;300;300;0;0;0;0;0;2;9;20;300;8;07.0;2;Cleopatra Selene;ptol;village;150;300;300;300;0;0;0;0;0;1;10;20;300;8;0More columns can be easily included, the attached code gives a few hints what else is available. I use an IPython Notebook to analyze the data, it is here: http://nbviewer.ipython.org/url/dl.dropboxusercontent.com/u/354885/notebooks/Numerus.ipynb And that's me playing against another bot: numerus.zip
- 34 replies
-
- 3
-
There seems to be no way to let bots communicate with each other like the way humans do by team chat. Actually in a 2v2 game, humans v. bots, humans can exchange info and tactics, bots can't - so chatting is cheating. Imagine sending "attack in 20 sec" to your bot ally to launch a synced attack. Or "need 2000 metal" to force a tribute. Mixed teams would add a new level to the game. Is it a big problem to put two way chat on the API? Sending is already there. Just listening is missing.
-
Hello, the game "Sins of a Solar Empire" supports granular difficulty settings: Besides difficulty level (easy, normal, hard...) it supports the AI behavior for each difficulty level: Aggressor, Fortifier, Reseacher, Economist, Random In 0 A.D. it could be: Aggressor: rush the enemy with 20 units or less groups, build siege weapons, constantly rushing the enemy, build few towers and no walls. Fortifier: build up towers and walls, then train a large army and then rushing the enemy Economist: harvest many resources, before rushing the enemy, build scant military building, no towers, no walls Random: self-explanatory thanks Raymond
-
Was in need to query the templates more often than acceptable and code got littered with ifs, switches and very long condition lines. So I've spend my bot a triple store and its own query language. This is how it loads: : reading 1188 templates : 65/1188 nodes for athen : 139/1188 nodes for gaia : ignored: Brit(1), brit(59), cart(84), celt(69), gaul(55), hele(93), ..... : loaded 0/0 nodes from Hannibal.Data.RootNodes : created 79/ 79 nodes for classes : created 41/ 41 nodes for technologies : created 14/ 14 nodes for resources : created 4/ 4 nodes for resourcetypes : created 613 edges on member (entities membering classes) : created 613 edges on contain (classes contain entities) : created 111 edges on provide (entities providing resources) : created 165 edges on gather (entities gathering resources) : created 274 edges on build (entities build entities) : created 26 edges on train (entities train entities) : created 46 edges on hold (entities holding class) : created 3 edges on heal (healer heal classes) : created 39 edges on research (entity researches technology) : created 57 edges on require (entities require technology) : created 57 edges on enable (technology enables entities) : created 12 edges on accept (entities accepting resourcetype (dropsites)) : created 156 edges on carry (entities carrying resourcetype (ships, trader, gatherer)) : have 2 civs, 13 verbs, 342 nodes, 2172 edges: : have [accept, build, carry, contain, enable, gather, heal, hold, member, provide, require, research, train]The database has nodes and edges, edges represent a verb and have a direction. Nodes have a unique name. So you start a query with some nodes. Here are a few sessions, 'i' denotes the query (a plain string), 'o:' the parse tree and R a result line: Parser: i 'healer, hero' : o: ["healer, hero"] Q: executed: msecs: 0, records: 2 R: node: healer R: node: heroQueries always return nodes and obviously two classes return two class nodes Parser: i 'healer, hero CONTAIN' : o: ["healer, hero",["CONTAIN"]] Q: executed: msecs: 0, records: 6 R: node: units.athen.support.healer.a R: node: units.athen.support.healer.b R: node: units.athen.support.healer.e R: node: units.athen.hero.iphicrates R: node: units.athen.hero.pericles R: node: units.athen.hero.themistoclesHere I added a verb after and now the query has a direction, it points from classes to entities. All verbs are keywords and uppercase. LIMIT, SORT, RAND, WITH are keywords too. Parser: i 'infantry, hero CONTAIN SORT > costs.metal' : o: ["infantry, hero",["CONTAIN"],["SORT","> costs.metal"]] Q: executed: msecs: 3, records: 21 R: node: units.athen.hero.pericles, metal: 200 R: node: units.athen.hero.themistocles, metal: 200 R: node: units.athen.hero.pericles, metal: 200 R: node: units.athen.hero.themistocles, metal: 200 R: node: units.athen.champion.infantry, metal: 80 R: node: units.athen.champion.marine, metal: 80 R: node: units.athen.champion.ranged, metal: 50 R: node: units.athen.infantry.archer.a, metal: 50 R: node: units.athen.infantry.archer.b, metal: 50 R: node: units.athen.infantry.archer.e, metal: 50 R: node: units.athen.infantry.javelinist.a, metal: 50 R: node: units.athen.infantry.javelinist.b, metal: 50 R: node: units.athen.infantry.javelinist.e, metal: 50 R: node: units.athen.hero.iphicrates, metal: 0 R: node: units.athen.infantry.slinger.a, metal: 0 R: node: units.athen.infantry.slinger.b, metal: 0 R: node: units.athen.infantry.slinger.e, metal: 0 R: node: units.athen.infantry.spearman.a, metal: 0 R: node: units.athen.infantry.spearman.b, metal: 0 R: node: units.athen.infantry.spearman.e, metal: 0 R: node: units.athen.hero.iphicrates, metal: 0The syntax is simple, it starts either with nodes or a verb clause. Then you may put one verb clause after another verb clause to traverse the mesh. [ nodes | VERB [prop [, prop, [...]]] [WITH prop op value [, prop op value, [...]]] [SORT op prop [, op prop, [...]]] [LIMIT value] [RAND value] [VERB [...]]]The idea is the DB represents the involved civilisations, it's a knowledge base of their capabilities. Who can do what, what does it cost and how long does it take. Next step is to retrieve not only templates but real game units, buildings, etc. and in the far future queries written in SPARQL. Currently the code is not optimized and I don't know what happens when 8 bots load their own triple store each with 8 civilisations. You start the whole thing like this: civs = new Hannibal.Civilisations(this, ["athen", "gaia"], this.settings.templates);HCQ = Hannibal.Civilisations.Queryquery = new HCQ(civs , "infantry, hero CONTAIN SORT > costs.metal");nodes = query.execute();Code (still hot, but working) is attached, comments welcome! querylanguage.zip
-
Not sure if I'm already literate enough to pose this question properly, but here it goes: On game start from scratch or from saved game, I'd like to know whether there is a Civil Centre or not. From that point on I'm only interested in changes, e.g. destroyed by enemy or building of another one has finished. How can I keep track of the number of Civil Centres? To me looks like the engine is internally heavily based on messages/events and on each call 'SharedScript.prototype.ApplyEntitiesDelta' processes new events into a datastructure/collection ready to get filtered by an AI. So the proposed approach is to query this collection to find out the number of Civil Centers. If this is true so far there is a conflict: on one hand the number of CCs is critical to the AI and on the other hand querying the collection is very costly. This leads to the question how often can I afford to query the collection for the number of CCs? And the answer depends very much on the horse power of the local machine. Actually there many similar questions, number of females, warriors, champions, houses, towers, etc. I hope, here someone can intercept and tell me why this thinking is wrong and all these queries are not needed at all. If not... An alternate interface/API would give the AI all its items at startup and from then both only talk about changes. The AI would demand the construction of a building *and* provide a callback function the API uses to inform about changes like destroyed or construction finished. Since functions are first class citizens in JavaScript this would solve two things: Queries are no longer needed and coding an AI would be much simpler. I made a test and put this into CustomInit sharedScript.ApplyEntitiesDelta = function(state){ debMsg("ApplyEntitiesDelta: %s events", state.events.length); }Which works as expected at the cost of disconnecting the enemy AI from the game. May I ask to apply a little change to shared.js and allow AIs to implement ApplyEntitiesDelta as they like? Edit: I understand the consequences on the use of gamestate.js
-
I'm opening a new topic since the API version 3 has now been committed. Kind of a conclusion on the past 2 weeks' work before I head back to school, and probably abandon developing 0 A.D. for a good 2/3 months. Warning: this is a huge wall of text, mainly intended for my own reading later, so that I may pick up where I left off without too much trouble . So basically I'm fairly happy of how much progress has been made on Aegis in these 2 weeks of holidays I got (on top of the work I did back then). Defense has been fixed to a fairly great extent, the attack has improved, the economy has learned how to deal with technology and phases without really losing much in terms of efficiency (there's room for improvement, though), and generally everything has been made more robust than it was before. There is however still a lot to do, as most players and myself can already tell. I would like it if we could release a "Hard" AI that did not cheat. Currently hard mode cheats by gathering 33% faster (and very hard 66%). In order to do this, many things to consider: First, the AI build order needs to be perfected. I've watched replays of mainly Quantumstate and Alpha123, but there is still work to be done, everything is not perfect. Furthermore the economy manager still isn't completely rational in the way it assigns workers, which makes the AI lose a few precious seconds now and the, but this is particularly problematic in the early game. Also, it doesn't trade. Secondly, the AI is still very hardcoded. I've switched most of the "time" checks to "number of workers" checks but this is far from enough. The AI is generally hardly aware of itself when it takes decision, thus leading to average decisions, and mostly to a lot of trouble with unexpected cases. In particular, raiding the AI early currently tends to cripple it, as it does not recover well enough, trying to start attacks instead of focusing on rebuilding an economy, things like that. Thirdly, building placement in general needs to be improved. the code for dropsite placement is in itself fairly efficient, and returns generally pretty good results. However, the code that decides when to build a dropsite is extremely inefficient. Placement of most other buildings is basically random with a few tweaks and doesn't really follow any particular logic, when it probably should. Third big issue: the defense system is still quite flawed, both from the "no sense of self" effect of the AI, which will make it defend useless things, defend in obviously losing battles, or not defend enough when it ought to, and the many flaws in the logic. It's basically very "instant" defense, it doesn't really consider what happened in the past or what might happen. Case in point: a tower on the border near an AI dropsite will basically make it get all its workers killed as it doesn't really notice. Fourth big issue(s): attack and unpredictability. The first subpoint is that the AI sucks at attacking. Basically it makes relatively balanced armies, but it sends them to the enemy and doesn't really consider how to use these units the most effectively, making its attack mostly useless against a skilled (micromanaging) player. Secondly, the AI is extremely predictable. It has only one real "strategy", if you can call it so, which is also extremely hardcoded and not at all enemy dependent. Work on that is less of a priority, of course. The AI should probably handle the above points first, and then we will be able to consider making it actually do interesting things. Finally, I'll post again the "to-do" list I had posted on the AI API version 3 topic back in early november, as most of the points are still valid -No real naval support. It can handle attack over water, in a basic way, but that's it (Update: that actually might have become slightly buggy) -No handling of multiple-island realms. For Aegis, its starting island is all there is on the map. -No handling of the cases where the AI runs out of resources to gather. It will start lagging and clogging the queue manager. Linked with the above points. -The defense system is really basic. It can't handle continuous frontier skirmishes, placement of defense buildings is not logical, no wall building, it's not reacting perfectly to attacks either. No sense of "this is a dangerous area, I should avoid going/collecting/building there". No support for building units that counter the enemy favorite units. So many other things... -No diplomacy support (see Fexor's post in the general development forum) -Economy is still perfectible: drop sites placement and building could be optimized, as could be building construction, or even Build Orders in general. There are some slightly insane behaviours here and then. Generally this is probably the area where the AIs hold up the best, particularly Aegis. (Update: see above.) -Very partial technology support. Aegis goes up in phases, but it's not flexible. The API support for tech may not be perfect either. (Update: actually, it now researches all techs, but chooses them randomly. So work needs to be done on that). -Partial attack system. It's OK at strategy, but bad at tactics and will generally attack inefficiently (though Aegis is better than qBot at that). -no LOS/scouting support. AIs see everything. (Update: this is actually linked to making the AI react naturally: even when cheating, it should be aware of its enemies and take decisions based on them) -optimization is far from perfect, though it's slowly getting better. Some possible improvements: hierarchical entity collection filtering, getting the AIs not to iterate over all units in a single turn once in a while but balance the load... (Update: probably better now, but there is still ton of room for improvements). A last word about something that is still bothering me: the queue manager. Currently it gives "accounts" to each queue which grow over time as the AI collects resources. It works fairly well, but it has a tendency to make the AI sit on resources, particularly when the gathering rates are low and the needs high. I think going for the most human approach here is what would work best, but I must say I actually have little idea of what the "human" approach is. Basically we might need the rest of the AIs to register what they will probably want to train/build in the next minutes for the future needs to be fairly stable (which will also help econ…). Then we need the AI to actually pass stuff, making sure it doesn't sit on tons of food just because the next item needs a little wood, and to do it with the maximal efficiency. I am not sure what the best system for that is, but I think the current queue system isn't quite perfect. Edit: moved to general forum.
-
i setup a match i'm using 0AD SVN 14574 and the AI Don't work, i only setup a game and hi bug from begining this is the result
-
I create a mod "simply a copy&paste of celtic structures of a "germanic faction", for humans is good!!, buildings "celtic tavern as barracks" "celtic barracks as fortress" but the AI can't understand the fancion! explantion: the AI trains units and soldiers, but when is the time of create structures and a huge army, can't do it! he link of the mod is: https://dl.dropboxusercontent.com/u/101275290/tribusgermanasmod.zip