The story of the creation of a classic RTS at home from scratch + analysis of the main stages of development (AI, network, etc.)
The article will discuss one very new project that was created at a completely different time and in completely different conditions. This is my old RTS called Onimod land. To make it immediately clear what it is, you can watch a short video:
It would probably be correct to immediately clarify the following: This game was once programmed by me personally from scratch without engines, designers and other modern tools. The project is quite large and was done on pure enthusiasm for several years. Contrary to all the laws of economics, I managed to bring this work to an end, though by the time the number of the development team had already decreased to one person. Unfortunately, at the time of its release, this game could not for many reasons be in demand by the broad masses of players - the games market changed first towards 3D, then towards casual games. For a long time, this game lay with me, so to speak, "on the shelf", and I myself have long ceased to be a game developer. ')
Nevertheless, it is quite interesting for me to recall how all this was done. Especially since I personally play my own game with great pleasure. I’m not at all sure that the well-known Blizzard made its Starcraft in the same way as I did, but I remember that in the course of development I occasionally ran into the same problems that the Blizzard developers had come across in their time. This could be understood by the decisions that they and I had to use to get out of the same “situation”. My version of how I did all this, I bring to your attention. In the end, I will briefly describe the conditions themselves in which the development took place, as well as the “rules of the game” that were set by Russian publishers at that time. The article attempts to describe the general structure of the classic RTS. Naturally, the description will not be particularly detailed, since there is no way to describe in detail such amount of code (and, frankly, even for the author to keep in mind subtleties of implementation is unrealistic, especially considering how many years have passed). However, I would like to hope that even a superficial idea of ​​how all this is done from scratch, I will be able to illuminate. In some places I will insert small pieces of the source code, but I will do it, rather, to demonstrate the principle than for anything more.
The following mechanisms will be considered, which, in my opinion, are fundamental:
Graphics (in what form, what and how).
Game resources / resource editor - preparing sprites for the game, creating game objects (units and buildings).
Object management is a tale about how to make units do something.
Algorithm search path.
AI or Artificial Intelligence - the section first examines the actions of the Instincts or the innate intelligence of the units, and then tries to clarify the process of global command management.
Network.
Briefly about the authors and the work done.
Starting conditions and their consequences - this is a lyrical section, not related to the essence of the article. I decided that it would not be superfluous, since our ideas about that time may be different. Therefore, I will briefly cover my version of the situation in which this project began.
Rts
As a game genre, the RTS with the type of 2D graphic in isometric was unambiguously chosen. This choice was justified solely by our personal preferences. I chose C ++ as my main programming language, which after a long programming process on an assembler on a Z80-type processor (ZX-Spectrum) seemed to me very simple, because in its essence it strongly resembled a very high-level assembler. Although I have to admit that for a long time I could not get used to using virtual functions, and without this, C ++ is very similar to ordinary C.
In my opinion, if you make a game from scratch, the first thing to do is to get at least some image on the screen. This means, of course, that the image should be meaningful, i.e. their appearance test game mechanisms. The main point here is the way the graphics get into the game and its subsequent rendering. From these two moments you need to start everything.
Graphics
At that moment, the vast majority of games used 8-bit color resolution, and we logically decided that we would go further and our game would use 16-bit colors. Why not 24-bit? At that time, 1 MB of memory was present on the video cards as the norm. The amount of memory that is required for one screen surface of 800x600, respectively, will be 800 x 600 x 2 = 960,000 bytes or 937.5 KB. Those. under one screen surface, almost all of the video memory of the video cards of that time was used. Initially, our game should have been able to work in the 640x480 screen mode, but later this question was revised at the moment the game works with any resolution that the monitor allows.
Graphics storage requires memory. It is clear that it will not work in my case to store something on a video card, and this is not possible given the requirements. Therefore, the sprites should be in RAM.
The following requirements were made to the sprite itself:
Sprite must have a name.
A compressed sprite can be of any shape, not just rectangular. Pixels that are completely transparent on the original rectangular shape are indicated in a special color so that they can be discarded.
Translucent pixels are not used.
The sprite can contain an identification color that can be changed while drawing. This is required to “mark” units / buildings belonging to the same team with their own color.
Instead of a 16-bit color coded sprite should contain a color index in the palette, which is encoded by 1 byte. Palettes will be built separately for a large number of sprites. This approach made it possible to greatly save on the storage of the color itself, but it required the ability to switch the current palette during rendering. However, most often the sprite was enough for one palette.
The sprite must contain the so-called pivot (the coordinate of the beginning of the sprite), relative to which the drawing is made.
Sprite may have dimensions in "cells". The playing field is a cellular world, so it is sometimes useful to know the space that a sprite occupies on the playing field.
The picture shows the size of sprites in the “cells” and the position of the sprite relative to the cells, i.e. pivot.
As a result, on the sprites, I made the following decision: to store the graphics in memory in compressed form and decode it at the moment of output to the screen. The main advantage of this option is the small amount of memory that is required by the sprite, the main disadvantage, of course, will be the constant decoding by the processor of each sprite at the time of drawing. What is required for this? You need a compression format and an algorithm that will compress and decompress the image.
For compression, the following method was chosen. The algorithm ran along the rectangular area of ​​the sprite vertically, starting from the upper left corner. Vertical inseparable stripes of pixels served as the basis for drawing (the vertical was chosen from the simple consideration that units basically have a larger size in height). Each such strip was remembered as an array, about which the number of pixels and the colors of these pixels are known. When the strip was interrupted by an “empty” pixel, the next vertical strip was searched for. Between the end of one strip and the beginning of the next, the offset of coordinates was preserved, which made it possible to avoid storing and, most importantly, drawing “empty” pixels. To all this, tricks with palettes were added that could switch on the go. In a simplified form, the compression format consisted of the following commands:
The offset of the coordinates relative to the previous batch of pixels
Array of pixel colors vertically (number, then color)
Installing a new palette
All this is not bad, but the question arises, what about the color that identifies the team, i.e. constantly changing? The solution in this case is quite simple. This identification color can always be coded by the 0th index in the palette. Then the zero color in the palette will be, as it were, reserved for variability. But before drawing, the sprite is sufficient in the used palettes to replace the very first color with the color of the command, and the issue is resolved.
As an additional optimization, this technique was used. Many buildings contained an animation that took up much more space than a static sprite of a building would take. But since the building itself was always displayed as a static sprite, and the animation was superimposed on top of the sprite, then from the animation you could throw away those pixels that coincided in color with the color of the static sprite of the building. Usually this would remove most of the pixels from the animation sprite.
For example, in the game, Farm looked like this:
In reality, the graphics were stored as follows:
Now it is necessary to solve the problem with decoding the compressed image. And this task is much more difficult than the compression itself. The principal difference is that the image can be compressed in advance, i.e. not caring about the speed of this process. Decoding is to be done on the fly, all the time for each sprite displayed on the screen. And it was precisely in this moment that the main difficulty lay. The second difficulty arising from the first was that sprites must be decoded in different ways. For example, imagine that some unit turned on the “masking” mode, which visually looks like it starts to quickly become transparent almost to complete dissolution. Or, for example, flying units should have a shadow on the surface of the landscape, with the shadow actually being a separate sprite so that the flying unit could change its height while the shadow remained on the ground. The shadow is always black and always has transparency, which means it can be decoded using our own algorithm.
Or one more example aimed at optimization - if it is known in advance that the sprite uses only one palette, then it is enough to set it once and, when decoding, not to check for a change in the palette at all. In general, there are plenty of options for improving the decoding algorithm for particular cases. There was even such an exotic version of the sprite decoding, which checked for hit in the visible area of ​​these coordinates, which was required to check for an exact mouse hit.
In addition, all decoding options were duplicated for the following cases:
A mirror image of a sprite horizontally.
Sprite is partially outside the window. Those. it was necessary to cut a piece of handles that did not fall into the visible area of ​​the screen.
For decoding, it was decided to use assembler, since this algorithm was the bottleneck in the entire program. The assembler allows the programmer to effectively use the registers of the processor, rather than placing variables on the stack, as the compiler usually does. As a result, several dozen functions were written on the assembler, which, in fact, did the same decoding, but with different nuances. The required function was called from C ++, receiving as arguments information about the compressed sprite and the intricacies of its visualization.
As an assembler, tasm32.exe was used. The command line for assembling an assembler looked like this:
tasm32 / l / ml / zi modul_s.asm , where modul_s.asm is the source code in assembler. The result was an object file modul_s.obj , which could already be linked to a C ++ project.
The function call itself from C ++ looked like this:
extern "C" bool AsmSprite (parameters) ;
Resources
The question of storing and editing resources is perhaps the most important question that determines everything else in the future. Therefore, in my opinion, the creation of any not the smallest game should begin with the creation of a resource editor. Ideally, you should have a visual editor that allows you to make almost any changes to the game without the help of a programmer. Those. when creating a game, you need to play the game, oddly enough, last but not least, and your first assault should be aimed at creating such an editor. The resource editor should not be confused with the map editor - they have completely different purposes. The map editor is a task; on the contrary, it is already “under a curtain”, since in order to draw maps you practically need the game itself to function.
So back to the resources ...
In my case, the game should handle the following types of resources:
Sprites (serve as images for all other types of resources)
Inanimate objects (trees, stones, minerals, various decorations)
Living objects: units and buildings
Shells (arrows, nuclei, rockets, magic)
Upgrades, i.e. studies that can be performed during the game in order to improve the characteristics of a unit or building.
With sprites, everything was more or less clear. They need to be loaded, compressed and stored in large portions in a separate file, which the game can then open by itself. Since the sprite has a name, in some cases it is quite possible to identify by this name the belonging of the sprite to non-living objects.
As I said earlier, at the initial stage it is very important to get an image, so you can start the resource editor with the ability to load and compress sprites.
Next, it was necessary to think about how to teach the resource editor to create Living Objects. To do this, it is not enough just to have a set of pictures, it is necessary to combine these pictures into animations and explain to the game what exactly this or that animation is used for.
Let's see what the usual actions can perform a combat unit in the RTS. Obviously, the unit must be able to be in a state of "doing nothing" - let's call it Waiting. Next, the unit must be able to move - let's call this action Move. A unit must be able to fight - let's call this action Impact (in general, the impact may be positive, for example, Healing). And, finally, a unit that was unlucky with the commander must have the action Death. These actions are a basic set of a true warrior.
In fact, the situation with the Impact was much more complicated, as there were additional stages. A complete Impact cycle could look like this:
Preparing for Impact is practically a preparation for shooting (the Crossbowman crouches for a shot).
The impact is actually the shot itself.
Reloading weapons - in the settings of the unit, you can specify the number of shots without reloading, then the weapon needed to be reloaded (Crossbowman lays a new arrow).
Pause between Impacts - there could be any animation here, but the most important thing is that this stage can be accelerated by upgrades, then the unit starts to shoot more often.
Exit Impact - the target is destroyed and the new target is absent, so you can enter the normal mode (the Crossbowman, who crouched for firing, straightens up).
In addition, this whole scheme is greatly complicated by the fact that we do not have 3D, and therefore it is impossible to simply turn the model to show it from different sides. Therefore, the animation must also have a Direction (up, down, right, left, etc.). These directions, of course, must be fixed, and we must take into account that each Direction, in practice, requires duplication of all unit sprites. Based on this, 8 directions of movement were chosen for the units, and in reality they were reduced to 5, since only the “up” and down ”directions do not mirror in opposite directions.
For units that were too abruptly changing their direction, an action was added: Turn, for example, the Tank turned in place to change the direction of movement.
Properties possessed by the animation:
Action - shows the game capabilities of the object (Standby, Move, Impact, etc.).
The direction of movement (5 pieces) is required so that the object can be visually displayed in different directions. Usually, for each direction of movement, you will need to duplicate the animation with all its properties, except, in fact, sprites.
Completion of animation:
Ending - the animation ends (if there is nothing more to do, then the animation usually starts on Waiting)
Looping - animation starts from the beginning (useful for Buildings where animation can be played indefinitely Waiting)
Transition - launching another animation, additionally you need to select an animation (allows you to combine animations with one another, you can use random animation from several options).
New object - at the moment of termination the current object turns into a new one, which must be specified (useful thing for the case when, for example, the Shaman revives the Statue, ie, it is required to turn the building into a unit).
Death - the current object is destroyed in the memory of the game.
Interruption of the animation is a sign that the animation can be interrupted by the user's actions (poked somewhere with the mouse). Additionally, you can specify the animation that will be executed if the user tried to interrupt the current animation. (For example, a Soldier in a state of rest holds the machine gun in front of him, and when he walks, the machine gun behind him - instantaneous switching between these states would not look very good, therefore there is an intermediate animation that visually removes the machine gun behind his back, and it will work before the Soldier budges).
Speed ​​- allows you to specify the speed of the animation in percent.
Icon - an image for the control panel where the user clicks to perform this action.
Cost - some actions are not free, for example, for a magician to conjure, he needs energy.
Frames - animation consists of sprites or frames. This is the most important property of animation. Most often, the frame only displays the corresponding sprite, but there is also a lot of additional functionality:
Pause - determines the delay of the animation on this frame. It is possible to use random delays. Pauses well help to portray the unhurried decomposition of a killed warrior, since usually the corpse is present on the map for a very long time after his death.
Sound - you can play any sound file. This property is well proven in the animations of firing from a machine gun or pecking an enemy with a sword.
A function is a specific action that is performed on a given animation frame. It was possible to simultaneously set several functions on one frame (for example, launching rockets from two barrels at once). We list the main functions (although they are a bit more):
Impact - this is the very moment when the enemy gets a hatchet on the head. This, of course, is the simplest use of the Impact function; in fact, additional parameters allow you to specify the type of this impact. And here in the list there is not only a Physical blow, but also Treatment, and Stealing magic, and a whole lot more. Also, the type of impact includes such ordinary affairs as Resource Extraction (the Worker knocks the Resource Extras function on the tree with a hatchet and fills him with wood from the tree), and also here is a banal Repair of a Broken Building when the Employee returns the Building life. Any Impact is always directed at the current target on which the unit performs the action.
Explosion - according to the coordinates of the current object, an explosion is carried out at which the force and radius of the shock wave are adjusted. For an explosion, you can also choose the type of impact, but usually it is just a Physical blow. It is logical to assume that the Explosion function is usually used not by Living Units, but by Projectiles that explode when reaching the target.
Object origin is a function for creating another object. For example, an Archer using this function should create an Arrow on a given animation frame. Additionally, for the Arrow, you will need to specify the coordinates by which it will be created, that is, in practice, you will still have to drag the Arrow sprite across the screen to correctly position it relative to the Archer. Naturally, to position the object being created relative to the creator is necessary for all directions of movement, i.e. in practice, this operation was performed 5 times. In each case, an Arrow sprite was selected that would be more appropriate for the current direction of the unit. The arrow in the game began its existence with this sprite, and then it could turn on its own, depending on the direction to the target.
In fact, the possibilities, of course, were much more, but there is not much point in enumerating everything - the main thing, perhaps, principle.
Naturally, units must have characteristics, such as strength, protection, amount of life, movement speed. For them, the building in which they will be produced, production speed, cost, etc. must be defined. There are units that can carry other units, i.e. Transports. There is an option when units are not just transported by Transport, but also shoot from it. Some units can fly, respectively, for them it is necessary to determine the altitude "from" and "to", within these limits the flying unit can change its height randomly. Some Buildings can act by analogy with transports, i.e. units can get inside, for example, Archers can be placed in the Defense Tower to shoot from it.
Separate should briefly mention the objects Shells. The projectile can hit ground or aerial targets, be navigable, i.e. , .. . . , 8 , . , . , . - , , .
The task of this phase is to deliver the resources collected by the farmer to the Vault. Strange as it may seem, this phase is in many respects similar to the EXTRACT phase, since, in practice, this phase uses Impact called Resource Delivery instead of Impact type Extraction. As I said at the beginning, there are a lot of Impact types in the resource editor and each unique action on another object requires its own Impact type. This, of course, includes all kinds of magic that exist in the game. Again, the phase is initialized first through the INITIALIZATION function, which makes the getter current Impact of the type Delivery resource. Next, you need to decide on the Warehouse, where it is more rational to deliver the resource. There may be a lot of storage on the map, so you need to select the nearest one. However, to make this search every time is irrational, since the Storages do not move around the map and, therefore, it is enough to select the Storage once, remember it and then carry the resource there. Actually, I almost do it only if suddenly another Vault appears, then I reset the previously found Warehouse of all earners on the map so that the search is repeated. For greater intelligence, you can perform a new search also periodically, since in theory the getter can be very far away from the original place of production.
The ACTION function performs the Resource Delivery action. Again, for the Employee, everything is relatively simple, since the Storage serves as the target, and for the Employee, the Delivery Resource animation does not create any Projectiles, he must come close to the Storage, so he stomps his legs to him. At Onimodov ITR comes much more interesting. His animation on the delivery of the resource contains the creation of the Projectile, but this projectile does not destroy the target, but has an Impact of the type Delivery of the resource, i.e. hitting in the Vault, he will transfer the resource to his team. This eliminates the need to run every time to the Vault and back. The Impact itself has several stages. First, there is preparation for the Impact (ITR plunges the pipe into the ground), then animation of the Impact is performed, which throws an invisible projectile flying at a very high speed into the Storage. The projectile has an interesting function, which I did not mention earlier, it is attached to the target, in practice, something like landing in Transport occurs, i.e. The shell as it falls into the warehouse, as if in a pillbox. At the Vault, 6 seats are predefined, where “passengers” can attach, and the Projectile is attached to the free space and immediately starts the animation, which is observed on the Vault as a pipe that has come out of the ground. Visually, the whole scheme looks like the ITR launched the pipe under the ground, and it crawled out to the Vault. The pipe on the Vault, after performing the animation, simply dies, as its animation ends with the action of Death. Then the engineer performs the animation Exit from the impact, i.e. tightens the pipe back. Everything, the resource is delivered. Naturally, all the ITR animations at the delivery stage are set up so that the player will not be able to instantly gain control of the unit - the ITR will first pull the pipe out of the ground, and then it will be able to go somewhere.
Then, control is again transferred to the START_EXTRACTION phase, but since the engineers and technicians are ready for production, is located next to the resource and already in the buried state, then the START_EXTRACTION and WAIT_EXTRACTION phases in 99.99% of cases will be skipped and the EXTRACT phase will immediately begin. An exception will occur when the Warehouse is already too far away and the Projectile simply does not reach the target. In this case, the animations will complete their task as follows:
Since the distance is too far, it is necessary to get closer to the goal, and the engineers and technicians at this moment are visually in a "crouched" state. The command handler tells him to move the wheels in the direction of the Vault, but first you need to exit the production animation, so the animation will first run, which visually detaches the engineers and technicians from the resource. Now you can go and the engineers will go to the warehouse. Having arrived at a sufficient distance, he will need to perform an Impact of the type Delivery resource, but she has the training, so he will first release the pipe. After the resource is delivered, the control will be transferred to the START_EXTRACTION phase, but since the resource is now far away, you will have to go to it again.
The above example was intended to demonstrate the mechanisms underlying game mechanics literally "in a nutshell." I wanted the information that I gave about the capabilities of the resource editor to be somehow related to the specific actions of the units. Please note that the COM_EXTRACT command for both the Worker and the ITR is completely identical in terms of code. But the settings for unit animations in the resource editor make the resource extraction process completely different. That is why it is important to have ample opportunity to customize animations.
Under each action that can be performed must exist its own team. In this case, for example, the commands COM_GO (go to the specified point), COM_DESTROY (destroy a specific target), COM_ATTACK (go to the specified point, destroying everyone in your path), COM_RUN (run away from the attacking enemy, since there is no possibility to defend) and COM_LEAVE (move away from the place where the building will be built) are, in fact, different. In my case, in the code I observe about 50 teams, which ensure the functioning of the entire game.
Also note that there is even such a nice command as COM_CANCEL, which simply cancels all other commands. Why is it needed? The fact is that at the end of the article I will briefly describe the network, and the network should be able to transfer any actions that the player performs, since these actions should be repeated one-on-one on another computer.
Finding the way
Units must be able to navigate the map and find an effective route in difficult cases. This issue should be given sufficient attention and time. At the initial stage, I would recommend to make any simplest solution, if only you can test the units created by artists. The real path finding algorithm will be needed at the moment of creating the AI, when the computer should be able to build a path in any of the most florid situations. Without a normal pathfinding algorithm, AI cannot act effectively, except for some exceptional cases where the playing field is the “bare steppe”.
So, we have more or less debugged game mechanics, units are able to perform the prescribed actions that they receive with the mouse, and the program does not fall out every 2 minutes. The next stage is the creation of an effective path finding algorithm. At the moment, there are quite a few tips on this topic on the Internet; I cannot say how good or bad these methods are, since I once invented my own and, in my opinion, a very effective solution to this. It is possible that it roughly repeats some kind of subsequently published algorithm, since the solution is really quite elegant. But, as I said, all the solutions that I show in this article at that time I generated with my head on my own.
Detailed article on my method of finding the path in the classic RTS is available here . In addition, in fact, the search algorithm itself, there is described the process of managing this algorithm. This section deals with such problems as the collision of units with each other while moving, following another unit (the target is constantly changing its position) and other not so obvious moments. The article was written 10 years ago and for me personally it was intended to “not forget” about my own decision. I don’t see much sense in duplicating this information here, especially considering that this information is already quite a lot.
AI (aka Artificial Intelligence)
Let's first deal with what is AI. Personally, I define AI for myself as an algorithm that replaces the actions of a live player that it performs with the mouse and keyboard. Now pay attention to what ... if the units in your game are not completely stupid, then they can independently make some decisions and carry them out without the help of the player. These solutions in my case include the following actions:
Warriors, noticing the enemy within sight, must independently engage in battle. Moreover, if some warrior from the squad got involved in a fight, then “colleagues in arms” should not stand and indifferently “smoke” a little to the side of the scene of action - they are also obliged to join the battle.
If a unit can heal, then it must automatically cure wounded warriors. This is especially effective if you give the order to the doctor to follow any warrior from the squad - by hanging around following the squad, the Doctor will cure everyone who needs it.
An idle worker will automatically repair a wounded building or help build a new building. In my case, the Worker even analyzes the “degree of brokenness” of the buildings and can interrupt the current repairs and start repairing the building that needs it most. This quality can be very useful when Employees “fuss” between several Defense Towers that are under fire at the same time. Reinforced repairs should be made at the tower, which is about to collapse. Additionally, the algorithm ensures that the distribution of Workers by “construction objects” is reasonable, and not according to the principle “all forces per building”.
The resource miner should automatically find the next resource next to it if the current one has ended. If there is no such type of resource, but there are other types of resources, then you need to look at which resources the team has less and obtain this type of resource.
Units that possess magic must independently take care not to die in vain. Practically, when a mage deducts life, he checks the amount of life left and, if it is already critically low, it is logical that the player most likely will not have time to react. In this case, “doing nothing” is equivalent to the fact that the magician will simply be killed without causing any damage to the enemy, so the magician uses magic himself.
A unit that can turn on the disguise mode (invisibility) will automatically turn it on if it is hit, but it is not in the field of vision of the Key (a unit that unmasks invisible enemies).
Units are able to automatically move aside if they interfere with the construction of a structure.
With some pressure, the unit’s ability to follow the moving target, i.e. if one unit is ordered to follow another, then the unit will follow him everywhere as if he were tied. At the same time, the “tied” unit may well shoot the enemies or carry out the treatment of friendly units, and after finishing this matter, again run after the “target”.
As can be seen from the above examples, all these actions do not require player intervention. Accordingly, my own formulation that “AI is an algorithm that replaces the actions of a live player that it performs with the mouse and keyboard” does not correspond to these examples. So, all these examples have no relation to AI. For myself, I once gave the name “Instincts” to these actions. Unit instincts are the most important part of the game, since they take care of routine actions, which are often impossible to keep track of, from the player. And the overall comfort of the game depends on the quality of the available Instincts. Instinct has a specific unit, AI controls groups of units and performs global tasks such as “Establish a new base for resource extraction”.
The reasons for the manifestation of instincts in the game a person often sees with the exact opposite. For example, when an employee runs to repair a building, it seems that this is an initiative of the employee himself. In fact, the burning Building “calls for help” in a small radius from itself of all the units that have in their arsenal Impacts like Repair. The same applies to the situation where nearby soldiers come to the warrior to help - this is a response to the call “Help-and-and-those! Killing-aaaa! ”
Despite the fact that, in my opinion, Instincts have nothing to do with AI, I put a small description in the section with AI, since for many such an arrangement would seem quite expected. But, in my opinion, Instincts belong to the general game mechanics, i.e. according to the mind, they should have been described a little higher in the text. And the game mechanic at the time of writing AI should already fully function including the section on Instincts of units. Instincts should work in the same way for the team that the live player controls and for the team that the AI ​​controls. In their decisions, AI should not descend to the level of Instincts, its tasks should sound something like this: “form a detachment and send it to the attack at such and such coordinates”, and the fact that this detachment will already crush everyone in its path is a task Instincts.
So back directly to AI. In my case, for each command that the computer manages, the AI ​​handler is called approximately 1 time per second. AI is guided in its actions by the following global principles:
There are teams of enemies and there are teams of allies. Accordingly, the enemies must be destroyed, and the allies come to the aid in difficult times.
Some of the enemy teams are designated as the main target for an attack, but from time to time this enemy may change.
AI has a Base concept, which is key. The base is, in fact, a cluster of several buildings on the map. Each base has its own boundaries - a rectangle, which occupies the base. If there is an interpenetration of the two bases, the AI ​​produces their union. Each base is built its own defense, and any unit is tied to a base, until he received some task.
The main tasks performed by AI:
Development
Attack
Protection
Search for an opponent
Definition of invisible warriors of the enemy using the determinant
To be precise, the intellect can perform 15 types of tasks. The most interesting thing is of course the tasks that relate to the attack. Whole intelligence can attack in 6 different ways:
Simple attack. The detachment is assembled near the target of the attack, but where it is not visible and then it attacks.
Siege attack. Something resembles a simple one, but a squad, sitting next to the target, does not immediately attack, but waits until it has accumulated enough strength. Forces gradually tightened and when they are enough, an attack occurs. A side effect of a siege attack is that in parallel, a blockade occurs, sometimes the only entrance to the enemy’s camp. Also, AI can roll out a catapult forward during the siege and start shooting the enemy's defense towers from a distance, while the main forces stand behind the Catapult and wait for the reaction of the besieged.
Destruction of a specific goal. Sometimes some enemy units (usually tanks) are positioned so that they shred the forces of the attackers without any serious losses on their part. This moment is monitored and periodically the intellect undertakes punitive raids specifically against these units. For this, flying vehicles are used, from which the warriors land directly on the target unit.
Subversive attack. Punitive raid in the heart of the enemy base. For this purpose, Transports are used, which land soldiers behind the line of defense of the enemy. Basically, warehouses with large concentrations of workers are attacked. The second variant of this attack is the landing of warriors on the nearest slope, from where it is possible to shoot well downwards and where the enemy cannot climb.
Magical sabotage. It can be executed only by either the Shaman (from Botswana) or the Scientific Module (from Onimods). The performers just start hanging around the camp of the enemy and sometimes leave the magic in a gaping enemy warrior.
Superataka. This is a simple attack that is done jointly. Before it happens a slight lull - the accumulation of forces. Further, all AI that are in the same union attack at the same time.
Genre: RTS - real time strategy Programming: Alexey Sedov (aka Odin_KG) - Programming Technologies: C ++, Assembler, DirectDraw - System requirements: Windows XP, Windows 7 (the network in 7-ke does not work, but otherwise everything is in order) Drawing: Roman Kovalenko, Konstantin Ivanov - Graphics style: 2D isometric (approximately 12 thousand sprites are used) Music: Dmitry Golov Way of development: Enthusiasm Development time: 1998 - 2005 Download page:Land of onymodes ~ 53 MB . Mode of distribution: free
Starting conditions and their consequences (lyrical section)
So, in the yard in 1998. Let's take a quick look at the surrounding reality of the then IT industry. Intel released the processor, already at 233 MHz, Blizzard is already known for its “Diablo 1” and “Warcraft 2”, and Microsoft distinguished itself with the help of “Age of Empires 1”. Almost all PCs have “Windows 95” installed, which some are already trying to upgrade to “Windows 98”. On the flea markets of the whole immense homeland, pirated discs, which are very popular among the people because of their low cost, diverge in tons. Licensed software can exist somewhere (for example, in Moscow), but, at a minimum, people do not even understand the difference between a pirate and a license. — , 6- 30- , , , «» . …