Skip to content

Commit

Permalink
pick_weight over pickweight (#6760)
Browse files Browse the repository at this point in the history
# About the pull request

Removes `pickweight` and switches over to `pick_weight`. The only
difference is that `pickweight` treated weight 0 as weight 1, and
`pick_weight` does not. Only `utility_closets` and `flow` had 0-weight
entries, and I corrected those.

Updates `pick_weight` to TG's version, which fixes a statistical error:
tgstation/tgstation#71271
tgstation/tgstation#71273

<!-- Remove this text and explain what the purpose of your PR is.

Mention if you have tested your changes. If you changed a map, make sure
you used the mapmerge tool.
If this is an Issue Correction, you can type "Fixes Issue #169420" to
link the PR to the corresponding Issue number #169420.

Remember: something that is self-evident to you might not be to others.
Explain your rationale fully, even if you feel it goes without saying.
-->

# Explain why it's good for the game

Less redundant code. More statistical accuracy.
# Testing Photographs and Procedure
Boots.


# Changelog
:cl:
code: Fixed and refactored probability weighting for pick_weight
/:cl:
  • Loading branch information
Doubleumc committed Jul 19, 2024
1 parent dbb3dea commit c840bb9
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 29 deletions.
18 changes: 12 additions & 6 deletions code/__HELPERS/_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,23 @@
* You should only pass integers in.
*/
/proc/pick_weight(list/list_to_pick)
if(length(list_to_pick) == 0)
return null

var/total = 0
var/item
for(item in list_to_pick)
for(var/item in list_to_pick)
if(!list_to_pick[item])
list_to_pick[item] = 0
total += list_to_pick[item]

total = rand(0, total)
for(item in list_to_pick)
total -= list_to_pick[item]
if(total <= 0 && list_to_pick[item])
total = rand(1, total)
for(var/item in list_to_pick)
var/item_weight = list_to_pick[item]
if(item_weight == 0)
continue

total -= item_weight
if(total <= 0)
return item

return null
Expand Down
16 changes: 0 additions & 16 deletions code/__HELPERS/lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,6 @@
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/L)
RETURN_TYPE(L[_].type)
Expand Down
4 changes: 2 additions & 2 deletions code/game/machinery/computer/arcade.dm
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
src.temp = "[src.enemy_name] has fallen! Rejoice!"

if(!length(contents))
var/prizeselect = pickweight(prizes)
var/prizeselect = pick_weight(prizes)
new prizeselect(src.loc)

if(istype(prizeselect, /obj/item/toy/gun)) //Ammo comes with the gun
Expand Down Expand Up @@ -176,5 +176,5 @@
if(2)
num_of_prizes = rand(0,2)
for(num_of_prizes; num_of_prizes > 0; num_of_prizes--)
empprize = pickweight(prizes)
empprize = pick_weight(prizes)
new empprize(src.loc)
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
. = ..()

#ifndef UNIT_TESTS
switch (pickweight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10, "nothing" = 0, "delete" = 0)))
switch (pick_weight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10, "nothing" = 1, "delete" = 1)))
#else
var/test = "both"
switch (test) // We don't want randomness in tests
Expand Down
2 changes: 1 addition & 1 deletion code/game/supplyshuttle.dm
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ GLOBAL_DATUM_INIT(supply_controller, /datum/controller/supply, new())
for(var/datum/supply_packs_asrs/crate in cratelist)
var/weight = (floor(10000/crate.cost))
weighted_crate_list[crate] = weight
return pickweight(weighted_crate_list)
return pick_weight(weighted_crate_list)

//To stop things being sent to centcomm which should not be sent to centcomm. Recursively checks for these types.
/datum/controller/supply/proc/forbidden_atoms_check(atom/A)
Expand Down
5 changes: 2 additions & 3 deletions code/modules/nightmare/nmnodes/flow.dm
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,14 @@
if(!.) return
var/list/datum/nmnode/pickables = choices.Copy()
for(var/datum/nmnode/node as anything in pickables)
if(isnum(node.raw["weight"]))
pickables[node] = node.raw["weight"]
pickables[node] = isnum(node.raw["weight"]) ? node.raw["weight"] : 1
var/list/datum/nmnode/picked = list()
var/remaining = src.amount
#if defined(UNIT_TESTS)
remaining = length(pickables) // Force all to be picked for testing (this could potentially make false positives though)
#endif
while(length(pickables) && remaining > 0)
var/datum/nmnode/node = pickweight(pickables)
var/datum/nmnode/node = pick_weight(pickables)
remaining--
pickables -= node
picked += node
Expand Down

0 comments on commit c840bb9

Please sign in to comment.