mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-20 16:37:09 +01:00
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may not be viewable. --> <!-- You can view Contributing.MD for a detailed description of the pull request process. --> ## About The Pull Request This PR aims to bring integrated circuits not only to a more up to date version but also fix some features that weren't working. For this I have used Baystations current circuits as a working reference. I have compiled, tested and checked for runtimes. Fixes include - Tile analyzer and examiner being able to handle tiles - Reference encoder and decoders doing their job - Advanced pathfinder being able to path through access restricted doors - The EPv2 circuit using an incompatible name for cloning As a consequence for the advanced pathfinder I had to readjust how access is given to circuits which now allows them to read the passkey of ID's, store them, send them and so on. A minor tweak also adjusts the TTS circuit to 1 second. Additionally, I have added an advanced signaler that while it behaves identical to EPv2 it is able to work the moment you print it without having to set an address (Not to mention that EPv2 often fails to create an address upon print) <!-- Both 🆑's are required for the changelog to work! You can put your name to the right of the first 🆑 if you want to overwrite your GitHub username as author ingame. --> <!-- You can use multiple of the same prefix (they're only used for the icon ingame) and delete the unneeded ones. Despite some of the tags, changelogs should generally represent how a player might be affected by the changes rather than a summary of the PR's contents. -->
136 lines
6.0 KiB
Plaintext
136 lines
6.0 KiB
Plaintext
//* This file is explicitly licensed under the MIT license. *//
|
|
//* Copyright (c) 2023 Citadel Station developers. *//
|
|
|
|
#define PATHFINDER_TIMEOUT 50
|
|
|
|
SUBSYSTEM_DEF(pathfinder)
|
|
name = "Pathfinder"
|
|
subsystem_flags = SS_NO_INIT | SS_NO_FIRE
|
|
|
|
/// pathfinding mutex - most algorithms depend on this
|
|
/// multi "threading" in byond just adds overhead
|
|
/// from everything trying to re-queue their executions
|
|
/// for this reason, much like with maploading,
|
|
/// it's somewhat pointless to have more than one operation going
|
|
/// at a time
|
|
var/pathfinding_mutex = FALSE
|
|
/// pathfinding calls blocked
|
|
var/pathfinding_blocked = 0
|
|
/// pathfinding cycle - this is usable because of the mutex
|
|
/// this is used in place of a closed list in algorithms like JPS
|
|
/// to maximize performance.
|
|
var/tmp/pathfinding_cycle = 0
|
|
|
|
/**
|
|
* be aware that this emits a set of disjunct nodes
|
|
* use [jps_output_turfs()] to convert them into a proper turf path list.
|
|
*
|
|
* Please see [code/__HELPERS/pathfinding/jps.dm] for details on what JPS does/is.
|
|
*/
|
|
/datum/controller/subsystem/pathfinder/proc/get_path_jps(atom/movable/actor = GLOB.generic_pathfinding_actor, turf/goal, turf/start = get_turf(actor), target_distance = 1, max_path_length = 128)
|
|
var/datum/pathfinding/jps/instance = new(actor, start, goal, target_distance, max_path_length)
|
|
return run_pathfinding(instance)
|
|
|
|
/**
|
|
* Please see [code/__HELPERS/pathfinding/astar.dm] for details on what JPS does/is.
|
|
*/
|
|
/datum/controller/subsystem/pathfinder/proc/get_path_astar(atom/movable/actor = GLOB.generic_pathfinding_actor, turf/goal, turf/start = get_turf(actor), target_distance = 1, max_path_length = 128)
|
|
var/datum/pathfinding/astar/instance = new(actor, start, goal, target_distance, max_path_length)
|
|
return run_pathfinding(instance)
|
|
|
|
/datum/controller/subsystem/pathfinder/proc/default_ai_pathfinding(datum/ai_holder/holder, turf/goal, min_dist = 1, max_path = 128)
|
|
var/datum/pathfinding/astar/instance = new(holder.holder, get_turf(holder.holder), goal, min_dist, max_path * 2)
|
|
var/obj/item/card/id/potential_id = holder.holder.GetIdCard()
|
|
if(!isnull(potential_id))
|
|
instance.ss13_with_access = potential_id.access?.Copy()
|
|
return run_pathfinding(instance)
|
|
|
|
/datum/controller/subsystem/pathfinder/proc/default_circuit_pathfinding(obj/item/electronic_assembly/assembly, turf/goal, min_dist = 1, max_path = 128, var/list/access)
|
|
var/datum/pathfinding/jps/instance = new(assembly, get_turf(assembly), goal, min_dist, max_path)
|
|
instance.ss13_with_access = access.Copy()
|
|
return jps_output_turfs(run_pathfinding(instance))
|
|
|
|
/datum/controller/subsystem/pathfinder/proc/default_bot_pathfinding(mob/living/bot/bot, turf/goal, min_dist = 1, max_path = 128)
|
|
var/datum/pathfinding/jps/instance = new(bot, get_turf(bot), goal, min_dist, max_path)
|
|
instance.ss13_with_access = bot.botcard.access?.Copy()
|
|
return jps_output_turfs(run_pathfinding(instance))
|
|
|
|
/datum/controller/subsystem/pathfinder/proc/run_pathfinding(datum/pathfinding/instance)
|
|
var/started = world.time
|
|
++pathfinding_blocked
|
|
if(pathfinding_blocked < 10)
|
|
while(pathfinding_mutex)
|
|
stoplag(1)
|
|
if(world.time > started + PATHFINDER_TIMEOUT)
|
|
stack_trace("pathfinder timeout; check debug logs.")
|
|
log_debug("pathfinder timeout of instance with debug variables [instance.debug_log_string()]")
|
|
return
|
|
else
|
|
while(pathfinding_mutex)
|
|
stoplag(3)
|
|
if(world.time > started + PATHFINDER_TIMEOUT)
|
|
stack_trace("pathfinder timeout; check debug logs.")
|
|
log_debug("pathfinder timeout of instance with debug variables [instance.debug_log_string()]")
|
|
return
|
|
--pathfinding_blocked
|
|
pathfinding_mutex = TRUE
|
|
. = instance.search()
|
|
if(world.time > started + PATHFINDER_TIMEOUT)
|
|
stack_trace("pathfinder timeout; check debug logs.")
|
|
log_debug("pathfinder timeout of instance with debug variables [instance.debug_log_string()]")
|
|
pathfinding_mutex = FALSE
|
|
|
|
#undef PATHFINDER_TIMEOUT
|
|
|
|
/proc/astar_debug(turf/target)
|
|
if(isnull(target))
|
|
return
|
|
return SSpathfinder.get_path_astar(usr, target, get_turf(usr))
|
|
|
|
/proc/jps_debug(turf/target)
|
|
if(isnull(target))
|
|
return
|
|
return SSpathfinder.get_path_jps(usr, target, get_turf(usr))
|
|
|
|
/proc/old_astar_debug(turf/target)
|
|
if(isnull(target))
|
|
return
|
|
return graph_astar(get_turf(usr), target, TYPE_PROC_REF(/turf, CardinalTurfsWithAccess), TYPE_PROC_REF(/turf, Distance), 0, 128, 1)
|
|
|
|
/proc/old_jps_debug(turf/target)
|
|
var/turf/start = get_turf(usr)
|
|
var/atom/movable/delegate_for_tg = new(start)
|
|
var/datum/tg_jps_pathfind/tg_instance = new(delegate_for_tg, target, null, 128, 1, FALSE, null)
|
|
return tg_instance.search()
|
|
|
|
/proc/pathfinding_run_all(turf/start = get_turf(usr), turf/goal)
|
|
var/pass_silicons_astar = SSpathfinder.get_path_astar(goal = goal, start = start, target_distance = 1, max_path_length = 256)
|
|
var/pass_silicons_jps = SSpathfinder.get_path_jps(goal = goal, start = start, target_distance = 1, max_path_length = 256)
|
|
// old astar has been cut because it's such horrible code it's not worth benchmarking against the other 3.
|
|
// var/pass_old_astar = graph_astar(
|
|
// start,
|
|
// goal,
|
|
// TYPE_PROC_REF(/turf, CardinalTurfsWithAccess),
|
|
// TYPE_PROC_REF(/turf, Distance),
|
|
// 0,
|
|
// 128,
|
|
// 1,
|
|
// )
|
|
var/atom/movable/delegate_for_tg = new(start)
|
|
var/datum/tg_jps_pathfind/tg_instance = new(delegate_for_tg, goal, null, 256, 1, FALSE, null)
|
|
var/pass_tg_jps = tg_instance.search()
|
|
pass_silicons_astar = !!length(pass_silicons_astar)
|
|
pass_silicons_jps = !!length(pass_silicons_jps)
|
|
// pass_old_astar = !!length(pass_old_astar)
|
|
pass_tg_jps = !!length(pass_tg_jps)
|
|
if(pass_silicons_astar != pass_silicons_jps || pass_silicons_jps != pass_tg_jps)
|
|
log_and_message_admins("turf pair [COORD(start)], [COORD(goal)] mismatch silicons-astar [pass_silicons_astar] silicons-jps [pass_silicons_jps] tg-jps [pass_tg_jps]")
|
|
else
|
|
log_and_message_admins("turf pair [COORD(start)], [COORD(goal)] succeeded")
|
|
|
|
/proc/pathfinding_run_benchmark(times = 1000, turf/source = get_turf(usr))
|
|
var/list/turf/nearby = RANGE_TURFS(100, source)
|
|
for(var/i in 1 to min(times, 10000))
|
|
var/turf/picked = pick(nearby)
|
|
pathfinding_run_all(source, picked)
|