mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-18 19:39:42 +01:00
An AI Attempts To Kill The Schlorrgo Test Fail (#21638)
The Schlorrgo test fail has stumped me for too long, on a complete whim I threw it at the AI I normally use for math tutoring. Please do not merge this, I'm making the runners do this repeatedly in order to attempt to actually find out why the test fail is happening. I also tested this to verify the game actually still works. <img width="1081" height="579" alt="image" src="https://github.com/user-attachments/assets/32b9bf86-c4cc-4a09-8776-e0127a964fd1" />
This commit is contained in:
+107
-40
@@ -70,38 +70,55 @@
|
||||
*/
|
||||
/datum/proc/UnregisterSignal(datum/target, sig_type_or_types)
|
||||
var/list/lookup = target._listen_lookup
|
||||
if(!_signal_procs || !_signal_procs[target] || !lookup)
|
||||
var/list/procs = _signal_procs
|
||||
|
||||
// If neither side has anything, bail.
|
||||
if(!lookup && (!procs || !procs[target]))
|
||||
return
|
||||
|
||||
if(!islist(sig_type_or_types))
|
||||
sig_type_or_types = list(sig_type_or_types)
|
||||
for(var/sig in sig_type_or_types)
|
||||
if(!_signal_procs[target][sig])
|
||||
if(!istext(sig))
|
||||
stack_trace("We're unregistering with something that isn't a valid signal \[[sig]\], you fucked up")
|
||||
continue
|
||||
switch(length(lookup[sig]))
|
||||
if(2)
|
||||
lookup[sig] = (lookup[sig]-src)[1]
|
||||
if(1)
|
||||
stack_trace("[target] ([target.type]) somehow has single length list inside _listen_lookup")
|
||||
if(src in lookup[sig])
|
||||
lookup -= sig
|
||||
if(!length(lookup))
|
||||
target._listen_lookup = null
|
||||
break
|
||||
if(0)
|
||||
if(lookup[sig] != src)
|
||||
continue
|
||||
lookup -= sig
|
||||
if(!length(lookup))
|
||||
target._listen_lookup = null
|
||||
break
|
||||
else
|
||||
lookup[sig] -= src
|
||||
|
||||
_signal_procs[target] -= sig_type_or_types
|
||||
if(!_signal_procs[target].len)
|
||||
_signal_procs -= target
|
||||
var/list/target_procs = procs ? procs[target] : null
|
||||
|
||||
for(var/sig in sig_type_or_types)
|
||||
var/has_proc = target_procs && target_procs[sig]
|
||||
|
||||
// Always try to clean the emitter side if lookup exists
|
||||
if(lookup && (sig in lookup))
|
||||
var/current = lookup[sig]
|
||||
|
||||
switch(length(current))
|
||||
if(2)
|
||||
// 2-element list: remove src, collapse to single datum
|
||||
var/list/new_list = current - src
|
||||
if(new_list.len)
|
||||
lookup[sig] = new_list.len == 1 ? new_list[1] : new_list
|
||||
else
|
||||
// if somehow both gone, just drop the key
|
||||
lookup -= sig
|
||||
if(1)
|
||||
// Single-length list (weird state, but handle it)
|
||||
if(islist(current) && (src in current))
|
||||
lookup -= sig
|
||||
if(0)
|
||||
// Non-list: either src or somebody else
|
||||
if(current == src)
|
||||
lookup -= sig
|
||||
else
|
||||
// >2 listeners
|
||||
current -= src
|
||||
|
||||
if(lookup && !lookup.len)
|
||||
target._listen_lookup = null
|
||||
|
||||
// Listener side cleanup, only if we actually had a proc
|
||||
if(has_proc)
|
||||
target_procs -= sig
|
||||
|
||||
// Final tidy: if target_procs is empty, remove that target from _signal_procs
|
||||
if(target_procs && !target_procs.len)
|
||||
procs -= target
|
||||
|
||||
/**
|
||||
* Internal proc to handle most all of the signaling procedure
|
||||
@@ -111,18 +128,68 @@
|
||||
* Use the [SEND_SIGNAL] define instead
|
||||
*/
|
||||
/datum/proc/_SendSignal(sigtype, list/arguments)
|
||||
var/target = _listen_lookup[sigtype]
|
||||
if(!length(target))
|
||||
var/datum/listening_datum = target
|
||||
return NONE | call(listening_datum, listening_datum._signal_procs[src][sigtype])(arglist(arguments))
|
||||
var/target = _listen_lookup?[sigtype]
|
||||
|
||||
// No listeners at all for this signal
|
||||
if(!target)
|
||||
return NONE
|
||||
|
||||
. = NONE
|
||||
// This exists so that even if one of the signal receivers unregisters the signal,
|
||||
// all the objects that are receiving the signal get the signal this final time.
|
||||
// AKA: No you can't cancel the signal reception of another object by doing an unregister in the same signal.
|
||||
|
||||
// SINGLE LISTENER
|
||||
if(!islist(target))
|
||||
var/datum/listening_datum = target
|
||||
if(!listening_datum)
|
||||
return NONE
|
||||
|
||||
var/list/proc_map = listening_datum?._signal_procs?[src]
|
||||
|
||||
if(!proc_map)
|
||||
// Listener has completely forgotten this source;
|
||||
// clean the emitter side and log.
|
||||
stack_trace("Signal mismatch (single): [src] has [sigtype] for [listening_datum], but listener has no _signal_procs entry")
|
||||
if(_listen_lookup[sigtype] == listening_datum)
|
||||
_listen_lookup -= sigtype
|
||||
return NONE
|
||||
|
||||
var/proc_name = proc_map[sigtype]
|
||||
if(!proc_name)
|
||||
// Listener still has a table for this source, but not this signal.
|
||||
stack_trace("Signal mismatch (single): [src] has [sigtype] for [listening_datum], but listener has no matching proc entry")
|
||||
if(_listen_lookup[sigtype] == listening_datum)
|
||||
_listen_lookup -= sigtype
|
||||
return NONE
|
||||
|
||||
// Happy path
|
||||
return NONE | call(listening_datum, proc_name)(arglist(arguments))
|
||||
|
||||
// MULTIPLE LISTENERS
|
||||
var/list/listeners = target
|
||||
var/list/queued_calls = list()
|
||||
// This should be faster than doing `var/datum/listening_datum as anything in target` as it does not implicitly copy the list
|
||||
for(var/i in 1 to length(target))
|
||||
var/datum/listening_datum = target[i]
|
||||
queued_calls.Add(listening_datum, listening_datum._signal_procs[src][sigtype])
|
||||
for(var/i in 1 to length(queued_calls) step 2)
|
||||
|
||||
for(var/i in 1 to listeners.len)
|
||||
var/datum/listening_datum = listeners[i]
|
||||
if(!listening_datum)
|
||||
continue
|
||||
|
||||
var/list/proc_map = listening_datum?._signal_procs?[src]
|
||||
if(!proc_map)
|
||||
// Listener forgot this source, but the source still remembers the listener.
|
||||
stack_trace("Signal mismatch: [src] has [sigtype] in _listen_lookup but [listening_datum] has no _signal_procs entry for it")
|
||||
// Self-heal: remove stale listener from src's listener list.
|
||||
listeners.Cut(i, i + 1)
|
||||
i--
|
||||
continue
|
||||
|
||||
var/proc_name = proc_map[sigtype]
|
||||
if(!proc_name)
|
||||
// Listener still has a table for this source, but not this signal.
|
||||
stack_trace("Signal mismatch: [src] has [sigtype] in _listen_lookup but [listening_datum] has no proc entry for it")
|
||||
listeners.Cut(i, i + 1)
|
||||
i--
|
||||
continue
|
||||
|
||||
queued_calls += list(listening_datum, proc_name)
|
||||
|
||||
for(var/i in 1 to queued_calls.len step 2)
|
||||
. |= call(queued_calls[i], queued_calls[i + 1])(arglist(arguments))
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
author: Hellfirejag
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Fixed the Schlorgo test fail."
|
||||
Reference in New Issue
Block a user