Files
Citadel-Station-13-RP/code/controllers/subsystem/pathfinder.dm
T
Dimasw99andGitHub ac1106caa1 Integrated circuits fixes and changes (#5962)
<!-- 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. -->
2023-09-15 13:09:13 -07:00

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)