Skip to content

Commit

Permalink
Areas and station areas work (#20195)
Browse files Browse the repository at this point in the history
Refactored sorting.
Added test to verify all horizon areas (outside exceptions) are marked
as station areas.
Added test to verify shuttle areas are not marked as station areas.
Refactored how the area sorting var is made and used.
Added a global list of all areas.
  • Loading branch information
FluffyGhoster authored Nov 27, 2024
1 parent 916df7c commit 3894663
Show file tree
Hide file tree
Showing 44 changed files with 483 additions and 229 deletions.
6 changes: 3 additions & 3 deletions aurorastation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,9 @@
#include "code\__HELPERS\paths\jps.dm"
#include "code\__HELPERS\paths\path.dm"
#include "code\__HELPERS\paths\sssp.dm"
#include "code\__HELPERS\sorting\__main.dm"
#include "code\__HELPERS\sorting\cmp.dm"
#include "code\__HELPERS\sorting\TimSort.dm"
#include "code\__HELPERS\sorts\cmp.dm"
#include "code\__HELPERS\sorts\helpers.dm"
#include "code\__HELPERS\sorts\sort_instance.dm"
#include "code\_globalvars\configuration.dm"
#include "code\_globalvars\edible.dm"
#include "code\_globalvars\logging.dm"
Expand Down
68 changes: 68 additions & 0 deletions code/__HELPERS/_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,74 @@

return null

/**
* Move a single element from position from_index within a list, to position to_index
* All elements in the range [1,to_index) before the move will be before the pivot afterwards
* All elements in the range [to_index, L.len+1) before the move will be after the pivot afterwards
* In other words, it's as if the range [from_index,to_index) have been rotated using a <<< operation common to other languages.
* from_index and to_index must be in the range [1,L.len+1]
* This will preserve associations ~Carnie
**/
/proc/move_element(list/inserted_list, from_index, to_index)
if(from_index == to_index || from_index + 1 == to_index) //no need to move
return
if(from_index > to_index)
++from_index //since a null will be inserted before from_index, the index needs to be nudged right by one

inserted_list.Insert(to_index, null)
inserted_list.Swap(from_index, to_index)
inserted_list.Cut(from_index, from_index + 1)


/**
* Move elements [from_index,from_index+len) to [to_index-len, to_index)
* Same as moveElement but for ranges of elements
* This will preserve associations ~Carnie
**/
/proc/move_range(list/inserted_list, from_index, to_index, len = 1)
var/distance = abs(to_index - from_index)
if(len >= distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going. The result being, our range we are moving is shifted left or right by dist elements
if(from_index <= to_index)
return //no need to move
from_index += len //we want to shift left instead of right

for(var/i in 1 to distance)
inserted_list.Insert(from_index, null)
inserted_list.Swap(from_index, to_index)
inserted_list.Cut(to_index, to_index + 1)
else
if(from_index > to_index)
from_index += len

for(var/i in 1 to len)
inserted_list.Insert(to_index, null)
inserted_list.Swap(from_index, to_index)
inserted_list.Cut(from_index, from_index + 1)

///Move elements from [from_index, from_index+len) to [to_index, to_index+len)
///Move any elements being overwritten by the move to the now-empty elements, preserving order
///Note: if the two ranges overlap, only the destination order will be preserved fully, since some elements will be within both ranges ~Carnie
/proc/swap_range(list/inserted_list, from_index, to_index, len=1)
var/distance = abs(to_index - from_index)
if(len > distance) //there is an overlap, therefore swapping each element will require more swaps than inserting new elements
if(from_index < to_index)
to_index += len
else
from_index += len

for(var/i in 1 to distance)
inserted_list.Insert(from_index, null)
inserted_list.Swap(from_index, to_index)
inserted_list.Cut(to_index, to_index + 1)
else
if(to_index > from_index)
var/temp = to_index
to_index = from_index
from_index = temp

for(var/i in 1 to len)
inserted_list.Swap(from_index++, to_index++)

///replaces reverseList ~Carnie
/proc/reverse_range(list/inserted_list, start = 1, end = 0)
if(inserted_list.len)
Expand Down
12 changes: 12 additions & 0 deletions code/__HELPERS/areas.dm
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,15 @@

/proc/is_not_maint_area(var/area/A)
. = !is_maint_area(A)

/*
Area Sorting
*/
/proc/require_area_resort()
GLOB.sortedAreas = null

/// Returns a sorted version of GLOB.areas, by name
/proc/get_sorted_areas()
if(!GLOB.sortedAreas)
GLOB.sortedAreas = sortTim(GLOB.areas.Copy(), /proc/cmp_name_asc)
return GLOB.sortedAreas
2 changes: 1 addition & 1 deletion code/__HELPERS/game.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
return max_z

/proc/get_area_name(N) //get area by its name
for(var/area/A in GLOB.all_areas)
for(var/area/A in get_sorted_areas())
if(A.name == N)
return A
return 0
Expand Down
4 changes: 1 addition & 3 deletions code/__HELPERS/global_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,8 @@ GLOBAL_LIST_EMPTY(implants)

/// Turf is added to this list if is_station_level() passes when it's initialized.
GLOBAL_LIST_EMPTY(station_turfs)
/// List of all instanced areas by type.
/// List of all instanced areas by type. THIS IS DIFFERENT FROM TG AS IT DOES NOT ONLY CONTAIN UNIQUE AREAS.
GLOBAL_LIST_EMPTY(areas_by_type)
/// List of all instanced areas.
GLOBAL_LIST_EMPTY(all_areas)

/// Languages/species/whitelist.
GLOBAL_LIST_EMPTY_TYPED(all_species, /datum/species)
Expand Down
17 changes: 0 additions & 17 deletions code/__HELPERS/sorting/TimSort.dm

This file was deleted.

File renamed without changes.
49 changes: 49 additions & 0 deletions code/__HELPERS/sorts/helpers.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/// Helper for the sorting procs. Prevents some code duplication. Creates /datum/sort_instance/sorter
#define CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex) \
if(length(to_sort) < 2) { \
return to_sort; \
} \
fromIndex = fromIndex % length(to_sort); \
toIndex = toIndex % (length(to_sort) + 1); \
if (fromIndex <= 0) { \
fromIndex += length(to_sort); \
} \
if (toIndex <= 0) { \
toIndex += length(to_sort) + 1; \
} \
var/datum/sort_instance/sorter = GLOB.sortInstance; \
if (isnull(sorter)) { \
sorter = new; \
} \
sorter.L = to_sort; \
sorter.cmp = cmp; \
sorter.associative = associative;

/**
* ## Tim Sort
* Hybrid sorting algorithm derived from merge sort and insertion sort.
*
* **Sorts in place**.
* You might not need to get the return value.
*
* @see
* https://en.wikipedia.org/wiki/Timsort
*
* @param {list} to_sort - The list to sort.
*
* @param {proc} cmp - The comparison proc to use. Default: Numeric ascending.
*
* @param {boolean} associative - Whether the list is associative. Default: FALSE.
*
* @param {int} fromIndex - The index to start sorting from. Default: 1.
*
* @param {int} toIndex - The index to stop sorting at. Default: 0.
*/
/proc/sortTim(list/to_sort, cmp = GLOBAL_PROC_REF(cmp_numeric_asc), associative = FALSE, fromIndex = 1, toIndex = 0) as /list
CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex)

sorter.timSort(fromIndex, toIndex)

return to_sort

#undef CREATE_SORT_INSTANCE
Loading

0 comments on commit 3894663

Please sign in to comment.