mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-09 16:14:13 +00:00
-Added two new symptoms, fever and itching. -Changed some stats on existing symptoms. -Emotes sucks so I used visible_message if there was no preset emote. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@5021 316c924e-a436-60f5-8080-3fe189b3f50e
312 lines
7.9 KiB
Plaintext
312 lines
7.9 KiB
Plaintext
/*
|
|
* Holds procs to help with list operations
|
|
* Contains groups:
|
|
* Misc
|
|
* Sorting
|
|
*/
|
|
|
|
/*
|
|
* Misc
|
|
*/
|
|
|
|
//Returns a list in plain english as a string
|
|
/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "," )
|
|
var/total = input.len
|
|
if (!total)
|
|
return "[nothing_text]"
|
|
else if (total == 1)
|
|
return "[input[1]]"
|
|
else if (total == 2)
|
|
return "[input[1]][and_text][input[2]]"
|
|
else
|
|
var/output = ""
|
|
var/index = 1
|
|
while (index < total)
|
|
if (index == total - 1)
|
|
comma_text = final_comma_text
|
|
|
|
output += "[input[index]][comma_text]"
|
|
index++
|
|
|
|
return "[output][and_text][input[index]]"
|
|
|
|
//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)
|
|
if(istype(A, type))
|
|
return 1
|
|
return 0
|
|
|
|
//Empties the list by setting the length to 0. Hopefully the elements get garbage collected
|
|
proc/clearlist(list/list)
|
|
if(istype(list))
|
|
list.len = 0
|
|
return
|
|
|
|
//Removes any null entries from the list
|
|
proc/listclearnulls(list/list)
|
|
if(istype(list))
|
|
while(null in list)
|
|
list -= null
|
|
return
|
|
|
|
/*
|
|
* Returns list containing all the entries from first list that are not present in second.
|
|
* If skiprep = 1, repeated elements are treated as one.
|
|
* If either of arguments is not a list, returns null
|
|
*/
|
|
/proc/difflist(var/list/first, var/list/second, var/skiprep=0)
|
|
if(!islist(first) || !islist(second))
|
|
return
|
|
var/list/result = new
|
|
if(skiprep)
|
|
for(var/e in first)
|
|
if(!(e in result) && !(e in second))
|
|
result += e
|
|
else
|
|
result = first - second
|
|
return result
|
|
|
|
/*
|
|
* Returns list containing entries that are in either list but not both.
|
|
* If skipref = 1, repeated elements are treated as one.
|
|
* If either of arguments is not a list, returns null
|
|
*/
|
|
/proc/uniquemergelist(var/list/first, var/list/second, var/skiprep=0)
|
|
if(!islist(first) || !islist(second))
|
|
return
|
|
var/list/result = new
|
|
if(skiprep)
|
|
result = difflist(first, second, skiprep)+difflist(second, first, skiprep)
|
|
else
|
|
result = first ^ second
|
|
return result
|
|
|
|
//Pretends to pick an element based on its weight but really just seems to pick a random element.
|
|
/proc/pickweight(list/L)
|
|
var/total = 0
|
|
var/item
|
|
for (item in L)
|
|
if (!L[item])
|
|
L[item] = 1
|
|
total += L[item]
|
|
|
|
total = rand(1, total)
|
|
for (item in L)
|
|
total -=L [item]
|
|
if (total <= 0)
|
|
return item
|
|
|
|
return null
|
|
|
|
//Pick a random element from the list and remove it from the list.
|
|
/proc/pick_n_take(list/listfrom)
|
|
if (listfrom.len > 0)
|
|
var/picked = pick(listfrom)
|
|
listfrom -= picked
|
|
return picked
|
|
return null
|
|
|
|
//Returns the top(last) element from the list and removes it from the list (typical stack function)
|
|
/proc/pop(list/listfrom)
|
|
if (listfrom.len > 0)
|
|
var/picked = listfrom[listfrom.len]
|
|
listfrom.len--
|
|
return picked
|
|
return null
|
|
|
|
/*
|
|
* Sorting
|
|
*/
|
|
|
|
//Reverses the order of items in the list (Turning a stack into a queue)
|
|
/proc/reverselist(var/list/input)
|
|
var/list/output = new/list()
|
|
for(var/A in input)
|
|
output += A
|
|
return output
|
|
|
|
//Randomize: Return the list in a random order
|
|
/proc/shuffle(var/list/shufflelist)
|
|
if(!shufflelist)
|
|
return
|
|
var/list/new_list = list()
|
|
var/list/old_list = shufflelist.Copy()
|
|
while(old_list.len)
|
|
var/item = pick(old_list)
|
|
new_list += item
|
|
old_list -= item
|
|
return new_list
|
|
|
|
//Return a list with no duplicate entries
|
|
/proc/uniquelist(var/list/L)
|
|
var/list/K = list()
|
|
for(var/item in L)
|
|
if(!(item in K))
|
|
K += item
|
|
return K
|
|
|
|
//Mergesort: divides up the list into halves to begin the sort
|
|
/proc/sortKey(var/list/client/L, var/order = 1)
|
|
if(isnull(L) || L.len < 2)
|
|
return L
|
|
var/middle = L.len / 2 + 1
|
|
return mergeKey(sortKey(L.Copy(0,middle)), sortKey(L.Copy(middle)), order)
|
|
|
|
//Mergsort: does the actual sorting and returns the results back to sortAtom
|
|
/proc/mergeKey(var/list/client/L, var/list/client/R, var/order = 1)
|
|
var/Li=1
|
|
var/Ri=1
|
|
var/list/result = new()
|
|
while(Li <= L.len && Ri <= R.len)
|
|
var/client/rL = L[Li]
|
|
var/client/rR = R[Ri]
|
|
if(sorttext(rL.ckey, rR.ckey) == order)
|
|
result += L[Li++]
|
|
else
|
|
result += R[Ri++]
|
|
|
|
if(Li <= L.len)
|
|
return (result + L.Copy(Li, 0))
|
|
return (result + R.Copy(Ri, 0))
|
|
|
|
//Mergesort: divides up the list into halves to begin the sort
|
|
/proc/sortAtom(var/list/atom/L, var/order = 1)
|
|
if(isnull(L) || L.len < 2)
|
|
return L
|
|
var/middle = L.len / 2 + 1
|
|
return mergeAtoms(sortAtom(L.Copy(0,middle)), sortAtom(L.Copy(middle)), order)
|
|
|
|
//Mergsort: does the actual sorting and returns the results back to sortAtom
|
|
/proc/mergeAtoms(var/list/atom/L, var/list/atom/R, var/order = 1)
|
|
var/Li=1
|
|
var/Ri=1
|
|
var/list/result = new()
|
|
while(Li <= L.len && Ri <= R.len)
|
|
var/atom/rL = L[Li]
|
|
var/atom/rR = R[Ri]
|
|
if(sorttext(rL.name, rR.name) == order)
|
|
result += L[Li++]
|
|
else
|
|
result += R[Ri++]
|
|
|
|
if(Li <= L.len)
|
|
return (result + L.Copy(Li, 0))
|
|
return (result + R.Copy(Ri, 0))
|
|
|
|
|
|
|
|
|
|
//Mergesort: Specifically for record datums in a list.
|
|
/proc/sortRecord(var/list/datum/data/record/L, var/field = "name", var/order = 1)
|
|
if(isnull(L))
|
|
return list()
|
|
if(L.len < 2)
|
|
return L
|
|
var/middle = L.len / 2 + 1
|
|
return mergeRecordLists(sortRecord(L.Copy(0, middle), field, order), sortRecord(L.Copy(middle), field, order), field, order)
|
|
|
|
//Mergsort: does the actual sorting and returns the results back to sortRecord
|
|
/proc/mergeRecordLists(var/list/datum/data/record/L, var/list/datum/data/record/R, var/field = "name", var/order = 1)
|
|
var/Li=1
|
|
var/Ri=1
|
|
var/list/result = new()
|
|
if(!isnull(L) && !isnull(R))
|
|
while(Li <= L.len && Ri <= R.len)
|
|
var/datum/data/record/rL = L[Li]
|
|
if(isnull(rL))
|
|
L -= rL
|
|
continue
|
|
var/datum/data/record/rR = R[Ri]
|
|
if(isnull(rR))
|
|
R -= rR
|
|
continue
|
|
if(sorttext(rL.fields[field], rR.fields[field]) == order)
|
|
result += L[Li++]
|
|
else
|
|
result += R[Ri++]
|
|
|
|
if(Li <= L.len)
|
|
return (result + L.Copy(Li, 0))
|
|
return (result + R.Copy(Ri, 0))
|
|
|
|
|
|
|
|
|
|
//Mergesort: any value in a list
|
|
/proc/sortList(var/list/L)
|
|
if(L.len < 2)
|
|
return L
|
|
var/middle = L.len / 2 + 1 // Copy is first,second-1
|
|
return mergeLists(sortList(L.Copy(0,middle)), sortList(L.Copy(middle))) //second parameter null = to end of list
|
|
|
|
//Mergsorge: uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
|
|
/proc/sortNames(var/list/L)
|
|
var/list/Q = new()
|
|
for(var/atom/x in L)
|
|
Q[x.name] = x
|
|
return sortList(Q)
|
|
|
|
/proc/mergeLists(var/list/L, var/list/R)
|
|
var/Li=1
|
|
var/Ri=1
|
|
var/list/result = new()
|
|
while(Li <= L.len && Ri <= R.len)
|
|
if(sorttext(L[Li], R[Ri]) < 1)
|
|
result += R[Ri++]
|
|
else
|
|
result += L[Li++]
|
|
|
|
if(Li <= L.len)
|
|
return (result + L.Copy(Li, 0))
|
|
return (result + R.Copy(Ri, 0))
|
|
|
|
|
|
//Converts a bitfield to a list of numbers (or words if a wordlist is provided)
|
|
/proc/bitfield2list(bitfield = 0, list/wordlist)
|
|
var/list/r = list()
|
|
if(istype(wordlist,/list))
|
|
var/max = min(wordlist.len,16)
|
|
var/bit = 1
|
|
for(var/i=1, i<=max, i++)
|
|
if(bitfield & bit)
|
|
r += wordlist[i]
|
|
bit = bit << 1
|
|
else
|
|
for(var/bit=1, bit<=65535, bit = bit << 1)
|
|
if(bitfield & bit)
|
|
r += bit
|
|
|
|
return r
|
|
|
|
/proc/safe_pick_list(var/list/L)
|
|
if(L.len)
|
|
return pick(L)
|
|
return null |