From d0fcc77f31af58cbf64c4e1ab5f4c546edf9afbc Mon Sep 17 00:00:00 2001 From: Lohikar Date: Mon, 3 Jul 2017 04:03:14 -0500 Subject: [PATCH] List stuff (#2932) changes: Converted some list procs to macros (why the fuck was islist() a proc?!) Removed some old sorting procs and replaced their few remaining calls with sortTim() calls. --- code/__defines/lists.dm | 6 + code/_helpers/lists.dm | 244 ------------------ code/game/machinery/computer/message.dm | 2 +- code/modules/admin/admin_secrets.dm | 3 - code/modules/events/money_spam.dm | 4 +- .../mob/living/simple_animal/parrot.dm | 4 +- code/modules/nano/modules/law_manager.dm | 2 +- 7 files changed, 12 insertions(+), 253 deletions(-) diff --git a/code/__defines/lists.dm b/code/__defines/lists.dm index 1990b624dfe..6c9e41580be 100644 --- a/code/__defines/lists.dm +++ b/code/__defines/lists.dm @@ -8,3 +8,9 @@ #define LAZYCLEARLIST(L) if(L) L.Cut() #define LAZYPICK(L,DEFAULT) (LAZYLEN(L) ? pick(L) : DEFAULT) + +// Shims for some list procs in lists.dm. +#define islist(L) istype(L,/list) +#define isemptylist(L) (!LAZYLEN(L)) +#define safepick(L) LAZYPICK(L,null) +#define listgetindex(L,I) LAZYACCESS(L,I) diff --git a/code/_helpers/lists.dm b/code/_helpers/lists.dm index f20880bc43f..dd5d244b263 100644 --- a/code/_helpers/lists.dm +++ b/code/_helpers/lists.dm @@ -37,33 +37,6 @@ temp_list[O] = text2num(temp_list[O]) return temp_list -//Returns list element or null. Should prevent "index out of bounds" error. -proc/listgetindex(var/list/list,index) - if(istype(list) && list.len) - if(isnum(index)) - if(InRange(index,1,list.len)) - return list[index] - else if(index in list) - return list[index] - return - -proc/islist(list/list) - if(istype(list)) - return 1 - return 0 - -//Return either pick(list) or null if list is not of type /list or is empty -proc/safepick(list/list) - if(!islist(list) || !list.len) - return - return pick(list) - -//Checks if the list is empty -proc/isemptylist(list/list) - if(!list.len) - return 1 - return 0 - //Checks for specific types in a list /proc/is_type_in_list(var/atom/A, var/list/L) for(var/type in L) @@ -104,11 +77,6 @@ proc/isemptylist(list/list) instances++ return instances -//Empties the list by .Cut(). Setting lenght = 0 has been confirmed to leak references. -proc/clearlist(var/list/L) - if(islist(L)) - L.Cut() - //Removes any null entries from the list //Returns TRUE if the list had nulls, FALSE otherwise /proc/listclearnulls(list/L) @@ -339,218 +307,6 @@ proc/clearlist(var/list/L) i++ return i -//Don't use this on lists larger than half a dozen or so -/proc/insertion_sort_numeric_list_ascending(var/list/L) - //world.log << "ascending len input: [L.len]" - var/list/out = list(pop(L)) - for(var/entry in L) - if(isnum(entry)) - var/success = 0 - for(var/i=1, i<=out.len, i++) - if(entry <= out[i]) - success = 1 - out.Insert(i, entry) - break - if(!success) - out.Add(entry) - - //world.log << " output: [out.len]" - return out - -/proc/insertion_sort_numeric_list_descending(var/list/L) - //world.log << "descending len input: [L.len]" - var/list/out = insertion_sort_numeric_list_ascending(L) - //world.log << " output: [out.len]" - return reverselist(out) - -/proc/dd_sortedObjectList(var/list/L, var/cache=list()) - if(L.len < 2) - return L - var/middle = L.len / 2 + 1 // Copy is first,second-1 - return dd_mergeObjectList(dd_sortedObjectList(L.Copy(0,middle), cache), dd_sortedObjectList(L.Copy(middle), cache), cache) //second parameter null = to end of list - -/proc/dd_mergeObjectList(var/list/L, var/list/R, var/list/cache) - var/Li=1 - var/Ri=1 - var/list/result = new() - while(Li <= L.len && Ri <= R.len) - var/LLi = L[Li] - var/RRi = R[Ri] - var/LLiV = cache[LLi] - var/RRiV = cache[RRi] - if(!LLiV) - LLiV = LLi:dd_SortValue() - cache[LLi] = LLiV - if(!RRiV) - RRiV = RRi:dd_SortValue() - cache[RRi] = RRiV - if(LLiV < RRiV) - result += L[Li++] - else - result += R[Ri++] - - if(Li <= L.len) - return (result + L.Copy(Li, 0)) - return (result + R.Copy(Ri, 0)) - -// Insert an object into a sorted list, preserving sortedness -/proc/dd_insertObjectList(var/list/L, var/O) - var/min = 1 - var/max = L.len - var/Oval = O:dd_SortValue() - - while(1) - var/mid = min+round((max-min)/2) - - if(mid == max) - L.Insert(mid, O) - return - - var/Lmid = L[mid] - var/midval = Lmid:dd_SortValue() - if(Oval == midval) - L.Insert(mid, O) - return - else if(Oval < midval) - max = mid - else - min = mid+1 - -/* -proc/dd_sortedObjectList(list/incoming) - /* - Use binary search to order by dd_SortValue(). - This works by going to the half-point of the list, seeing if the node in - question is higher or lower cost, then going halfway up or down the list - and checking again. This is a very fast way to sort an item into a list. - */ - var/list/sorted_list = new() - var/low_index - var/high_index - var/insert_index - var/midway_calc - var/current_index - var/current_item - var/current_item_value - var/current_sort_object_value - var/list/list_bottom - - var/current_sort_object - for (current_sort_object in incoming) - low_index = 1 - high_index = sorted_list.len - while (low_index <= high_index) - // Figure out the midpoint, rounding up for fractions. (BYOND rounds down, so add 1 if necessary.) - midway_calc = (low_index + high_index) / 2 - current_index = round(midway_calc) - if (midway_calc > current_index) - current_index++ - current_item = sorted_list[current_index] - - current_item_value = current_item:dd_SortValue() - current_sort_object_value = current_sort_object:dd_SortValue() - if (current_sort_object_value < current_item_value) - high_index = current_index - 1 - else if (current_sort_object_value > current_item_value) - low_index = current_index + 1 - else - // current_sort_object == current_item - low_index = current_index - break - - // Insert before low_index. - insert_index = low_index - - // Special case adding to end of list. - if (insert_index > sorted_list.len) - sorted_list += current_sort_object - continue - - // Because BYOND lists don't support insert, have to do it by: - // 1) taking out bottom of list, 2) adding item, 3) putting back bottom of list. - list_bottom = sorted_list.Copy(insert_index) - sorted_list.Cut(insert_index) - sorted_list += current_sort_object - sorted_list += list_bottom - return sorted_list -*/ - -proc/dd_sortedtextlist(list/incoming, case_sensitive = 0) - // Returns a new list with the text values sorted. - // Use binary search to order by sortValue. - // This works by going to the half-point of the list, seeing if the node in question is higher or lower cost, - // then going halfway up or down the list and checking again. - // This is a very fast way to sort an item into a list. - var/list/sorted_text = new() - var/low_index - var/high_index - var/insert_index - var/midway_calc - var/current_index - var/current_item - var/list/list_bottom - var/sort_result - - var/current_sort_text - for (current_sort_text in incoming) - low_index = 1 - high_index = sorted_text.len - while (low_index <= high_index) - // Figure out the midpoint, rounding up for fractions. (BYOND rounds down, so add 1 if necessary.) - midway_calc = (low_index + high_index) / 2 - current_index = round(midway_calc) - if (midway_calc > current_index) - current_index++ - current_item = sorted_text[current_index] - - if (case_sensitive) - sort_result = sorttextEx(current_sort_text, current_item) - else - sort_result = sorttext(current_sort_text, current_item) - - switch(sort_result) - if (1) - high_index = current_index - 1 // current_sort_text < current_item - if (-1) - low_index = current_index + 1 // current_sort_text > current_item - if (0) - low_index = current_index // current_sort_text == current_item - break - - // Insert before low_index. - insert_index = low_index - - // Special case adding to end of list. - if (insert_index > sorted_text.len) - sorted_text += current_sort_text - continue - - // Because BYOND lists don't support insert, have to do it by: - // 1) taking out bottom of list, 2) adding item, 3) putting back bottom of list. - list_bottom = sorted_text.Copy(insert_index) - sorted_text.Cut(insert_index) - sorted_text += current_sort_text - sorted_text += list_bottom - return sorted_text - - -proc/dd_sortedTextList(list/incoming) - var/case_sensitive = 1 - return dd_sortedtextlist(incoming, case_sensitive) - - -/datum/proc/dd_SortValue() - return "[src]" - -/obj/machinery/dd_SortValue() - return "[sanitize_old(name)]" - -/obj/machinery/camera/dd_SortValue() - return "[c_tag]" - -/datum/alarm/dd_SortValue() - return "[sanitize_old(last_name)]" - /proc/subtypesof(prototype) return (typesof(prototype) - prototype) diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 2bb9dcf126e..05e7a5cb680 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -427,7 +427,7 @@ if(!P.owner || P.toff || P.hidden) continue sendPDAs += P if(PDAs && PDAs.len > 0) - customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortAtom(sendPDAs) + customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sendPDAs else customrecepient = null diff --git a/code/modules/admin/admin_secrets.dm b/code/modules/admin/admin_secrets.dm index 95d02a527ea..50e9d93c9e5 100644 --- a/code/modules/admin/admin_secrets.dm +++ b/code/modules/admin/admin_secrets.dm @@ -47,9 +47,6 @@ var/datum/admin_secrets/admin_secrets = new() var/permissions = R_ADMIN var/warn_before_use = 0 -/datum/admin_secret_item/dd_SortValue() - return "[name]" - /datum/admin_secret_item/proc/name() return name diff --git a/code/modules/events/money_spam.dm b/code/modules/events/money_spam.dm index 881bacfd72b..7937ccbef15 100644 --- a/code/modules/events/money_spam.dm +++ b/code/modules/events/money_spam.dm @@ -29,7 +29,7 @@ // /obj/machinery/message_server/proc/send_pda_message(var/recipient = "",var/sender = "",var/message = "") var/obj/item/device/pda/P var/list/viables = list() - for(var/obj/item/device/pda/check_pda in sortAtom(PDAs)) + for(var/obj/item/device/pda/check_pda in PDAs) if (!check_pda.owner||check_pda.toff||check_pda == src||check_pda.hidden) continue viables.Add(check_pda) @@ -59,7 +59,7 @@ message = pick("Luxury watches for Blowout sale prices!",\ "Watches, Jewelry & Accessories, Bags & Wallets !",\ "Deposit 100$ and get 300$ totally free!",\ - " 100K NT.|WOWGOLD õnly $89 ",\ + " 100K NT.|WOWGOLD õnly $89 ",\ "We have been filed with a complaint from one of your customers in respect of their business relations with you.",\ "We kindly ask you to open the COMPLAINT REPORT (attached) to reply on this complaint..") if(4) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 1c7f92c7330..76c162985fd 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -189,7 +189,7 @@ src.ears = headset_to_add usr << "You fit the headset onto [src]." - clearlist(available_channels) + LAZYCLEARLIST(available_channels) for(var/ch in headset_to_add.channels) switch(ch) if("Engineering") @@ -293,7 +293,7 @@ speak.Remove(pick(speak)) speak.Add(pick(speech_buffer)) - clearlist(speech_buffer) + LAZYCLEARLIST(speech_buffer) //-----SLEEPING diff --git a/code/modules/nano/modules/law_manager.dm b/code/modules/nano/modules/law_manager.dm index 9410e989120..2baa0edda41 100644 --- a/code/modules/nano/modules/law_manager.dm +++ b/code/modules/nano/modules/law_manager.dm @@ -21,7 +21,7 @@ player_laws = new() init_subtypes(/datum/ai_laws, admin_laws) - admin_laws = dd_sortedObjectList(admin_laws) + sortTim(admin_laws, /proc/cmp_name_asc) for(var/datum/ai_laws/laws in admin_laws) if(laws.selectable)