# SS13 Mob AI Overhaul
###### tags: `Ideas Guy` `Development` `Design`
## Key Goals
To provide performant, intelligent AI to SS13, such that players are actually significantly challenged by organized groups of NPCs.
## Concepts
- Flocking Behavior
- "Trend towards center of herd"
- Group moves in concert, does single pathing as a group with basic cellular behaviors for local collision avoidance.
- Center isn't necessarily on a mob, more the directed center of the group
- Shared state about targeting
- Raycasting algo based off of the atom density field around the flock
- Shares pathfinding knowledge by using each individual mob as an outer edge in the pathfinding algo for other mobs.
- Mobs share their optimal path to target
- Splitting/Flanking behaviors for "intelligent" flocks
- "Crowded" paths are treated as high-cost movement, will repath around targets if possible.
- Chokepoint exploitation
- instead of filing into the fatal funnel to be killed, can call mob specific behaivors based on flock capabilities
- Individuals providing capabilities to the flock like demolitions/breaching/anti-personnel/anti-mech attacks as options.
- Checks to determine when the behavior should be used are provided by the capabilities, but the flock AI chooses when to actually execute the order.
- Leader unit that, when killed, disorganizes the flock temporarily until a re-election is performed.
## Algorithm Details
Psuedocode in some places like yield
Note: Not necessarily needed to be implemented in DM, great candidate for C++/Rust implementation.
```
#define FLOCK_BEHAVIOR_STARTING 0x1
#define FLOCK_BEHAVIOR_RUNNING 0x2
#define FLOCK_BEHAVIOR_COMPLETE 0x3
/datum/flock_behavior
var/behavior_state = 0x0
/datum/flock_behavior/bind(/datum/flock_controller/flock)
flock.set_active_behavior(src)
/datum/flock_behavior/pathfind_behavior/Initialize(/turf/origin, /turf/dest)
/datum/flock_behavior/pathfind_behavior/bind(/datum/flock_controller/flock)
/datum/flock_decision_tree/Initialize()
/datum/flock_decision_tree/basic/Initialize()
/datum/flock_decision_tree/basic/step(flock)
if (flock.has_target() && flock.aggresive_state() && !flock.not_engaged())
var/datum/flock_behavior/pathfind_behavior/P = flock.get_pathfind_from_cache(
astar.path(WEAKREF(flock.center), WEAKREF(flock.target.loc))
)
if (P.behavior_state & FLOCK_BEHAVIOR_COMPLETE)
var/datum/flock_behavior/engage_behavior/E = flock.engage_target()
return E.bind(flock)
if (P.behavior_state & FLOCK_BEHAVIOR_RUNNING)
return P.step(flock)
else
return P.bind(flock)
else if (flock.aggressive_state())
var/datum/flock_behavior/seek_behavior/S = flock.seek_target()
return S.bind(flock)
else
var/datum/flock_behavior/idle_behavior/B = flock.select_idle_behavior()
return B.bind(flock)
/datum/flock_controller
var/state = 0x0
/datum/flock_controller/Initialize(decision_tree, list_of_mobs)
for var/m in list_of_mobs
m.set_flock(src)
src.elect_leader()
/datum/flock_controller/get_pathfind_from_cache(/turf/origin, /turf/dest)
var/hash = loc_merge_hash(origin, dest)
if (src.pathfind_cache[hash] != NULL)
return src.pathfind_cache[hash]
else
return new /datum/flock_behavior/pathfind_behavior(origin, dest)