From 3ea806eecabc82caa919813d63e73f33cf6db9e3 Mon Sep 17 00:00:00 2001 From: PowerfulBacon <26465327+PowerfulBacon@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:58:40 +0100 Subject: [PATCH] Adds some mapping testers --- beestation.dme | 5 ++ code/_globalvars/lists/flavor_misc.dm | 37 ++++++++++ .../unit_tests/mapping/check_active_turfs.dm | 6 ++ .../unit_tests/mapping/check_area_apc.dm | 7 ++ .../mapping/check_camera_attachment.dm | 8 ++ .../unit_tests/mapping/check_disposals.dm | 73 +++++++++++++++++++ .../mapping/check_light_attachment.dm | 10 +++ code/modules/unit_tests/mapping/map_test.dm | 42 ++++++++--- 8 files changed, 178 insertions(+), 10 deletions(-) create mode 100644 code/modules/unit_tests/mapping/check_active_turfs.dm create mode 100644 code/modules/unit_tests/mapping/check_area_apc.dm create mode 100644 code/modules/unit_tests/mapping/check_camera_attachment.dm create mode 100644 code/modules/unit_tests/mapping/check_disposals.dm create mode 100644 code/modules/unit_tests/mapping/check_light_attachment.dm diff --git a/beestation.dme b/beestation.dme index 178bae7aa3544..719263e81d41c 100644 --- a/beestation.dme +++ b/beestation.dme @@ -4098,6 +4098,11 @@ #include "code\modules\tgui_panel\tgui_panel.dm" #include "code\modules\tooltip\tooltip.dm" #include "code\modules\unit_tests\_unit_tests.dm" +#include "code\modules\unit_tests\mapping\check_active_turfs.dm" +#include "code\modules\unit_tests\mapping\check_area_apc.dm" +#include "code\modules\unit_tests\mapping\check_camera_attachment.dm" +#include "code\modules\unit_tests\mapping\check_disposals.dm" +#include "code\modules\unit_tests\mapping\check_light_attachment.dm" #include "code\modules\unit_tests\mapping\map_test.dm" #include "code\modules\uplink\uplink_devices.dm" #include "code\modules\uplink\uplink_items.dm" diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index a70e44d4d7912..8f2166cbe19b0 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -312,6 +312,43 @@ GLOBAL_LIST_INIT(TAGGERLOCATIONS, list( "Detective's Office", )) +#if defined(UNIT_TESTS) || defined(SPACEMAN_DMM) + +GLOBAL_LIST_INIT(tagger_destination_areas, list( + "Disposals" = list(/area/maintenance/disposal), + "Cargo Bay" = list(/area/quartermaster), + "QM Office" = list(/area/quartermaster/qm, /area/quartermaster/qm_bedroom), + "Engineering" = list(/area/engine, /area/engineering), + "CE Office" = list(/area/crew_quarters/heads/chief), + "Atmospherics" = list(/area/engine/atmos, /area/engine/atmospherics_engine), + "Security" = list(/area/security), + "HoS Office" = list(/area/crew_quarters/heads/hos), + "Medbay" = list(/area/medical), + "CMO Office" = list(/area/crew_quarters/heads/cmo), + "Chemistry" = list(/area/medical/chemistry), + "Research" = list(/area/science), + "RD Office" = list(/area/crew_quarters/heads/hor), + "Robotics" = list(/area/science/robotics), + "HoP Office" = list(/area/crew_quarters/heads/hop), + "Library" = list(/area/library), + "Chapel" = list(/area/chapel), + "Theatre" = list(/area/crew_quarters/theatre), + "Bar" = list(/area/crew_quarters/bar), + "Kitchen" = list(/area/crew_quarters/kitchen), + "Hydroponics" = list(/area/hydroponics), + "Janitor Closet" = list(/area/janitor), + "Genetics" = list(/area/medical/genetics), + "Testing Range" = list(/area/science/misc_lab, /area/science/test_area, /area/science/mixing), + "Toxins" = list(/area/science/misc_lab, /area/science/test_area, /area/science/mixing), + "Dormitories" = list(/area/crew_quarters/dorms, /area/commons/dorms), + "Virology" = list(/area/medical/virology), + "Xenobiology" = list(/area/science/xenobiology), + "Law Office" = list(/area/lawoffice), + "Detective's Office" = list(/area/security/detectives_office), +)) + +#endif + GLOBAL_LIST_INIT(station_prefixes, world.file2list("strings/station_prefixes.txt") + "") GLOBAL_LIST_INIT(station_names, world.file2list("strings/station_names.txt") + "") diff --git a/code/modules/unit_tests/mapping/check_active_turfs.dm b/code/modules/unit_tests/mapping/check_active_turfs.dm new file mode 100644 index 0000000000000..12a4d26641fa6 --- /dev/null +++ b/code/modules/unit_tests/mapping/check_active_turfs.dm @@ -0,0 +1,6 @@ +/datum/unit_test/map_test/active_turfs/check_map() + var/list/failures = list() + for(var/turf/t in GLOB.active_turfs_startlist) + failures += "Roundstart active turf at ([t.x], [t.y], [t.z] in [t.loc])" + if (length(failures)) + TEST_FAIL(jointext(failures, "\n")) diff --git a/code/modules/unit_tests/mapping/check_area_apc.dm b/code/modules/unit_tests/mapping/check_area_apc.dm new file mode 100644 index 0000000000000..67906357b27c5 --- /dev/null +++ b/code/modules/unit_tests/mapping/check_area_apc.dm @@ -0,0 +1,7 @@ +/datum/unit_test/map_test/apc/check_area(area/check_area) + if (!check_area.requires_power) + return + if (!check_area.apc && !check_area.always_unpowered) + return "No APC in an area that requires power" + if (check_area.apc && check_area.always_unpowered) + return "APC found in an always unpowered area" diff --git a/code/modules/unit_tests/mapping/check_camera_attachment.dm b/code/modules/unit_tests/mapping/check_camera_attachment.dm new file mode 100644 index 0000000000000..a74a2ac3a52d9 --- /dev/null +++ b/code/modules/unit_tests/mapping/check_camera_attachment.dm @@ -0,0 +1,8 @@ +/datum/unit_test/map_test/camera/check_turf(turf/check_turf, is_map_border) + var/found = FALSE + for (var/obj/machinery/camera/camera in check_turf) + if (found) + return "Multiple cameras detected" + if (!isclosedturf(get_step(check_turf, camera.dir))) + return "Camera not attached to a wall" + found = TRUE diff --git a/code/modules/unit_tests/mapping/check_disposals.dm b/code/modules/unit_tests/mapping/check_disposals.dm new file mode 100644 index 0000000000000..0965752758a43 --- /dev/null +++ b/code/modules/unit_tests/mapping/check_disposals.dm @@ -0,0 +1,73 @@ +/obj/structure/disposalpipe/var/_traversed = 0 + +/datum/unit_test/map_test/check_disposals + var/failure_reason + var/is_sorting_network + +// Find all entries into the disposal system +/datum/unit_test/map_test/check_disposals/collect_targets(list/turfs) + var/located = list() + for (var/turf/check_turf in turfs) + var/found = locate(/obj/machinery/disposal) + if (found) + located += found + return located + +// Make sure that we can end up in the correct location +/datum/unit_test/map_test/check_disposals/check_target(obj/machinery/disposal/target) + var/list/failures = list() + failure_reason = null + is_sorting_network = FALSE + if (!target.trunk) + return "[target.name] not attached to a trunk" + // Create a terrible disposal holder object + var/obj/structure/disposalholder/holder = new() + traverse_loop(target.trunk, holder) + // Abuse byonds variables to get out (We can use pointers as an out variable in 515) + if (failure_reason) + failures += failure_reason + // This is fine, we probably are a bin that leads to space or something + if (!is_sorting_network) + return failures + holder.last_pipe = null + holder.current_pipe = null + failure_reason = null + // Since we have filters, lets make sure this is a proper, fully connected and fully functioning loop + // We should be able to enter the loop at any point from an input gate to get to our destination + for (var/sort_code in GLOB.TAGGERLOCATIONS) + holder.destinationTag = sort_code + var/obj/structure/disposaloutlet/destination = traverse_loop(target.trunk, holder) + if (failure_reason) + return failure_reason + var/arrived = FALSE + for (var/valid_destination in GLOB.tagger_destination_areas[sort_code]) + if (istype(get_area(destination), valid_destination)) + arrived = TRUE + break + if (!arrived) + failures += "Disposal track starting at [COORD(target)] does not end up in the correct destination. Expected [sort_code], got [get_area(destination)] at [COORD(destination)]" + return failures + +/datum/unit_test/map_test/check_disposals/proc/traverse_loop(obj/structure/disposalholder/holder, obj/structure/disposalpipe/start) + // First check to ensure that we end up somewhere + var/obj/structure/disposalpipe/current = holder + while (current) + holder.current_pipe = current + var/turf/T = get_step(current, current.nextdir(holder)) + current = locate(/obj/structure/disposalpipe) in T + // Found a valid ending + if (locate(/obj/structure/disposaloutlet) in T) + return locate(/obj/structure/disposaloutlet) + // Detect ending back at an input + if (locate(/obj/machinery/disposal) in T) + failure_reason = "Disposal loop starting at [COORD(start)] leads to an input node at [COORD(T)] but should lead to an outlet" + if (locate(/obj/structure/disposalpipe/sorting)) + is_sorting_network = TRUE + // End detection + if (current == null) + failure_reason = "Disposal network starting at [COORD(start)] has a pipe with no output at [COORD(T)] but should lead to an outlet" + // Loop detection + if (current._traversed == 1) + failure_reason = "Disposal network starting at [COORD(start)] contains a loop at [COORD(T)] which is not allowed" + current._traversed = 1 + holder.last_pipe = current diff --git a/code/modules/unit_tests/mapping/check_light_attachment.dm b/code/modules/unit_tests/mapping/check_light_attachment.dm new file mode 100644 index 0000000000000..ec22c1844be10 --- /dev/null +++ b/code/modules/unit_tests/mapping/check_light_attachment.dm @@ -0,0 +1,10 @@ +/datum/unit_test/map_test/lights/check_turf(turf/check_turf, is_map_border) + var/found = FALSE + for (var/obj/machinery/light/light in check_turf) + if (istype(light, /obj/machinery/light/floor)) + continue + if (found) + return "Multiple lights detected" + if (!isclosedturf(get_step(check_turf, light.dir))) + return "Light not attached to a wall" + found = TRUE diff --git a/code/modules/unit_tests/mapping/map_test.dm b/code/modules/unit_tests/mapping/map_test.dm index 671beb241d105..88f9ea0f4edbb 100644 --- a/code/modules/unit_tests/mapping/map_test.dm +++ b/code/modules/unit_tests/mapping/map_test.dm @@ -1,38 +1,60 @@ /datum/unit_test/map_test/Run() var/list/failures var/list/areas = list() + var/list/turfs = list() + // Check turfs for (var/z in 1 to world.maxz) if (!is_station_level(z)) continue for (var/x in 1 to world.maxx) for (var/y in 1 to world.maxy) var/turf/tile = locate(x, y, z) + turfs += tile areas[tile.loc] = TRUE - var/result = check_tile(tile, x == 1 || x == world.maxx || y == 1 || y == world.maxy) + var/result = check_turf(tile, x == 1 || x == world.maxx || y == 1 || y == world.maxy) if (result) - LAZYADD(failures, result) + LAZYADD(failures, "([x], [y], [z]): [result]") + // Check areas for (var/area/A in areas) var/result = check_area(A) if (result) - LAZYADD(failures, result) - if (LAZYLEN(failures)) - TEST_FAIL(jointext(failures, "\n")) + LAZYADD(failures, "([A.type]): [result]") + // Check Zs for (var/z in 1 to world.maxz) if (!is_station_level(z)) continue var/result = check_z_level(z) if (result) LAZYADD(failures, result) + // Get things we want to specifically test for + var/list/targets = collect_targets(turfs) + for (var/target in targets) + var/result = check_target(target) + if (result) + LAZYADD(failures, result) + // Full map general checks + var/result = check_map() + if (result) + LAZYADD(failures, result) + // Fail if necessary + if (LAZYLEN(failures)) + TEST_FAIL(jointext(failures, "\n")) + +/// Return a string if failed, return null otherwise +/datum/unit_test/map_test/proc/check_turf(turf/check_turf, is_map_border) /// Return a string if failed, return null otherwise -/datum/unit_test/map_test/proc/check_tile(turf/T, is_map_border) +/datum/unit_test/map_test/proc/check_map(turf/check_turf, is_map_border) /// Return a string if failed, return null otherwise -/datum/unit_test/map_test/proc/check_area(area/T) +/datum/unit_test/map_test/proc/check_area(area/check_area) /// Return a string if failed, return null otherwise /datum/unit_test/map_test/proc/check_z_level(z_value) -/datum/unit_test/map_test/test/check_tile(turf/T, is_map_border) - if (istype(T, /turf/closed/wall)) - return "[T.type] detected" +/// Returns a list of things that you want to specifically check +/datum/unit_test/map_test/proc/collect_targets(list/turfs) + return list() + +/// Return a string if failed, return null otherwise +/datum/unit_test/map_test/proc/check_target(atom/target)