Skip to content

Commit

Permalink
[MIRROR] Integration (and tweaks) for Polaris AI Framework
Browse files Browse the repository at this point in the history
  • Loading branch information
wb13 authored and SuhEugene committed Oct 17, 2023
1 parent 9930c7c commit 9e18f38
Show file tree
Hide file tree
Showing 36 changed files with 688 additions and 492 deletions.
6 changes: 4 additions & 2 deletions baystation12.dme
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "code\__defines\_excom.dm"
#include "code\__defines\_renderer.dm"
#include "code\__defines\admin.dm"
#include "code\__defines\ai.dm"
#include "code\__defines\antagonists.dm"
#include "code\__defines\ao.dm"
#include "code\__defines\ao_misc.dm"
Expand Down Expand Up @@ -1424,7 +1425,6 @@
#include "code\modules\admin\view_variables\view_variables.dm"
#include "code\modules\admin\view_variables\view_variables_global.dm"
#include "code\modules\admin\view_variables\vv_set_handlers.dm"
#include "code\modules\ai\_defines.dm"
#include "code\modules\ai\ai_holder.dm"
#include "code\modules\ai\ai_holder_combat.dm"
#include "code\modules\ai\ai_holder_combat_unseen.dm"
Expand All @@ -1439,7 +1439,9 @@
#include "code\modules\ai\ai_holder_targeting.dm"
#include "code\modules\ai\interfaces.dm"
#include "code\modules\ai\say_list.dm"
#include "code\modules\ai\aI_holder_subtypes\simple_mob_ai.dm"
#include "code\modules\ai\ai_holder_subtypes\alien_ai.dm"
#include "code\modules\ai\ai_holder_subtypes\human_ai.dm"
#include "code\modules\ai\ai_holder_subtypes\simple_mob_ai.dm"
#include "code\modules\alarm\alarm.dm"
#include "code\modules\alarm\alarm_handler.dm"
#include "code\modules\alarm\atmosphere_alarm.dm"
Expand Down
20 changes: 19 additions & 1 deletion code/modules/ai/_defines.dm → code/__defines/ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#define MOVEMENT_FAILED 0 // Move() returned false for whatever reason and the mob didn't move.
#define MOVEMENT_SUCCESSFUL 1 // Move() returned true and the mob hopefully moved.

// Results of pre-attack checks
// Results of pre-attack checks.
#define ATTACK_ON_COOLDOWN -1 // Recently attacked and needs to try again soon.
#define ATTACK_FAILED 0 // Something else went wrong! Maybe they moved away!
#define ATTACK_SUCCESSFUL 1 // We attacked (or tried to, misses count too)
Expand All @@ -32,3 +32,21 @@
#define AI_TARGET_ALLY 3 // They are an ally. Find a new target.
#define AI_TARGET_DEAD 4 // They're dead. Find a new target.
#define AI_TARGET_INVINCIBLE 5 // Target is currently unable to receive damage for whatever reason. Find a new target or wait.

// Stances to determine AI state.
#define STANCE_SLEEP 0 // Doing (almost) nothing, to save on CPU because nobody is around to notice or the mob died.
#define STANCE_IDLE 1 // The more or less default state. Wanders around, looks for baddies, and spouts one-liners.
#define STANCE_ALERT 2 // A baddie is visible but not too close, and essentially we tell them to go away or die.
#define STANCE_APPROACH 3 // Attempting to get into range to attack them.
#define STANCE_FIGHT 4 // Actually fighting, with melee or ranged.
#define STANCE_BLINDFIGHT 5 // Fighting something that cannot be seen by the mob, from invisibility or out of sight.
#define STANCE_REPOSITION 6 // Relocating to a better position while in combat. Also used when moving away from a danger like grenades.
#define STANCE_MOVE 7 // Similar to above but for out of combat. If a baddie is seen, they'll cancel and fight them.
#define STANCE_FOLLOW 8 // Following somone, without trying to murder them.
#define STANCE_FLEE 9 // Run away from the target because they're too spooky/we're dying/some other reason.
#define STANCE_DISABLED 10 // Used when the holder is afflicted with certain status effects, such as stuns or confusion.

#define STANCE_ATTACK 11 // Backwards compatability
#define STANCE_ATTACKING 12 // Ditto

#define STANCES_COMBAT list(STANCE_ALERT, STANCE_APPROACH, STANCE_FIGHT, STANCE_BLINDFIGHT, STANCE_REPOSITION)
18 changes: 0 additions & 18 deletions code/__defines/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,6 @@
#define BORGXRAY FLAG(2)
#define BORGMATERIAL FLAG(3)


#define STANCE_SLEEP 0 // Doing (almost) nothing, to save on CPU because nobody is around to notice or the mob died.
#define STANCE_IDLE 1 // The more or less default state. Wanders around, looks for baddies, and spouts one-liners.
#define STANCE_ALERT 2 // A baddie is visible but not too close, and essentially we tell them to go away or die.
#define STANCE_APPROACH 3 // Attempting to get into range to attack them.
#define STANCE_FIGHT 4 // Actually fighting, with melee or ranged.
#define STANCE_BLINDFIGHT 5 // Fighting something that cannot be seen by the mob, from invisibility or out of sight.
#define STANCE_REPOSITION 6 // Relocating to a better position while in combat. Also used when moving away from a danger like grenades.
#define STANCE_MOVE 7 // Similar to above but for out of combat. If a baddie is seen, they'll cancel and fight them.
#define STANCE_FOLLOW 8 // Following somone, without trying to murder them.
#define STANCE_FLEE 9 // Run away from the target because they're too spooky/we're dying/some other reason.
#define STANCE_DISABLED 10 // Used when the holder is afflicted with certain status effects, such as stuns or confusion.

#define STANCE_ATTACK 11 // Backwards compatability
#define STANCE_ATTACKING 12 // Ditto

#define STANCES_COMBAT list(STANCE_ALERT, STANCE_APPROACH, STANCE_FIGHT, STANCE_BLINDFIGHT, STANCE_REPOSITION)

#define LEFT FLAG(0)
#define RIGHT FLAG(1)
#define UNDER FLAG(2)
Expand Down
2 changes: 1 addition & 1 deletion code/__defines/subsystem-priority.dm
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define SS_PRIORITY_LIGHTING 50 // Queued lighting engine updates.
#define SS_PRIORITY_SPACEDRIFT 45 // Drifting things
#define SS_PRIORITY_CHAT 40 // Chat
#define SS_PRIORITY_AI 25 // Mob AI
#define SS_PRIORITY_ALARM 20 // Alarm processing.
#define SS_PRIORITY_EVENT 20 // Event processing and queue handling.
#define SS_PRIORITY_SHUTTLE 20 // Shuttle movement.
Expand All @@ -31,7 +32,6 @@
#define SS_PRIORITY_RADIATION 20 // Radiation processing and cache updates.
#define SS_PRIORITY_OPEN_SPACE 20 // Open turf updates.
#define SS_PRIORITY_AIRFLOW 15 // Object movement from ZAS airflow.
#define SS_PRIORITY_AI 15 // Mob AI
#define SS_PRIORITY_PRESENCE 10 // z-level player presence testing
#define SS_PRIORITY_VOTE 10 // Vote management.
#define SS_PRIORITY_SUPPLY 10 // Supply point accumulation.
Expand Down
2 changes: 1 addition & 1 deletion code/controllers/subsystems/aifast.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ SUBSYSTEM_DEF(aifast)
name = "AI (Fast)"
init_order = SS_INIT_AIFAST
priority = SS_PRIORITY_AI
wait = 0.25 SECONDS
wait = 0.5 SECONDS
var/static/list/datum/ai_holder/ai_holders = list()
var/static/list/datum/ai_holder/queue = list()

Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/portable_turret.dm
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ var/global/list/turret_icons
if(get_dist(src, L) > 7) //if it's too far away, why bother?
return TURRET_NOT_TARGET

if(!check_trajectory(L, src)) //check if we have true line of sight
if(check_trajectory(L, src) != L) //check if we have true line of sight
return TURRET_NOT_TARGET

if(emagged) // If emagged not even the dead get a rest
Expand Down
2 changes: 1 addition & 1 deletion code/modules/ai/__readme.dm
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ avoid infinite loops (I.E. Stance A switches to Stance B, which then
switches to Stance A, and so on...), and the delay is very short so
it should not be an issue.
See code/__defines/mob.dm for a list of stance defines, and descriptions
See code/__defines/ai.dm for a list of stance defines, and descriptions
about their purpose. Generally, each stance has its own file in the AI
module folder and are mostly self contained, however some files instead
deal with general things that other stances may require, such as targeting
Expand Down
85 changes: 60 additions & 25 deletions code/modules/ai/ai_holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ if (!(datum.process_flags & AI_FASTPROCESSING)) { \

/datum/ai_holder
/// The mob this datum is going to control.
var/mob/living/simple_animal/holder = null
var/mob/living/holder = null
/// The required mob type of the holder.
var/holder_required_type = /mob/living
/// Determines if the mob should be doing a specific thing, e.g. attacking, following, standing around, etc.
var/stance = STANCE_IDLE
/// Adjust to make the AI be intentionally dumber, or make it more robust (e.g. dodging grenades).
Expand All @@ -86,7 +88,6 @@ if (!(datum.process_flags & AI_FASTPROCESSING)) { \
STANCE_MOVE,
STANCE_FOLLOW,
STANCE_FLEE,
STANCE_DISABLED
)
var/static/list/noprocess_stances = list(
STANCE_SLEEP
Expand All @@ -104,8 +105,18 @@ if (!(datum.process_flags & AI_FASTPROCESSING)) { \
ASSERT(new_holder)
holder = new_holder
home_turf = get_turf(holder)

if (!istype(new_holder, holder_required_type))
var/mob/new_holder_mob = new_holder
src.debug_ai = AI_LOG_ERROR
ai_log("New(): Invalid holder type, destroying AI. (Expected: [holder_required_type] Received: [new_holder_mob.type])", AI_LOG_ERROR)
QDEL_NULL(src)
return
manage_processing(AI_PROCESSING)
GLOB.stat_set_event.register(holder, src, .proc/holder_stat_change)

if (cooperative)
build_faction_friends()
..()

/datum/ai_holder/Destroy()
Expand Down Expand Up @@ -179,14 +190,16 @@ if (!(datum.process_flags & AI_FASTPROCESSING)) { \
/datum/ai_holder/proc/handle_tactics()
if (holder.key && !autopilot)
return
handle_special_tactic()
if (!is_disabled())
handle_special_tactic()
handle_stance_tactical()

/// 'Strategical' processes that are more expensive on the CPU and so don't get run as often as the above proc, such as A* pathfinding or robust targeting.
/datum/ai_holder/proc/handle_strategicals()
if (holder.key && !autopilot)
return
handle_special_strategical()
if (!is_disabled())
handle_special_strategical()
handle_stance_strategical()

/// Override this for special things without polluting the main `handle_tactics()` loop.
Expand Down Expand Up @@ -219,21 +232,21 @@ if (!(datum.process_flags & AI_FASTPROCESSING)) { \
/// This is called every half a second.
/datum/ai_holder/proc/handle_stance_tactical()
ai_log("========= Fast Process Beginning ==========", AI_LOG_TRACE) // This is to make it easier visually to disinguish between 'blocks' of what a tick did.
ai_log("handle_stance_tactical() : Called.", AI_LOG_TRACE)
ai_log("handle_stance_tactical() : Entering.", AI_LOG_TRACE)

if (stance == STANCE_SLEEP)
ai_log("handle_stance_tactical() : Going to sleep.", AI_LOG_TRACE)
go_sleep()
return

if (target && can_see_target(target))
track_target_position()

if (stance != STANCE_DISABLED && is_disabled()) // Stunned/confused/etc
ai_log("handle_stance_tactical() : Disabled.", AI_LOG_TRACE)
set_stance(STANCE_DISABLED)
return

if (target && can_see_target(target))
track_target_position()

if (stance in STANCES_COMBAT)
// Should resist? We check this before fleeing so that we can actually flee and not be trapped in a chair.
if (holder.incapacitated(INCAPACITATION_BUCKLED_PARTIALLY))
Expand Down Expand Up @@ -271,10 +284,9 @@ if (!(datum.process_flags & AI_FASTPROCESSING)) { \
ai_log("handle_stance_tactical() : STANCE_MOVE, going to walk_to_destination().", AI_LOG_TRACE)
walk_to_destination()

if (STANCE_REPOSITION) // This is the same as above but doesn't stop if an enemy is visible since its an 'in-combat' move order.
if (STANCE_REPOSITION) // This is the same as above but stops if an enemy is visible since its an 'in-combat' move order.
ai_log("handle_stance_tactical() : STANCE_REPOSITION, going to walk_to_destination().", AI_LOG_TRACE)
if (!target && !find_target())
walk_to_destination()
walk_to_destination()

if (STANCE_FOLLOW)
ai_log("handle_stance_tactical() : STANCE_FOLLOW, going to walk_to_leader().", AI_LOG_TRACE)
Expand All @@ -284,63 +296,78 @@ if (!(datum.process_flags & AI_FASTPROCESSING)) { \
ai_log("handle_stance_tactical() : STANCE_FLEE, going to flee_from_target().", AI_LOG_TRACE)
flee_from_target()

if (STANCE_DISABLED)
ai_log("handle_stance_tactical() : STANCE_DISABLED.", AI_LOG_TRACE)
if (!is_disabled())
ai_log("handle_stance_tactical() : No longer disabled.", AI_LOG_TRACE)
set_stance(STANCE_IDLE)
else
handle_disabled()

ai_log("handle_stance_tactical() : Exiting.", AI_LOG_TRACE)
ai_log("========= Fast Process Ending ==========", AI_LOG_TRACE)

/// This is called every two seconds.
/datum/ai_holder/proc/handle_stance_strategical()
ai_log("++++++++++ Slow Process Beginning ++++++++++", AI_LOG_TRACE)
ai_log("handle_stance_strategical() : Called.", AI_LOG_TRACE)
ai_log("handle_stance_strategical() : Entering.", AI_LOG_TRACE)

//We got left around for some reason. Goodbye cruel world.
if (!holder)
qdel(src)

if (stance == STANCE_SLEEP)
ai_log("handle_stance_tactical() : Going to sleep. Exiting.", AI_LOG_TRACE)
go_sleep()
return

if (stance != STANCE_DISABLED && is_disabled()) // Stunned/confused/etc
ai_log("handle_stance_tactical() : Disabled. Exiting.", AI_LOG_TRACE)
set_stance(STANCE_DISABLED)
return

ai_log("handle_stance_strategical() : LTT=[lose_target_time]", AI_LOG_TRACE)
if (lose_target_time && (lose_target_time + lose_target_timeout < world.time)) // We were tracking an enemy but they are gone.
ai_log("handle_stance_strategical() : Giving up a chase.", AI_LOG_DEBUG)
remove_target()

if (stance in STANCES_COMBAT)
request_help() // Call our allies.
if (target && hostile && !can_pursue(target))
ai_log("handle_stance_stragical() : Target no longer valid, dropping.", AI_LOG_TRACE)
remove_target()

switch(stance)
if (STANCE_IDLE)
if (speak_chance) // In the long loop since otherwise it wont shut up.
if (target)
ai_log("handle_stance_strategical() : STANCE_IDLE, target still present. Getting ready to fight.", AI_LOG_TRACE)
set_stance(STANCE_FIGHT);

if (prob(speak_chance)) // In the long loop since otherwise it wont shut up.
handle_idle_speaking()

if (hostile)
ai_log("handle_stance_strategical() : STANCE_IDLE, going to find_target().", AI_LOG_TRACE)
find_target()

if (should_go_home())
ai_log("handle_stance_tactical() : STANCE_IDLE, going to go home.", AI_LOG_TRACE)
ai_log("handle_stance_strategical() : STANCE_IDLE, going to go home.", AI_LOG_TRACE)
go_home()

else if (should_follow_leader())
ai_log("handle_stance_tactical() : STANCE_IDLE, going to follow leader.", AI_LOG_TRACE)
ai_log("handle_stance_strategical() : STANCE_IDLE, going to follow leader.", AI_LOG_TRACE)
set_stance(STANCE_FOLLOW)

else if (should_wander())
ai_log("handle_stance_tactical() : STANCE_IDLE, going to wander randomly.", AI_LOG_TRACE)
ai_log("handle_stance_strategical() : STANCE_IDLE, going to wander randomly.", AI_LOG_TRACE)
handle_wander_movement()

if (STANCE_APPROACH)
if (target)
if (hostile && find_target()) // In case another target is closer.
ai_log("handle_stance_strategical() : STANCE_APPROACH, going to calculate_path([target]).", AI_LOG_TRACE)
calculate_path(target)
walk_to_target()

if (STANCE_MOVE)
if (hostile && find_target()) // This will switch its stance.
ai_log("handle_stance_strategical() : STANCE_MOVE, found target and was inturrupted.", AI_LOG_TRACE)

if (STANCE_REPOSITION)
if (hostile && find_target())
ai_log("handle_stance_strategical() : STANCE_REPOSITION, found target and was inturrupted.", AI_LOG_TRACE)

if (STANCE_FOLLOW)
if (hostile && find_target()) // This will switch its stance.
ai_log("handle_stance_strategical() : STANCE_FOLLOW, found target and was inturrupted.", AI_LOG_TRACE)
Expand All @@ -349,6 +376,14 @@ if (!(datum.process_flags & AI_FASTPROCESSING)) { \
calculate_path(leader)
walk_to_leader()

if (STANCE_DISABLED)
ai_log("handle_stance_tactical() : STANCE_DISABLED.", AI_LOG_TRACE)
if (!is_disabled())
ai_log("handle_stance_tactical() : No longer disabled.", AI_LOG_TRACE)
set_stance(STANCE_IDLE)
else
handle_disabled()

ai_log("handle_stance_strategical() : Exiting.", AI_LOG_TRACE)
ai_log("++++++++++ Slow Process Ending ++++++++++", AI_LOG_TRACE)

Expand Down
Loading

0 comments on commit 9e18f38

Please sign in to comment.