I really want to make a decent state machine. I think the proper way to go is modular, eventful and probably recursive . The idea of really flexible state machine is… tantalizing, but unfortunately I still can not see t completely and, truthfully, TankUp will not utilize it fully. I don’t have a lot of possible states and they are, for better or for worse, hierarchical. The best I can get is a fairly bonsaical tree.
The core of my decision making is something like this:
| condition | reaction |
|---|---|
| More than 1 enemy | flee |
| 1 enemy | fight |
| Upgrades and Layers | choose layers |
| Nothing in range | roam |
Of course, this can be (and will be) elaborated upon by adding more precision to the conditions. Also… The best idea I’ve had so far is to add another layer to the behaviour.
All a tank can do is fight another tank, flee the scene, pick upsome asset or wander about, looking for trouble. However, the player is bound to have some more information about the battlefield than the autotanks (he sees further, for example). So I don’t want the player to see two tanks that appear to be in range of each other and immediately know with certainty what they will do. Some variability goes a long way.
Enter stances.
There are three primary stances – aggressive, balanced, evasive. Each autotank has one stance associated at birth. Shove that into the table and you get to that:
| condition | Aggressive reaction | Balanced reaction | Evasive reaction |
|---|---|---|---|
| More than 1 enemy, total size larger than own size | flee | flee | flee |
| More than 1 enemy, total size smaller than own size | fight | flee | flee |
| 1 enemy, larger than self | fight | fight | flee |
| 1 enemy, smaller than self | fight | fight | fight |
| Upgrades and Layers | upgrades | layers | layers |
| No assets in range | roam | roam | roam |
You can see some real behavoiur now. Or a semblance of one, at least.
And if you’ve gone that far, there is one more step, that costs nothing, but adds a lot – two extra stances at each end of the spectrum and a simple mechanism for changing stance.
| condition | Berserk | Aggressive | Balanced | Evasive | Coward |
|---|---|---|---|---|---|
| More than 1 enemy, total size larger than own size | fight | flee | flee | flee | flee |
| More than 1 enemy, total size smaller than own size | fight | fight | flee | flee | flee |
| 1 enemy, larger than self | fight | fight | fight | flee | flee |
| 1 enemy, smaller than self | fight | fight | fight | fight | flee |
| Upgrades and Layers | upgrades | upgrades | layers | layers | layers |
| No assets in range | roam | roam | roam | roam | roam |
Each stance sets two variables – upper and lower threshold for the autotank size (in terms of number of layers). Let’s say for balanced the upper bound is 4, the lower is 2.
For now (cause it’s untested) the lower bound is not taken into account until the autotank has reached it (see “Speed”, “50mph”). So the autotank is created, starting with 1 layer. If it collects another one, the tank gets in it’s own zone (I need a term… ‘native’?). If the tank picks up another 2 layers and gets to 4, he changes the stance to aggressive. If he drops below 2, he becoms a coward. Those stances dictate the reaction to his surroundings.
Important note about the tanks upbringing:
Let’s take an aggressive tank for example. The bounds are, let’s say, 6 and 3. So if an aggresive tank drops below 3 layers, he becomes balanced. However, the tank that was born balanced needs to drop below 4 to transition from aggresive to balanced. So the native stance matters. That should keep things interesting.
And of course, there is no upbound transition for the berserk, just as there is no downwards transition for the coward.
