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.
This commit is contained in:
Lohikar
2017-07-03 04:03:14 -05:00
committed by skull132
parent 780d8805de
commit d0fcc77f31
7 changed files with 12 additions and 253 deletions
+6
View File
@@ -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)
-244
View File
@@ -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)
+1 -1
View File
@@ -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
-3
View File
@@ -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
+2 -2
View File
@@ -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 <HOT>",\
" 100K NT.|WOWGOLD õnly $89 <HOT>",\
"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)
@@ -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
+1 -1
View File
@@ -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)