ai in caveman has been through three major versions.
the first version was just quick and dirty code to get things going. like
all code of this type, it quickly grew and evolved into an ugly mess.
the second version of the ai was a more traditional setstate/runstate
type affair. setstate selected one of about 14 or so AI states for an
entity, depending on what was going on. runstate was a big switch
statement that executed the code for the various states. one problem
with the traditional setstate/runstate model is that it only has one
state variable. so if you have multiple states at once you must have
different states for each combo.
the third and current version of the AI uses a different approach.
it uses prioritized condition checks to determine what to do. as soon as
a condition is found it should react to, it does so, then returns. no
setstate/runstate. as soon as condition is found, the equivalent setstate
is therby determined and the appropriate runstate code can be immediately
it also uses multiple AI state variables (mostly booleans) in lieu of a
single AIstate variable as in setstate/runstate. so it has AI state
variables like in_collsion _recovery, in_collsion_avoidance,
taking_missile_fire, orders (goto, attack, follow, etc.), and so on.
this allows an entity to be in multiple states at once such as:
"in_collision_recovery" while moving to attack due to
"taking_missile_fire" while "following" another entity. when they finish
collision recovery, they resume moving to attack. when done attacking,
they resume following the entity. without the need to push and pop states
on and off a state stack. the condition check priorities cause them to
automatically resume a lower priority state once a higher priority
state is no longer in effect.
the prioritized condition checks work as an expert system.
the condition handlers (code) in turn are each mini expert systems in
handling their condition. implementation varies depending on the condition
being handled. most are rule based systems. some are state machines. the
handlers in turn may call even lower level expert systems for tasks such
as selecting best weapon to use, etc.
all told, the game implements about 18 different types of ai depending on
the entity type and whose side they're on. so for example, AI for a pet
dire wolf is different from that for a wild, subdued, or captured dire wolf.
and AI for a traveling companion caveman is different from that of a neutral,
hostile, thief, hired warrior, or band member caveman.
there are four basic types of AI for animals:
1. defend - the animal will stand its ground and defend itself if approached.
2. maintain_distance - the animal will attempt to maintain a safe distance
from all threats. if approached, it will flee.
3. attack - the animal is predator. when hungry it will go hunting, feeding
on nearby carcasses if available, or attacking other animals not bigger than
itself. when not hungry it just hangs out.
4. defend_location - the animal will defend a specific location in the game
world. used by quests where animals guard treasure. if far from the
location, the animal will move to the location. if at the location, it will
attack all who approach.
Avian AI is completely separate from that for ground animals, although it
takes the same form.
All animals include "graze" as one of their possible AI moves. its usually
the last choice - IE when there's nothing more important to do.
"graze" cycles between stand, wander, flock, and migrate states periodically
at random. its an example of a condition handler that uses a state machine.
wander simply moves to a random wander_to point. flock moves towards the leader
(the first animal of a given type appearing in the entities list). in the case
of the leader, flock becomes stand. migrate is only used by the leader. the
leader moves off in a migrate_direction determined by the type of animal (so
they still migrate the same direction even if the leader is killed). if a
leader is killed, the next active animal of that type becomes the new "leader".
note that leader migration behavior in combo with flock behavior leads to emergent herd migration behavior!
model the little stuff right and the big stuff happens on its own! - well at least sometimes - if you do it right.
multiple AI states vs setstate/runstate is another example of this. by tracking _multiple_ states (which setstate/runstate does not do) - IE by modeling state in greater depth than setstate/runstate - you automatically get emergent push-state, pop-state type behavior with no pushing, popping or state stack required.