---
# System prepended metadata

title: SS13 Mob AI Overhaul
tags: [Design, Development, Ideas Guy]

---

# 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)