I've been experimenting with building a planner for the AI. For now, the idea is to be able to dynamically generate a behavior tree for acquiring a specific item. Now that we have a rudimentary crafting system that the player can interact with, I thought it might be a good idea to see if the AI characters could interact with it as well. This isn't just to give me something to tinker with - one of the earliest ideas I had for a puzzle in the game involves slipping some poison into the castle kitchen at a point in the process where it will go undetected. At that time it would have been a very scripted event, but now that I am moving towards simulation something more reactive and flexible makes more sense.
So I wrote a function called get_item_tree, which basically walks through all of the recipes, and builds a tree to acquire that item. At each level of the tree, we first determine if we already have the item or can just pick it up somewhere. If not, we recursively search for the ingredients that make up the item, and call get_item_tree on those.
Here's an example of one of these generated trees:
{ "type": "P", "name": "Get item from combo", "children": [ { "btf": "_interact_object", "type": "SUB", "args": { "action": "get", "object": "poisoned_meat", "dist": 50 } }, { "type": "S", "name": "Collect ingredients", "children": [ { "type": "P", "name": "Get item from combo", "children": [ { "btf": "_interact_object", "type": "SUB", "args": { "action": "get", "object": "meat", "dist": 50 } } ] }, { "type": "P", "name": "Get item from combo", "children": [ { "btf": "_interact_object", "type": "SUB", "args": { "action": "get", "object": "poison", "dist": 50 } }, { "type": "S", "name": "Collect ingredients", "children": [ { "type": "P", "name": "Get item from combo", "children": [ { "btf": "_interact_object", "type": "SUB", "args": { "action": "get", "object": "poisonberry", "dist": 50 } } ] }, { "type": "P", "name": "Get item from combo", "children": [ { "btf": "_interact_object", "type": "SUB", "args": { "action": "get", "object": "masher", "dist": 50 } } ] }, { "items": "poisonberry,masher", "type": "COMBINE_ACTION" } ] } ] }, { "items": "meat,poison", "type": "COMBINE_ACTION" } ] } ] }
Note that we first try to get "poisoned_meat", which if that fails we search for both meat and poison. At the end of all the searching, we make a call to combine the meat and the poison (which will access the crafting function). I can build as complicated a crafting tree as I want (though I probably won't go very deep with it in the actual game) and I can easily set up scenarios where npcs are involved in a crafting process of some kind.
I haven't actually tested the generated tree in-game yet, so there's still quite a bit to do here. Also missing is that most npc crafting will be much better for the player if you can actually see the crafting happen. Weaponsmiths will need anvils to work on, cooks will need an oven to cook meat over, weavers will need a loom, etc. I will need a much more descriptive list of recipes for npcs which includes not just the items used but the device needed, and whatever resource that device needs to function (i.e. coal for a furnace/stove).
For the player I have so far just been hardcoding these actions, such as stoking the firepit with logs. So I'll need to decide if the extra crafting info npcs need is just a markup for their benefit, or if I want to change how the player actions are coded as well to generate them from the same data. Making things more data oriented would be very cool I think.