Cataclysm-DDA icon indicating copy to clipboard operation
Cataclysm-DDA copied to clipboard

[WIP] Recursive recipes

Open marilynias opened this issue 6 months ago • 9 comments

Summary

Features "recursive recipe crafting"

Purpose of change

From the feedback for #81030 it became clear that was actually desired is to be able to craft recursively.

Describe the solution

Give recipe components another flag: [ [ "flour", 22, "CRAFTABLE" ] ]. If those components are not present, recursively check if those components are craftable and craft those first.

When displaying recipes, show recipes which components can be crafted in a different color (similar to when its using rotten components). When crafting, craft required components first.

TODO:

  • [ ] selector when multiple components are craftable
  • [ ] result information for selector menu (kcal etc.)
  • [ ] auto-craft the next recipe when component craft is completed
  • [ ] general optimization/caching
  • [ ] correct "recraft last recipe" behaviour
  • [ ] check circular dependencies
  • [ ] check for multiple recipes for same component (suffix)
  • [ ] check for in-progress crafts
  • [ ] check for components consumed by previous step

Describe alternatives you've considered

Testing

Additional context

Demo:

https://github.com/user-attachments/assets/ce5b8ecf-10bc-41f2-b41e-d10f94fca072

Just a prototype for now, currently very brittle and un-optimized.

Also don't mind the yeast_dough_rested recipe, its in preparation for the future.

marilynias avatar Jun 10 '25 13:06 marilynias

Similar principles are used for construction, sometimes with very weird results.

An example: I ordered my companion to build upwards stairs. This requires the construction of half a stair, which in turn requires the construction of a shallow pit. The bizarre path chosen was to build a coffin, bury it, unearth it, and then build the half stairs on the shallow pit left behind.

This is not an isolated case, as base camp expansions can use up much more time and materials than they ought to based on similarly bizarre paths for pits, doors, and windows.

What I'm warning against here is that your recursive logic has to be robust enough to at least find a decent path to get the materials needed, or you may end up having your rare tools deconstructed to get reasonably common components you might have wanted to get through just about any other path.

PatrikLundell avatar Jun 10 '25 14:06 PatrikLundell

This is indeed an excellent change, but please bear in mind that recipe steps are equally desired. Unattended steps would be a godsend.

Hyperseeker avatar Jun 10 '25 20:06 Hyperseeker

This is indeed an excellent change, but please bear in mind that recipe steps are equally desired. Unattended steps would be a godsend.

I don't think unattended recipes require steps. But that will be a problem for the future.

marilynias avatar Jun 11 '25 05:06 marilynias

What I'm warning against here is that your recursive logic has to be robust enough to at least find a decent path to get the materials needed, or you may end up having your rare tools deconstructed to get reasonably common components you might have wanted to get through just about any other path.

Components that are craftable have to have the flag set in the recipe. Components without the flag are ignored.

marilynias avatar Jun 11 '25 05:06 marilynias

Deliberately marking components eligible for recursion reduces the risk of stupidity, but it doesn't prevent it. There are quite a few things that can be made using multiple recipes, so a choice of which one to use would have to be made. I believe there is a "base" recipe which is just the name of the item, but there can be alternatives that use suffixes. One approach would be ignore suffixed versions and only considering the base recipe. That would obviously have consequences.

PatrikLundell avatar Jun 11 '25 07:06 PatrikLundell

Oh I forgot about suffixes. But since I plan of implementing a choice query for which component to craft if multiple are possible, similarly to current component query, it should not be too difficult to ask for the recipe version you want to use.

marilynias avatar Jun 11 '25 07:06 marilynias

I don't think unattended recipes require steps.

I think they will, 'cause otherwise what you end up having is a bunch of half-finished products, and I seem to remember the core dev team being quite opposed to creating a bunch of small items for this sort of thing. It's partly a developer experience thing, in this case.

No pressure. Just wanted to give some feedback on a cool feature.

Hyperseeker avatar Jun 11 '25 14:06 Hyperseeker

I think they will, 'cause otherwise what you end up having is a bunch of half-finished products, and I seem to remember the core dev team being quite opposed to creating a bunch of small items for this sort of thing. It's partly a developer experience thing, in this case.

No pressure. Just wanted to give some feedback on a cool feature.

The comments from #81030 made it clear that every step should have its own product to be able to be used in different recipes, so intermediate items no matter what. But yeah, not relevent yet for this PR.

marilynias avatar Jun 11 '25 16:06 marilynias

That's actually a pretty decent representation of what we want, methinks I don't think it is actually necessary to have subcomponent for steps, like i absolutely can see dough not requiring such, or set of crafts that may or may not require to unfreeze the meat before cooking it (atm we have bunch of crafts that do allow to cook frozen meat directly, and another bunch that do not), unless it is handled by allowing to require item with specific flag (like water vs water (hot))

GuardianDll avatar Jun 12 '25 13:06 GuardianDll

update: can select which recipe to use for a given component. Currently shows recipe id, since I dont think there is a description of the recipe that doesn't just list the result. I will probably allow using the "name" field in recipes for non-practice recipes in a separate PR if it doesn't break other stuff like crafting menu filtering.

https://github.com/user-attachments/assets/297d4012-cb7a-4e37-8a5a-0294d1742e01

marilynias avatar Jun 23 '25 13:06 marilynias

Apologies for the slow progress, but this is quite a bit above my current skill-level, but I'm still committed to see this through. Next milestone reached: start next craft when current is finished, correctly implement known recipes, so that we check follower recipes and follower crafting, and checking requirement alternatives (deduped-requirements).

https://github.com/user-attachments/assets/199857e2-2546-4353-9264-21bb3180def5

Currently marking duplicate requirements (notably LIST categories) as craftable is broken, since one part of the component is craftable and the other is not, confusing the system. I will have to adjust the de-duplicator, so that it takes into account the craftable flag. But that part of the code is so opaque that that will probably have to wait for a follow-up.

marilynias avatar Jul 07 '25 07:07 marilynias

this is a beautiful PR, good luck.

I-am-Erk avatar Jul 15 '25 16:07 I-am-Erk

I'm a little concerned about the direction of selecting components, but hopefully I'm just misunderstanding something.

The use case I'm worried about is recipes where there are dozens of component choices to make. Is there a mechanism here that either prevents that from happening altogether, or makes it where that isn't presenting the player with a dozen or more choices in order to start a craft?

kevingranade avatar Jul 15 '25 16:07 kevingranade

The use case I'm worried about is recipes where there are dozens of component choices to make. Is there a mechanism here that either prevents that from happening altogether, or makes it where that isn't presenting the player with a dozen or more choices in order to start a craft?

If the craft can be done with existing components, it will do that without query. Otherwise if there is only 1 component with with 1 recipe to craft that component, it will do that without query.

I'm not sure if there will be many cases where you'd need to make more then ~4 choices (depending on just how recursive the crafting gets.)

marilynias avatar Jul 18 '25 11:07 marilynias

If is not actually recursive, as in it will craft components for the current craft but not components for those crafts, I would imagine it wouldn't get out of control.

If it's actually recursive I don't see it working without at least sometimes walking the player through an unreasonably long list of choices about which component to use for something.

kevingranade avatar Jul 18 '25 16:07 kevingranade

It is fully recursive, but it depends on how many intermediate recipes there are and how many alternate components those recipes have. I expect Recipes with > 4 intermediate steps to be very rare (purely on instinct/feeling).

But no matter what, it will be fewer key-presses then currently, where you have to craft each step individually. Of course I'm very open to suggestions on how to handle this better. Maybe I could calculate the time each recipe/alternate component selection takes and automatically do the shortest one, but the player may, for example, want to craft food with the highest calories instead of the quickest.

(sorry for the late responses, I don't have much time to work on this atm)

marilynias avatar Jul 21 '25 10:07 marilynias

What happens when the skill/proficiency requirements of the crafting of missing components exceed the skills/proficiencies of the crafter?

An example: Leather Body Armor (a quest item) is a simple recipe where you just assemble the set of parts requiring Tailoring 1 and Principles of Leatherworking.

  • Leather Armor Cuirass: Tailoring 4, Principles of Leatherworking, Skilled Leatherworking
  • Leather Arm Guards, same, but Tailoring 3
  • Leather Leg Guards: ditto

This is a fairly easy example, as all the skill/proficiency requirements are closely related, but the parts are considerably harder to make than assembling them. It should be similar with other armor assemblies. I tried to find appliance examples, but you currently can't make the difficult parts or make the items at all, it seems (disconnected oven uses parts you can't make, except for crude heating elements, which are harder to make than the assembly).

PatrikLundell avatar Jul 21 '25 11:07 PatrikLundell

What happens when the skill/proficiency requirements of the crafting of missing components exceed the skills/proficiencies of the crafter?

I double checked and currently I do not check for skill/proficiency. Thank you, will fix.

marilynias avatar Jul 21 '25 11:07 marilynias

What would happen if there is more than one recipe under such id? one of the extensions crafting needs is alternative tools that alter the speed of craft, and i wonder if it can be handled by something like separate recipe for "sew everything by hand" and "sew everything using sewing machine", or it's something out of scope

GuardianDll avatar Jul 22 '25 07:07 GuardianDll

I agree, that would be very helpful, but I currently don't have the mental capacity to also take that on, my brain is already mush from this PR. Though if someone wants to design the system, I could do the implementation and work that into this PR, but its too much for me alone rn.

marilynias avatar Jul 22 '25 07:07 marilynias

Spell checker encountered unrecognized words in the in-game text added in this pull request. See below for details.

Click to expand
  • comp %s available (cache)
  • comp %s craftable (cache)

This alert is automatically generated. You can simply disregard if this is inaccurate, or (optionally) you can also add the new words to tools/spell_checker/dictionary.txt so they will not trigger an alert next time.

Hints for adding a new word to the dictionary
  • If the word is normally in all lowercase, such as the noun word or the verb does, add it in its lower-case form; if the word is a proper noun, such as the surname George, add it in its initial-caps form; if the word is an acronym or has special letter case, such as the acronym CDDA or the unit mW, add it by preserving the case of all the letters. A word in the dictionary will also match its initial-caps form (if the word is in all lowercase) and all-uppercase form, so a word should be added to the dictionary in its normal letter case even if used in a different letter case in a sentence.
  • For a word to be added to the dictionary, it should either be a real, properly-spelled modern American English word, a foreign loan word (including romanized foreign names), or a foreign or made-up word that is used consistently and commonly enough in the game. Intentional misspelling (including eye dialect) of a word should not be added unless it has become a common terminology in the game, because while someone may have a legitimate use for it, another person may spell it that way accidentally.

github-actions[bot] avatar Jul 22 '25 08:07 github-actions[bot]

Just a quick status update: I'm very busy rn and won't be able to work on this for another month, give or take. If anyone wants to pick this up in the meantime, feel I'm more then willing to answer any questions.

marilynias avatar Aug 11 '25 15:08 marilynias

I'm back and returning to this.

marilynias avatar Oct 27 '25 12:10 marilynias