|
Difference between revisions of "AINicowar"
From Globulation2
|
|
Line 1: |
Line 1: |
|
|
Nicowar is the new powerhouse AI. AI's for Globulation 2 generally perform bad compared to the skilled player, but Nicowar is an attempt to close that gap. Nicowar is based upon the Echo AI system, which provides easy functionality that saves Nicowar from doing allot of the work. Nicowar has a bunch of groups of functions, each of which are called in sequence from tick. |
|
Nicowar is going to be the most difficult AI in the game. It uses complicated statistics manegement along with full action records in order to achieve the best balance. It is designed as a set of independantly working modules, of which there only interaction with eachother is by applying factors to eachother. However, a module should still be able to run even if all of the modules it interacts with where not loaded. This, each module is self sufficient, but relies on other modules to help it run efficently and with the most difficulty. This is not particularly up to date so don't use this information for anything important, the code is documented much better. |
|
|
|
|
|
|
⚫ |
|
|
==Conventions== |
|
|
There are many conventions I employ when writing Nicowar. From my experience, you should assume nothing on the condition of the world. I have gone through a world of bugs where I changed something in one tick and expected the change to have taken place the next tick. Well thats not how it works. One of the primary ones would be when I created attack or defense flags. the code would assume that the flag would be created the next tick, so on the net tick it would look for the flag, and if it was found, it would be added to the records. All of the code that would get executed following that tick would depend on the fact that all of the records are valid, because the flag was creating the next tick. This is a very painfull thing to endure. At the point I declared this as one my conventions, I went through all of the old code updating it to the new convention. Another tricky one that follows this is when I was upgrading or repairing a building. My original code would assume the building was still there and still under construction. I've had to replace it, the building can be destroyed at any point in time. Even worse than that, if other parts of the ai make a suitable replacement for this building fast enough, it can assume the same gid, so the records are linked to the wrong building, and their original one was destroyed. This was also a very painfull bug, and I have had to revamp most of my code in order to keep up with it. Another hint to keep inline with this rule is: Always assume the only state that is carried between two ticks is the state that you have in your own structures. Never rely on the state of something external to be what you think it is. Use your internal state and compare it to the external state, don't make assumptions. |
|
|
|
|
|
|
|
Nicowars layout, code wise, is straightforward. First, There are a variety of phases. Nicowar phases are "fuzzy" in that they don't transition from one phase to the next. Instead, any number of phases can be active at any one time, and the effects of the phases are meant to stack. There are a large number of phases that activate any number of different behaviours. For example, the skilled work phase activates building schools, racetracks and swimmingpools, where as the war preperation phase causes swarms to build warriors, and workers to build barracks. |
|
Another convention that I have had since the start of programming Nicowar is that you should always store what you are doing. This is the core cause that the above bugs can exist. It also make Nicowar a little bit memory inefficent, and as well, Nicowar takes up the most proccessing time. You may be wondering why its a good thing at all. Well, its good for several reasons: It can help keep the AI on task and managing everything. Keeping on top of everything you're trying to manage is a bit easier if you have an easy way to know everything your supposed to manage. It also makes saving and recovering a bit easier, as the AI has to recompute nothing. It saves signifigantly on proccessing time as everything that should be happenning is known, it also saves on lots of fancy "hacks" to figure out what the AI should be doing, and has been doing. Nicowar can then be devided up into higher level behaviours easier without having to deal with the "to do or not to do" part of it. |
|
|
|
|
|
|
|
== Building Queues and Orders == |
|
A debugging convention I follow is to have a global debug mode, which is given by the constant boolean variable AINicowar_DEBUG. A debug message should be printed if the AI issues an order. There are some cases, when the AI could be issues many orders, that this should be ignored. But 90% of the time it should output some kind of debug information. As well, for more verbose debug information, keep it to the function. Put a constant boolean at the top of the function (if required) that enables or disables verbose output for that function. Most compilers will remove the debug code if the value is false (and its constant), so there is little loss of speed as oppossed to commenting the debugging code out. As well, a newly formed debugging trick is to send update messages to the core Nicowar module. These "messages" are output to the file "NicowarStatus.txt". They should contain information on why or why not the AI is doing something, and what it "thinks" its doing. Bugs will become easier to spot, for example, the other day I noticed that on a particular map, the AI wouldn't construct any racetracks. I located the racetrack construction section in NicowarStatus.txt, and to my surprise, it thought it was constructing a racetrack. A little more debugging revealed that it was misplacing its racetrack, trying to construct it on invalid positions. |
|
|
|
|
|
|
|
Nicowar bassically queues buildings to be constructed in the queue_* functions. Each of these are responsible for deciding how many of what buildings to be constructed. Buildings can also have different kinds of placements, in the BuildingPlacement enum they are listed. For now, Nicowar really has only one method of placement for most buildings, and a couple special methods for the starving recovery inns. One obvious flaw in this system is that buildings are queued based on the circumstances at point t, but between t and when the building is actually constructed circumstances might have changed, leaving one to conclude that Nicowar should build a different building. I have tried the other method, where the type of building to be constructed is done on the fly. While theorietically it should be better, in reality this method produced very poor performance, because most of the time Nicowar thinks it should be constructing Inns, leaving little room for other construction. Every once in a while, nicowar has to sacrifice building an Inn to build more important buildings for the greater good of the colony. |
|
Those are just a few of the conventions I use when writing nicowar, if you intend to write another module for Nicowar, please follow them, and thanks for your support. Now, on with the good stuff: |
|
|
|
|
|
|
|
Queued buildings are picked up and constructed in the order_* methods. Only a certain number of buildings can be constructed at once. Every building has different parameters to its placement. |
⚫ |
== Upgrade and Repair Management System== |
|
|
This was the first system to be created. It bassically manages upgrades and repairs. It will cycle through buildings (in a random order), starting upgrades(or repairs) as long as it has enough spare workers with the right skill levels. It will also retask buildings that are already being upgraded or repaired depending on how many units are available at that time. So, it can adjust to changes throughout the construction of a building. If something has happens and it discovers that it does not have enough units to keep constructing a building, it cancels construction. |
|
|
|
|
|
|
⚫ |
== Building Management == |
|
==Air Search and Assault System== |
|
|
This system deals with exploration and air attacks. Air attacks are a devilish strategy involving the fact the explorers can attack ground units after they go through a level 3 school. This makes them extremely powerfull, as they can not be defended against by anything but other explorers. However, it takes allot of explorers to harvest an attack, which can take swarm time away from other areas. Exploration is much simpler, the AI will try to uncover as much of the map as possible that is covered with hidden squares using exploration flags. It dramatically decreases the amount of time before it can see everything on the map. |
|
|
|
|
|
|
|
Nicowar really only does post-construction management on two types of buildings: Swarms and Inns. The manage_buildings function goes through all buildings, and calls the respective manage_* functions for those buildings. |
|
==Swarm Controller== |
|
|
The swarm controller takes in factors from all of the other modules in order to control the spawns on what to build. Other modules send in amount of units that they want and priorites along with them. The Spawn Controller will do its best to try and maintain these numbers of units, so that every module gets what they want. It creates ratios by adding up the number of units wanted by every module, giving 1 point for desired units, 2 poitns for required units, and 3 points for emergency units. It will then compare the ratios of the three types of units and their respective scores in order to give the ratios for the swarm. |
|
|
|
|
|
|
|
Managing Inns is fairly simple. If the Inn has less than a certain ammount of wheat for its level, then it will be given more workers, if it has more than anough wheat, it will be given less. These variables are hard coded in Beta1-rc and previous, however they are in the nicowar.txt and nicowar.default.txt files in later releases (and the Mercurial). |
|
==Inn Manager== |
|
|
The inn manager is probably the most complex module algorithmically. About every 100 ticks, the inn manager records the number of units in a specific inn, and the amount of food in it. This recording is done round robin, meaning that everytime it hits the end of the vector its recording to, it starts back at the begining. Then, every so often, the inn will compile a list of all the inns, the total number of units that were in the inn, and the total amount of food that was in the inn (some units and bits of food may be counted twice, or even more, this is ok). It then copies this list into to other lists, sorting them by the total units and the total food. In the total units one, the less units, the closer to the begining you are. With the food one, the more food, the closer to the begining you are. So, an inn that has few units and a lot of food will be near the begining of both lists. Then it makes a fourth, final list by taking each building, and compiling it with its respective score on each of the two other lists. For example, an inn that was near the top of both lists will have the highest score. Then it sorts this list based on the two scores added together. The top ones in this final list are the ones with a lot of units eating at them but with very little food to supply them. The inn manager increases the number of units assigned to each of these tied top ones. It then goes to the bottom of the list. Those inns are the ones who get very few units eating at them, and are constantly full of food. They will have one unit taken away from them. This algorithm allows for inns that are very commonly used but hard to keep full get the most units assigned to them. The algorithm also keeps track of the number of units it needs to fill the inns, and gives the swarm manager these numbers plus a few extra (backup). |
|
|
|
|
|
|
|
Managing Swarms is more complex. The variety of different phases activate different behaviours for the swarm. It also uses statistics to decide whether to assign more or less workers to the swarm, and, like the Inn, adjusts depending on the ammount of wheat in the swarm. Phases also change a swarms various ratios, for example, war_preperation turns on warrior production, and no_workers turns off worker production. |
⚫ |
|
|
|
A simple, building based, priority based ground attack system. However, this is one of the most important modules, without this, it would be impossible for the AI to actually win the game. First, when its ready to attack, it chooses who to attack by picking the weakest opponent. Some would say this is mean, however I think its effective. It then picks the buildings to attack, based on the priority. Meaning it will destroy all of one type of building before it works on the next. Since some buildings may be deep in the enemies area, there may very well be a large swath of destruction from where the AI's warriors went to get to the target building. The priorites were devised by first destroying anything that can directly benifit the enemies warriors, especially in combat. The priorites are: Barracks -> Hospital -> Racetrack -> Inn -> Swimming Pool -> School -> Swarm -> Tower -> Market. Some people may argue why hospital is so high up. Well I say, because warriors allways run to heal themselves. If units can't heal themselves, then the enemy has to entirely rely on warriors coming out of its spawn, while the rest of its army devours away at the food and without any health, don't do anything else. So the enemy becomes an easy target. Also notice that a school is a very low priority building, mainly because the school is of no use in an attack. You *wouldn't* want to be upgrading things during an attack. And without inns (which are a fairly high priority), no workers will ever go to train. |
|
|
|
|
|
|
|
== Building Upgrades == |
|
==Defense Engine== |
|
|
The defense engine is my simple, zone defending defense system. Every so often, it checks to see if a building is being attacked. If it is being attacked, it finds what zone that building is in. If that zone is already being defended, it quits. However, if it is not already being defended, it checks to see how many available warriors it has to defend with. It also counts up how many warriors are in that zone. It always tried to defend with as many warriors are attacking *1.5. If does not have enough warriors it tells the swarms to produce more with an emergency status. Then it creates the flag, and hopes for the best. It will delete the flag when there are no longer enemy units in the zone. |
|
|
|
|
|
|
|
Buildings upgrades are mostly random. Bassically, Nicowar manages a maximum number of upgrades at one moment for each building level (and a special override for schools, which should not be upgraded in parrallell). When it decides it needs to upgrade its buildings, it looks at the options. Nicowar chooses a building type to upgrade randomly (although certain building types are weighted over others), then it chooses among the buildings that exist of the type. This means the number of buildings on the map is irrelevant, except when there are 0 buildings of a type. Barracks are weighted very highly, for example, as part of Nicowars strategy. |
|
==Tower Controller== |
|
|
Probably the simplest module, all it does is tell the spawn manager how many units it needs for the towers, and assigns these numbers to the towers. TODO: Implement statistics information to find out what towers are attacked most, and give them more units. |
|
|
|
|
|
[[Category:AI]] |
|
Revision as of 03:22, 8 August 2007
Nicowar is the new powerhouse AI. AI's for Globulation 2 generally perform bad compared to the skilled player, but Nicowar is an attempt to close that gap. Nicowar is based upon the Echo AI system, which provides easy functionality that saves Nicowar from doing allot of the work. Nicowar has a bunch of groups of functions, each of which are called in sequence from tick.
The Phase System
Nicowars layout, code wise, is straightforward. First, There are a variety of phases. Nicowar phases are "fuzzy" in that they don't transition from one phase to the next. Instead, any number of phases can be active at any one time, and the effects of the phases are meant to stack. There are a large number of phases that activate any number of different behaviours. For example, the skilled work phase activates building schools, racetracks and swimmingpools, where as the war preperation phase causes swarms to build warriors, and workers to build barracks.
Building Queues and Orders
Nicowar bassically queues buildings to be constructed in the queue_* functions. Each of these are responsible for deciding how many of what buildings to be constructed. Buildings can also have different kinds of placements, in the BuildingPlacement enum they are listed. For now, Nicowar really has only one method of placement for most buildings, and a couple special methods for the starving recovery inns. One obvious flaw in this system is that buildings are queued based on the circumstances at point t, but between t and when the building is actually constructed circumstances might have changed, leaving one to conclude that Nicowar should build a different building. I have tried the other method, where the type of building to be constructed is done on the fly. While theorietically it should be better, in reality this method produced very poor performance, because most of the time Nicowar thinks it should be constructing Inns, leaving little room for other construction. Every once in a while, nicowar has to sacrifice building an Inn to build more important buildings for the greater good of the colony.
Queued buildings are picked up and constructed in the order_* methods. Only a certain number of buildings can be constructed at once. Every building has different parameters to its placement.
Building Management
Nicowar really only does post-construction management on two types of buildings: Swarms and Inns. The manage_buildings function goes through all buildings, and calls the respective manage_* functions for those buildings.
Managing Inns is fairly simple. If the Inn has less than a certain ammount of wheat for its level, then it will be given more workers, if it has more than anough wheat, it will be given less. These variables are hard coded in Beta1-rc and previous, however they are in the nicowar.txt and nicowar.default.txt files in later releases (and the Mercurial).
Managing Swarms is more complex. The variety of different phases activate different behaviours for the swarm. It also uses statistics to decide whether to assign more or less workers to the swarm, and, like the Inn, adjusts depending on the ammount of wheat in the swarm. Phases also change a swarms various ratios, for example, war_preperation turns on warrior production, and no_workers turns off worker production.
Building Upgrades
Buildings upgrades are mostly random. Bassically, Nicowar manages a maximum number of upgrades at one moment for each building level (and a special override for schools, which should not be upgraded in parrallell). When it decides it needs to upgrade its buildings, it looks at the options. Nicowar chooses a building type to upgrade randomly (although certain building types are weighted over others), then it chooses among the buildings that exist of the type. This means the number of buildings on the map is irrelevant, except when there are 0 buildings of a type. Barracks are weighted very highly, for example, as part of Nicowars strategy.
| |