RTS AI

I want to do computer AI for an RTS game.

This game will have a human vs. computer mode only, e.g. skirmish mode.

I know little or nothing about how to do this. What’s the best approach?

I may not be looking for most perfect solution, but rather something that’s simple enough and is challenging. My thoughts lean towards creating some sort of a AIController, which periodically checks the state of the game, and then puts some set of plans into motion.

I’m rather enjoying the emergent behaviour that arises just from letting all the little gidrahs do their own thing.

Cas :slight_smile:

Well, they don’t have to collect resources, build a base, protect a base, attack the enemy, defend resources, etc.

I’ve had a go a this problem before, you might want to try an AI Controller which works using influence maps to make decisions.

Start from scratch, outside of your existing game. Start small: one building, two types of units (resource gatherers + armored units) on a tiny grid map, say 10x10 cells. Draw the cells using lines, draw the buildings as rectangles, draw the units as circles. One unit or building per cell. No animations. This way you don’t get lost in feature creep.

Work out the mechanics, as kapta said, use influence maps (draw them as overlays), and make the AI reasonably smart within these restrictions. Then, when it works, add a building type, or a unit type, or expand the map, and see how that works out. Tune it, and take the next step, until ‘strategies’ emerge.

Don’t waste time on neural networks or other highlevel / abstract algorithms (use floodfill, not even A*, if you don’t have it already). Do as much as possible bruteforce, optimize once it works, not while you’re building it. Keep the code simple (preferably messy, code-blobs are fine) as you’re going to refactor it all the time anyway. Slowly you can refactor ‘behavior’ into classes using simple finite state machines. Keep everything as simple as possible. It will lack advanced behavior, but that’s not in the scope of your project anyway.

Once you have built a tiny minigame that is hard to beat, integrate it into your existing game.

Thanks, influence maps seems to be a good start. I’ll look into this.

Ok, how about unit AI?

I’ve been thinking about using a stack of states. Here’s my description of the idea (which I posted on the forum of the rts game project):

[quote]I’ve been thinking about tackling the unit behavior AI.

This is something I’ve never really done before. What I am thinking about is using a stack containing the states (state=the ai logic) the unit could be doing.

A collector could have a stack of (topmost is what the collector is doing right now):
Code:

DeployOnProtostar
WaitForOrders
AutomaticallyCollectNearestProtomatter
WaitForOrders
AutomaticallyDeployOnNearestAvailableProtostar
Reset

This could be a stack of a collector that the player has ordered to deploy on a certain protostar. The DeployOnProtostar AI state makes the collector move to a clicked on protostar and deploy there. It also contains logic to check if some other unit has deployed there first, and if so, that state is popped off the stack and WaitForOrders state is activated.

Once the collector has waited 1 minute without any human interference, it will pop the WaitForOrders state and activate the AutomaticallyCollectNearestProtomatter state.

Once it cannot find any nearby protomatter (all been collected), it will go into yet another WaitForOrders state.

Once that’s done, it will execute the AutomaticallyDeployOnNearestAvailableProtostar state. This will try to find nearby available protostar, and deploy on it. If it can’t find anything, it will go to the bottommost state.

The bottommost state is the fail-safe state and is never removed. It will reset the stack with a certain set of states (e.g. AutomaticallyCollectNearestProtomatter, WaitForOrders, AutomaticallyDeployOnNearestAvailableProtostar). In effect, it will go into a loop.

Makes sense?
[/quote]

I think you should read up on Behaviour trees. You’re describing a crude, hardcoded behaviour tree there really, and you’d probably find it easier to do it ‘properly’.

ty.

I’m wondering about those sequences, and selectors. The article(s) is not very clear on how it all fits together. How do sequences and selectors work together? What resides within each “behavior” node?

Too high level, not enough “this is how it all fits together and how you do it” details.

I guess a behavior tree can be more than two levels?

What about units that can be given commands by humans or a computer controller? (E.g. in a RTS game). How do commands like “move to this location” and “attack this target” fit into this?

There’s a ton of information about them on the website, but since the redesign it’s become harder to find it. :frowning:

IIRC this is a good introduction and overview: http://aigamedev.com/insider/presentations/behavior-trees/

‘Sequences’ are nodes which execute all of their child nodes in sequence. This is for when you want one thing to happen after another. ‘Selectors’ choose to execute one of their child nodes based on some condition (which might be random, or based on priority, or based on some gameplay logic).

[quote]I guess a behavior tree can be more than two levels?
[/quote]
It wouldn’t be much of a tree otherwise. :slight_smile:

[quote]What about units that can be given commands by humans or a computer controller? (E.g. in a RTS game). How do commands like “move to this location” and “attack this target” fit into this?
[/quote]
That’s probably be done with a top-level selector, where it choses to do the ‘queued human command’ subnode if there’s a queued command, or selects the ‘idle behaviour’ subnode if there’s nothing pending.

Great, thanks Orangy :smiley:

An example might be clearer, so here’s how I’d do you ‘collector’ behaviour tree (I assume some kind of resource harvester that collects protomatter and deploys it to a protostar?).

Numbered for talky referencing.

1 PrioritySelector
-2 QueuedHumanOrder Node
–3 GoTo action
-4 PrioritySelector
–5 Flee node (enabled when attacked, disabled after cool-down time)
----6 GoToNearestBase
–7 Unload node (enables self when full, disabled otherwise)
—8 LinearSequence
----9 GoToNearestProtoStar
----10 WaitForProtostarFree
----11 DeployOnProtostar
–12 Harvest node (disabled when full)
—13 LinearSequence
----14 GoToNearestProtomatter
----15 Harvest
–16 Idle

Not perfect, and not the only way to do it, but it should give you the idea.

The ‘priority selector’ node would execute the highest enabled child node, so ‘1’ would select between the human action if present, or the default harvest behaviour. Similarly 4 chooses the flee, unload or harvest states depending on the unit state.

‘linear sequence’ performs all the actions in turn, so 8 defines the unload behaviour as ‘wait for free’ followed by ‘unload’.

You can see there’s a fair amount of harvester specific nodes, because the harvester has very specific actions. But similarly there’s some very generic nodes (PrioritySelector, LinearSequence, Idle) which would be useable everywhere, and some generic gameplay nodes which would be useful (and easy) to reuse in other units (GoTo, Flee, QueuedHumanOrder, GoToNearestBase).

Yup, nice design, I like it. I watched the video, understood most of it, but probably need to watch it again to grasp all of it. Probably don’t need any of that concurrency? :slight_smile:

In any case, this really warrants a special test project for a few weeks to get the hang of it.

How do you deal with this “blackboard”?

Do you have one? What is it? How do you use it? How do you implement it?

I realize it’s used for sending “events of change” to the unit, which then reacts to the change. But, I feel like that is a bit overhead to do, sending event notification every time a unit moves from x,y to x2,y2. I do have access to all the gameobjects in the world, why would I need a blackboard? What events should a blackboard receive?

I use blackboards a lot. Primarily so that other units don’t do the “same thing”. However they are api specialized to the data i want on them for performance reasons.

Each unit in my RTS has a blackboard, even enemy units. Say a red team tank starts to shoot at a blue unit, it would put on the black board of the blue unit that its going to attack it in about x seconds with expected y damage. If another red unit is looking for a target and then picks the same blue unit. It checks the blackboard to see if enough damage is going to be done in a particular time. If so it picks a different target.

This avoids the common problem in RTS games where all units just shoot at the closest thing… which is perhaps a zergling, rather than the hydralisks that are doing all the damage…

I think layered blackboards would be a good idea:

blackboard per unit
blackboard per group
blackboard per side
blackboard per game

Each blackboard would hold information for that specific set of units, so that you can have both fine grained and high level knowledge without ending up with spaghetti.

Haha I’ve got exactly the problem of my turrets all shooting at the nearest targets :slight_smile: I’m trying to hack around it though rather than trying anything clever like blackboards.

Cas :slight_smile:

In my game I have a targeter component for each unit. The weapons on the unit rely on that component to get a target to shoot at.
It has several implementations, e.g. PriorityTargeter, which finds the most dangerous target, NearestTargeter, which simply finds the nearest target to shoot at.
There could other implementations, such as TargetTheMostDamagedEnemyFirstTargeter, or RandomlyFindNewTargetAtCertainIntervalTargeter, or perhaps you have a type of tower that works very well against certain type of units, so you could have the targeter to try to find those matches first.

I’m still not sure about the benefit of blackboards.

I think the key thing here is that your “targeter” component can’t handle the case delt0r outlined. You would need to look at all other units, see if they are targetting the unit you are considering, see if lethal damage is already going to be dealt, etc. It seems like a blackboard handles this succinctly and efficiently.

Another example might be a stun turret that has a 2 second ramp up time before it shoots. You wouldn’t want two stun turrets to fire on the same target.