Free and Open Source real time strategy game with a new take on micro-management

AINicowar

From Globulation2

Revision as of 06:30, 17 May 2006 by Gizbot (talk | contribs) (Inn Manager)
Jump to: navigation, search

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.

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.

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.

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:

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.

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.

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.

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).

Ground Attack System

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 path of destruction from where the AI's warriors went to get to the targett building. The priorites where 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 fiarly high priority), no workers will ever go to train.

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.

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.

Misc