Freitag, 2. April 2010

Behavior - Top-down Approach

In order to define a framework that allows us to specify what funcionality exactly a micro behavior should provide, we have to abstract from the tasks, a player has to accomplish. And I don't mean tasks live saving Sandy or getting the rest of those alien bastersd. I mean tasks like moving, dropping converters and activating upgrades.

Or even more abstract: pulling the right triggeer, clicking the left stick, and so on. And that's exactly the way I suggest: use your control scheme to go back to the very roots of what a player has to do! In Squar, you have to...
- Drop converters (LT)
- Fire your tank gun (RT)
- Activate converter upgrades (LB)
- Activate tank upgrades (RB)
- Move (LS)
- Aim (RS)
- Switch between tank gun and base weapon (Click RS)
- Aim with the base gun (RS)
- Fire the base gun (RT)

Considering things this way, we see that we unvoluntarily assumed a certain scheme when we implemented the micro behavior for the energy ray. (Ok that was not our headline when we did it, but I wrote in my last post that we could interpret our hitherto implemented AI that way.)

We integrated movement and firing, for example, in every of the states of our finite automaton:

What we called "building" was actually building-oriented movement with firing as a secondary task (i.e., at targets within line of sight).

What we called "hunting" was enemy oriented-movement with nothing as a secondary task. However, we could have dropped a converter once in a while!

In a first step we identify the questions that we have to answer (these are derived with little effort from the controls list above):



In a second step we reason which of these questions we should integrate in the macro behavior (what should we do?) and which of them belong to the micro behavior (how can we do it?).



Now we get to the meat of the matter: In order to allow for intelligent decisions, we need a lot of information about the environment. Let's introduce some parameters that describe our situation in the game (where for each object we want to have a value for all enemy and ally objects):
- chance that a tank is easily destroyed
- value of a tank
- chance that a tower is destroyed
- value of a tower
- chance that we will be able to build a tower
- value of a potential tower
- chance that we will be able to pick up a power-up before the enemy does
- value of a power up (for us and him)

Note that in the end, all that can happen in a game situation is that we (or the enemy) gain or lose a tower, gain or lose a tank, gain or lose a power-up.
On the other hand we have our current upgrades which we can consider our "bank account". For each situation we have to determine whether we want to save more power-ups or whether we prefer to spend them to enhance our chances to accomplish our present task.

Our next step will be to realize this parameter-guided concept. The very best example (respectively starting point) I can imagine for this purpose is the mighty converter upgrade together with the existence of blocked squares. Will we be able to describe with our paramters, that:

- A potential tower on a blocked square has (on an adequate map) a high importance?
- We should thus save our converter power-ups?
- We should protect our tank well once we have saved several power-ups?

Behavior - Mirco vs. Macro

As we saw in the last video, the AI already behaves somehow reasonable for most of the time. However it is obvious that we can't let our AI behave determinsitc. A determinstic AI is likely to behave "stupid", e.g. our hitherto implemented AI would chase a player forever if he drives around a long wall.

It is a good idea to add some fuzziness to the AI's behavior. Our AI decides to hunt a player down if his health goes below a quarter of maximum. We could instead say that it does only do so in 80% of the time.

Or, to prevent the pitfall from above (and similar cases) let's say that whenever a certain objevtive has been pursued for more than 1 minute without success, try something else. Or every second let there be a chance of 1% to do something else. Or define a curve with the Curve Editor for a more differentiated way to determine the chance to abort your present task.

However before we finally add fuzzines to our behavior let's try and make the behavior as good as possible without.

What will be our next step?

A) One idea would be to implement a bunch of "micro behaviors" that simulate human player tactics. In a team shooter like battlefield or counterstrike, that would be something like hide & snipe, or use a tank to attack.

In Squar, the micro behaviors significantly depend on the currently available power-ups. In fact, we have until now implemented some kind of micro behavior for an enemy that has collected no power-up at all. Once it has collected a tank power-up it could activate the grenades and start destroying enemy towers. To define the micro behavior for using grenades we could consider again a priortiy chain which target to attack first. It makes no sense to attack the enemy tank because we probably won't hit it with grenades. So we could start with converters as primary targets and proceed to towers as secondary targets. It is straightforward to define a routine that let's the AI activate the grenades at once when it picks up a tank power-up and starts firing according to this priorization.

But should we keep building (and collecting) and fire at targets within range only,
or should we give priority to destroying enemy towers? This brings us to the second way of proceeding with the AI implementation.

B) While one could call A the bottom-up approach, we will now consider the top-down approach. Instead of implementing micro-behaviors and determining which to choose when later, we could try and specifiy more abstract guidelines at first.



The advantage of developing the AI bottom-up is that we can think about every plan of action the AI could take before we have to put them together. That way, we may have certain ideas of when it is advantageous to, e.g., activate a certain upgrade and when it is not.

The advantage of developing the AI top-down is that this approach makes it less likely that we have to modify our micro behaviors later when we find out that we should organize things differently (e.g., integrate or separate movement and shooting in a micro behavior).

=> I would suggest to start top-down, especially if its your own game you are developping the AI for, because you should already have quite a good idea of your micro behaviors should look like in this case.
Whenever you feel like you don't get ahead this way, switch to implementation of micro-behaviors, test them and try when it is advantageous to activate which of them. I will henceforth refer to this question by macro behavior.