Improves select_recipe. (#8141)

* select_recipe improvement

Removes the call to Timsort and the recipe comparator proc;
uses a handrolled implementation of
`argmax(items + reagents + fruit)` instead.
This reduces the memory footprint of `select_recipe`
as well as the amount of processing needed to select the optimal recipe.

* angelogchay
This commit is contained in:
MarinaGryphon
2021-06-18 18:06:27 -05:00
committed by GitHub
parent 1672a51eff
commit c224b192a9
3 changed files with 44 additions and 15 deletions

View File

@@ -57,12 +57,6 @@
if (!.)
. = B[STAT_ENTRY_COUNT] - A[STAT_ENTRY_COUNT]
// Compares complexity of recipes for use in cooking, etc. This is for telling which recipe to make, not for showing things to the player.
/proc/cmp_recipe_complexity_dsc(datum/recipe/A, datum/recipe/B)
var/a_score = LAZYLEN(A.items) + LAZYLEN(A.reagents) + LAZYLEN(A.fruit)
var/b_score = LAZYLEN(B.items) + LAZYLEN(B.reagents) + LAZYLEN(B.fruit)
return b_score - a_score
/proc/cmp_typepaths_asc(A, B)
return sorttext("[B]","[A]")

View File

@@ -314,20 +314,19 @@
// When exact is false, extraneous ingredients are ignored
// When exact is true, extraneous ingredients will fail the recipe
// In both cases, the full complement of required inredients is still needed
// In both cases, the full set of required ingredients is still needed
/proc/select_recipe(var/list/datum/recipe/available_recipes, var/obj/obj as obj, var/exact)
var/list/datum/recipe/possible_recipes = list()
var/highest_count = 0
var/count = 0
for (var/datum/recipe/recipe in available_recipes)
if(!recipe.check_reagents(obj.reagents, exact) || !recipe.check_items(obj, exact) || !recipe.check_fruit(obj, exact))
continue
possible_recipes |= recipe
if (!possible_recipes.len)
return null
else if (possible_recipes.len == 1)
return possible_recipes[1]
else //okay, let's select the most complicated recipe
sortTim(possible_recipes, /proc/cmp_recipe_complexity_dsc)
return possible_recipes[1]
// Taken from cmp_recipe_complexity_dsc, but is way faster.
count = LAZYLEN(recipe.items) + LAZYLEN(recipe.reagents) + LAZYLEN(recipe.fruit)
if(count >= highest_count)
highest_count = count
. = recipe
// Both of these are just placeholders to allow special behavior for mob holders, but you can do other things in here later if you feel like it.
/datum/recipe/proc/before_cook(obj/container) // Called Before the Microwave starts delays and cooking stuff