From c82c18769f8c5e17da932dbf7e00e8dfc7948173 Mon Sep 17 00:00:00 2001 From: spookerton Date: Thu, 7 Apr 2022 19:36:55 +0100 Subject: [PATCH] improved fire loop behavior of SSai & SSaifast --- code/__defines/ai.dm | 9 ++++ code/controllers/subsystems/ai.dm | 57 ++++++++++++++++++-------- code/controllers/subsystems/aifast.dm | 59 ++++++++++++++++++--------- code/modules/ai/ai_holder.dm | 8 ---- polaris.dme | 1 + 5 files changed, 89 insertions(+), 45 deletions(-) create mode 100644 code/__defines/ai.dm diff --git a/code/__defines/ai.dm b/code/__defines/ai.dm new file mode 100644 index 0000000000..2f7d9db3a0 --- /dev/null +++ b/code/__defines/ai.dm @@ -0,0 +1,9 @@ + +/// Used in ai/manage_processing to indicate that the AI should be dequeued from slow and fast AI processing +#define AI_NO_PROCESS 0 + +/// Used in ai/manage_processing to indicate that the AI should be queued for slow AI processing, and for related subsystem checks +#define AI_PROCESSING (1 << 0) + +/// Used in ai/manage_processing to indicate that the AI should be queued for fast AI processing, and for related subsystem checks +#define AI_FASTPROCESSING (1 << 1) diff --git a/code/controllers/subsystems/ai.dm b/code/controllers/subsystems/ai.dm index 57bd5cc1ac..46b078cde9 100644 --- a/code/controllers/subsystems/ai.dm +++ b/code/controllers/subsystems/ai.dm @@ -1,32 +1,53 @@ SUBSYSTEM_DEF(ai) name = "AI" - init_order = INIT_ORDER_AI - priority = FIRE_PRIORITY_AI - wait = 2 SECONDS flags = SS_NO_INIT runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + priority = FIRE_PRIORITY_AI + wait = 2 SECONDS + + /// The list of AI datums to be processed. + var/static/tmp/list/queue = list() + + /// The list of AI datums currently being processed. + var/static/tmp/list/current = list() - var/list/processing = list() - var/list/currentrun = list() /datum/controller/subsystem/ai/stat_entry(msg_prefix) var/list/msg = list(msg_prefix) - msg += "P:[processing.len]" + msg += "P:[queue.len]" ..(msg.Join()) + +/datum/controller/subsystem/ai/Recover() + current.Cut() + + /datum/controller/subsystem/ai/fire(resumed, no_mc_tick) if (!resumed) - src.currentrun = processing.Copy() - - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - - while(currentrun.len) - var/datum/ai_holder/A = currentrun[currentrun.len] - --currentrun.len - if(!A || QDELETED(A) || A.busy) // Doesn't exist or won't exist soon or not doing it this tick + current = queue.Copy() + var/datum/ai_holder/subject + for (var/i = current.len to 1 step -1) + subject = current[i] + if (QDELETED(subject) || subject.busy) continue - A.handle_strategicals() - - if(MC_TICK_CHECK) + subject.handle_strategicals() + if (no_mc_tick) + CHECK_TICK + else if (MC_TICK_CHECK) + current.Cut(i) return + current.Cut() + + +/// Convenience define for safely enqueueing an AI datum for slow processing. +#define START_AIPROCESSING(DATUM) \ +if (!(DATUM.process_flags & AI_PROCESSING)) {\ + DATUM.process_flags |= AI_PROCESSING;\ + SSai.queue += DATUM;\ +} + + +/// Convenience define for safely dequeueing an AI datum from slow processing. +#define STOP_AIPROCESSING(DATUM) \ +DATUM.process_flags &= ~AI_PROCESSING; \ +SSai.queue -= DATUM; diff --git a/code/controllers/subsystems/aifast.dm b/code/controllers/subsystems/aifast.dm index 6ce841855d..d4a70a3853 100644 --- a/code/controllers/subsystems/aifast.dm +++ b/code/controllers/subsystems/aifast.dm @@ -1,32 +1,53 @@ SUBSYSTEM_DEF(aifast) - name = "AI (Fast)" - init_order = INIT_ORDER_AI_FAST - priority = FIRE_PRIORITY_AI - wait = 0.25 SECONDS + name = "AI Fast" flags = SS_NO_INIT runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + priority = FIRE_PRIORITY_AI + wait = 0.25 SECONDS + + /// The list of AI datums to be processed. + var/static/tmp/list/queue = list() + + /// The list of AI datums currently being processed. + var/static/tmp/list/current = list() - var/list/processing = list() - var/list/currentrun = list() /datum/controller/subsystem/aifast/stat_entry(msg_prefix) var/list/msg = list(msg_prefix) - msg += "P:[processing.len]" + msg += "P:[queue.len]" ..(msg.Join()) + +/datum/controller/subsystem/aifast/Recover() + current.Cut() + + /datum/controller/subsystem/aifast/fire(resumed, no_mc_tick) if (!resumed) - src.currentrun = processing.Copy() - - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - - while(currentrun.len) - var/datum/ai_holder/A = currentrun[currentrun.len] - --currentrun.len - if(!A || QDELETED(A) || A.busy) // Doesn't exist or won't exist soon or not doing it this tick + current = queue.Copy() + var/datum/ai_holder/subject + for (var/i = current.len to 1 step -1) + subject = current[i] + if (QDELETED(subject) || subject.busy) continue - A.handle_tactics() - - if(MC_TICK_CHECK) + subject.handle_tactics() + if (no_mc_tick) + CHECK_TICK + else if (MC_TICK_CHECK) + current.Cut(i) return + current.Cut() + + +/// Convenience define for safely enqueueing an AI datum for fast processing. +#define START_AIFASTPROCESSING(DATUM) \ +if (!(DATUM.process_flags & AI_FASTPROCESSING)) {\ + DATUM.process_flags |= AI_FASTPROCESSING;\ + SSaifast.queue += DATUM;\ +} + + +/// Convenience define for safely dequeueing an AI datum from fast processing. +#define STOP_AIFASTPROCESSING(DATUM) \ +DATUM.process_flags &= ~AI_FASTPROCESSING; \ +SSaifast.queue -= DATUM; diff --git a/code/modules/ai/ai_holder.dm b/code/modules/ai/ai_holder.dm index 21d9cd8588..a285225286 100644 --- a/code/modules/ai/ai_holder.dm +++ b/code/modules/ai/ai_holder.dm @@ -1,14 +1,6 @@ // This is a datum-based artificial intelligence for simple mobs (and possibly others) to use. // The neat thing with having this here instead of on the mob is that it is independant of Life(), and that different mobs // can use a more or less complex AI by giving it a different datum. -#define AI_NO_PROCESS 0 -#define AI_PROCESSING (1<<0) -#define AI_FASTPROCESSING (1<<1) - -#define START_AIPROCESSING(Datum) if (!(Datum.process_flags & AI_PROCESSING)) {Datum.process_flags |= AI_PROCESSING;SSai.processing += Datum} -#define STOP_AIPROCESSING(Datum) Datum.process_flags &= ~AI_PROCESSING;SSai.processing -= Datum -#define START_AIFASTPROCESSING(Datum) if (!(Datum.process_flags & AI_FASTPROCESSING)) {Datum.process_flags |= AI_FASTPROCESSING;SSaifast.processing += Datum} -#define STOP_AIFASTPROCESSING(Datum) Datum.process_flags &= ~AI_FASTPROCESSING;SSaifast.processing -= Datum /mob/living var/datum/ai_holder/ai_holder = null diff --git a/polaris.dme b/polaris.dme index 2279763bc2..88fbdc7fab 100644 --- a/polaris.dme +++ b/polaris.dme @@ -26,6 +26,7 @@ #include "code\__defines\_protect.dm" #include "code\__defines\_tick.dm" #include "code\__defines\admin.dm" +#include "code\__defines\ai.dm" #include "code\__defines\appearance.dm" #include "code\__defines\atmos.dm" #include "code\__defines\callbacks.dm"