aboutsummaryrefslogtreecommitdiff
path: root/data/recipes/default.ts
diff options
context:
space:
mode:
Diffstat (limited to 'data/recipes/default.ts')
-rw-r--r--data/recipes/default.ts302
1 files changed, 161 insertions, 141 deletions
diff --git a/data/recipes/default.ts b/data/recipes/default.ts
index 33b433a6..662b6817 100644
--- a/data/recipes/default.ts
+++ b/data/recipes/default.ts
@@ -16,12 +16,12 @@
*/
-//? Is is a good idea? Probably not.
+//? Is this a good idea? Probably not.
export interface Recipe {
tile?: string,
- inputs: (string | null)[],
- outputs: (string | null)[],
+ inputs: (Item | null | undefined)[],
+ outputs: (Item | null | undefined)[],
action: "instant" | "passive" | "active" | "demand" | "demand"
duration?: number
revert_duration?: number,
@@ -29,184 +29,204 @@ export interface Recipe {
points?: number,
}
-function trash_output(ifull: string) {
- const [i, ic] = get_container(ifull)
- if (i == "plate") return ifull
- if (i == "glass") return ifull
- if (i == "pot") return ifull
- if (i == "foodprocessor") return ifull
- if (i == "dirty") return ifull
- if (ic == "glass") return "glass"
- if (ic == "plate") return "dirty-plate"
- return null
-}
-
-export const all_items = new Set<string>()
-export function auto_trash() {
- for (const ifull of all_items) {
- let [i, ic] = get_container(ifull)
- if (i == "plate") continue
- if (i == "glass") continue
- if (i == "pot") continue
- if (i == "foodprocessor") continue
- if (i == "dirty") continue
- if (ic == "glass") ic = "glass"
- if (ic == "plate") ic = "dirty-plate"
- out({
- action: "instant",
- tile: ic == "glass" ? "sink" : "trash",
- inputs: [ifull],
- outputs: [ic]
- })
- }
-}
-
+const all_items = new Set<Item>()
+const all_recipes = new Set<Recipe>()
export function out(r: Recipe) {
r.inputs.forEach(i => i ? all_items.add(i) : void 0)
r.outputs.forEach(i => i ? all_items.add(i) : void 0)
r.inputs = r.inputs.filter(e => e)
r.outputs = r.outputs.filter(e => e)
- console.log(`- ${JSON.stringify(r).replaceAll("\"active\"", "!active").replaceAll("\"passive\"", "!passive").replaceAll("\"instant\"", "!instant")}`);
+ all_recipes.add(r);
+}
+export function finish() {
+ const k = new Set<string>()
+ for (const r of all_recipes) {
+ let s = `- action: !${r.action}\n`
+ s += ` inputs: [${r.inputs.map(e => e!.toString()).join(",")}]\n`
+ s += ` outputs: [${r.outputs.map(e => e!.toString()).join(",")}]\n`
+ if (r.warn) s += ` warn: true\n`
+ if (r.duration) s += ` duration: ${r.duration}\n`
+ if (r.revert_duration) s += ` revert_duration: ${r.revert_duration}\n`
+ if (r.points) s += ` points: ${r.points}\n`
+ if (r.tile) s += ` tile: ${r.tile}\n`
+ k.add(s)
+ }
+ for (const r of k)
+ console.log(r);
+}
+function auto_trash() {
+ for (const i of all_items) {
+ if (i instanceof Container) continue
+ if (!i.container) out({ action: "instant", inputs: [i], outputs: [], tile: "trash" })
+ else {
+ out({ action: "instant", inputs: [i], outputs: [i.container.dispose ?? i.container], tile: "trash" })
+ }
+ }
}
-export function edible(item: string) {
- let i = item
- if (!item.endsWith("-plate") && !item.endsWith("-glass")) {
- i += "-plate"
- out({ action: "instant", inputs: [item], outputs: [i] })
+class Item {
+ constructor(
+ public name: string,
+ public container?: Container
+ ) { }
+ as(s: string) { this.name = s; return this }
+ tr(container?: Container) {
+ const o = new Item(this.name, container)
+ if (this.container) out({ action: "instant", inputs: [this, container], outputs: [this.container, o] })
+ else out({ action: "instant", inputs: [container, this], outputs: [o] })
+ return o
+ }
+ toString() {
+ return this.name + (this.container ? "-" + this.container : "")
}
- out({ action: "demand", inputs: [i], outputs: [trash_output(i)], duration: 10 })
}
-export function cut(from: string, to?: string, to2?: string) {
- out({ action: "active", duration: 2, tile: "cuttingboard", inputs: [from], outputs: [to ?? ("sliced-" + from), to2 ?? null] })
+class Container extends Item { constructor(name: string, public dispose?: Item) { super(name) } }
+const FP = new Container("foodprocessor")
+const POT = new Container("pot")
+const PL = new Container("plate", new Container("dirty-plate"))
+const GL = new Container("glass")
+
+function crate(s: string): Item {
+ const item = new Item(s);
+ out({ action: "instant", inputs: [], outputs: [item], tile: `${s}-crate`, points: -1 })
+ return item
}
-export function cook(from: string, to?: string) {
- const i = from.endsWith("-pot") ? from : from + "-pot"
- const o = (to ?? ("cooked-" + from)) + "-pot"
- if (!from.endsWith("-pot")) out({ action: "instant", inputs: ["pot", from], outputs: [i] })
- out({ action: "passive", duration: 20, revert_duration: 40, tile: "stove", inputs: [i], outputs: [o] })
- out({ action: "passive", duration: 5, revert_duration: 10, tile: "stove", inputs: [o], outputs: ["burned-pot"], warn: true })
+function cut(s: Item, two?: boolean): Item {
+ const o = new Item(`sliced-${s.name}`, s.container)
+ out({ action: "active", inputs: [s], outputs: [o, two ? o : null], tile: "cuttingboard", duration: 2 })
+ return o
}
-export function process(from: string, to?: string) {
- const i = from.endsWith("-foodprocessor") ? from : from + "-foodprocessor"
- const o = (to ?? (from + "-juice")) + "-foodprocessor"
- if (!from.endsWith("-foodprocessor")) out({ action: "instant", inputs: ["foodprocessor", from], outputs: [i] })
- out({ action: "passive", duration: 5, inputs: [i], outputs: [o] })
+function cook(s: Item, duration = 20): Item {
+ const o = new Item(`cooked-${s.name}`, s.container)
+ out({ action: "passive", duration, tile: "stove", inputs: [s], outputs: [o] })
+ out({ action: "passive", duration: duration / 3, revert_duration: 20, tile: "stove", inputs: [o], outputs: [new Item("burned", POT)], warn: true })
+ return o
}
-export function bake(from: string, to?: string) {
- const o = (to ?? ("baked-" + from))
- out({ action: "passive", duration: 25, tile: "oven", inputs: [from], outputs: [o] })
- out({ action: "passive", duration: 15, revert_duration: 20, tile: "oven", inputs: [o], outputs: ["burned"], warn: true })
+function bake(s: Item, duration = 25): Item {
+ const o = new Item(`sliced-${s.name}`, s.container)
+ out({ action: "passive", duration, tile: "oven", inputs: [s], outputs: [o] })
+ out({ action: "passive", duration: duration / 2, revert_duration: 20, tile: "oven", inputs: [o], outputs: [new Item("burned")], warn: true })
+ return o
}
-export function crate(item: string) {
- out({ action: "instant", tile: item + "-crate", inputs: [], outputs: [item], points: -1 })
+function freeze(s: Item): Item {
+ const o = new Item(`frozen-${s.name}`, s.container)
+ out({ action: "passive", duration: 25, tile: "freezer", inputs: [s], outputs: [o] })
+ return o
}
-
-export function get_container(ifull: string): [string, string | null] {
- const iparts = ifull.split("-")
- const ic = iparts.pop()
- if (ic && iparts.length && ["pot", "plate", "foodprocessor", "glass"].includes(ic)) return [iparts.join("-"), ic]
- return [ifull, null]
+function process(s: Item): Item {
+ const o = new Item(`processed-${s.name}`, s.container)
+ out({ action: "passive", duration: 5, inputs: [s], outputs: [o] })
+ return o
}
-
-export function combine(container: string, ...inputs: string[]) {
- const open = inputs.map(ifull => {
- const [i, ic] = get_container(ifull)
- out({ action: "instant", inputs: [container, ifull], outputs: [i + "-" + container, ic] })
- return [i]
- })
+function container_add(base: Item, add: Item): Item {
+ const o = new Item("!!!", base.container)
+ out({ action: "instant", inputs: [base, add], outputs: [o, add.container] })
+ return o
+}
+function combine(c: Container, ...items: Item[]): Item {
+ const open = items.map(i => (i.tr(c), [i.name]))
const seen = new Set<string>()
+ let result
while (1) {
const cur = open.pop()
if (!cur) break;
- const c = cur.join("-") + "-" + container
- for (const ifull of inputs) {
- const [i, ic] = get_container(ifull)
- if (cur.includes(i)) continue
- const rkey = cur.join("-") + "#" + i
+ for (const new_item of items) {
+ if (cur.includes(new_item.name)) continue
+ const rkey = cur.join("-") + "#" + new_item
+
if (seen.has(rkey)) continue
seen.add(rkey)
- const parts = [...cur, i]
+ const parts = [...cur, new_item.name]
parts.sort()
- const o = parts.join("-") + "-" + container
open.push(parts)
+ const i = new Item(cur.join("-"), c)
+ const o = new Item(parts.join("-"), c)
+ if (parts.length == items.length) result = o
out({
action: "instant",
- inputs: [c, ifull],
- outputs: [o, ic]
+ inputs: [i, new_item],
+ outputs: [o, new_item.container]
})
}
}
+ return result!
+}
+function edible(...items: Item[]) {
+ for (const i of items) {
+ out({ action: "demand", inputs: [i], outputs: [i.container?.dispose ?? i.container], duration: 10 })
+ }
+}
+function either(a: Item, b: Item) {
+ if (a.name != b.name) throw new Error("either options are named differently");
+ if (a.container != b.container) throw new Error("either options are contained differently");
+ return a
+}
+function sink_fill(c: Container) {
+ const o = new Item("water", c)
+ out({ action: "instant", inputs: [c], outputs: [o], tile: "sink" })
+ return o
}
+out({ action: "active", duration: 2, tile: "sink", inputs: [new Container("dirty-plate")], outputs: [PL] })
-if (import.meta.main) {
- out({ action: "active", duration: 2, tile: "sink", inputs: ["dirty-plate"], outputs: ["plate"] })
-
- crate("tomato")
- crate("raw-steak")
- crate("flour")
- crate("leek")
-
- cut("tomato")
- cook("raw-steak", "steak")
-
- // bread
- process("flour", "dough")
- out({ action: "instant", inputs: ["dough-foodprocessor"], outputs: ["foodprocessor", "dough"] })
- bake("dough", "bread")
- cut("bread", "bread-slice", "bread-slice")
-
- // tomato soup
- process("tomato")
- combine("pot", "leek", "tomato-juice-foodprocessor")
- cook("leek-tomato-juice-pot", "tomato-soup")
- out({ action: "instant", inputs: ["tomato-soup-pot", "plate"], outputs: ["pot", "tomato-soup-plate"] })
+const tomato = crate("tomato")
+const raw_steak = crate("raw-steak")
+const flour = crate("flour")
+const leek = crate("leek")
+const rice = crate("rice")
+const fish = crate("fish")
+const coconut = crate("coconut")
+const strawberry = crate("strawberry")
- combine("plate", "steak-pot", "sliced-tomato", "bread-slice")
+// Bread
+const dough = process(flour.tr(FP)).as("dough").tr()
+const bread = bake(dough).as("bread")
+const bread_slice = cut(bread, true).as("bread-slice")
+edible(bread)
- edible("steak-plate")
- edible("bread-slice-steak-plate")
- edible("bread-slice-sliced-tomato-plate")
- edible("bread-slice-sliced-tomato-steak-plate")
- out({ action: "demand", inputs: ["bread"], outputs: [], duration: 0 })
+// Burger
+const steak_pot = cook(raw_steak.tr(POT)).as("steak")
+const sliced_tomato = cut(tomato).as("sliced-tomato")
+const burger = combine(PL, steak_pot, sliced_tomato, bread_slice)
+const tomato_toast = combine(PL, sliced_tomato, bread_slice)
+edible(burger, tomato_toast)
- crate("rice")
- crate("fish")
- crate("coconut")
- crate("strawberry")
+// Soup
+const tomato_juice = process(tomato.tr(FP)).as("tomato-juice")
+const leek_tj_pot = combine(POT, leek, tomato_juice)
+const tomato_soup_plate = cook(leek_tj_pot).as("tomato-soup").tr(PL)
+edible(tomato_soup_plate)
- // Rice and nigiri
- cut("fish")
- cook("rice")
- out({ action: "instant", inputs: ["sliced-fish", "cooked-rice-pot"], outputs: ["nigiri", "pot"] })
+// Rice and nigiri
+const nigiri = container_add(cut(fish), cook(rice.tr(POT))).as("nigiri").tr(PL)
+edible(nigiri)
- out({ action: "instant", inputs: ["plate", "cooked-rice-pot"], outputs: ["cooked-rice-plate", "pot"] })
- edible("cooked-rice-plate")
- edible("nigiri")
+// coconut milk and strawberry puree
+const strawberry_puree = process(strawberry.tr(FP)).as("strawberry-puree")
+const milk = process(coconut.tr(FP)).as("milk")
+const strawberry_shake = either(
+ process(container_add(milk, strawberry).as("coconut-strawberry-puree")).as("strawberry-shake"),
+ process(container_add(strawberry_puree, coconut).as("milk-strawberry")).as("strawberry-shake")
+)
- // coconut milk and strawberry puree
- process("strawberry", "strawberry-puree")
- process("coconut", "milk")
- out({ action: "instant", inputs: ["milk-foodprocessor", "strawberry"], outputs: ["strawberry-milk-foodprocessor"] })
- out({ action: "instant", inputs: ["strawberry-puree-foodprocessor", "coconut"], outputs: ["strawberry-milk-foodprocessor"] })
- process("strawberry-milk-foodprocessor", "strawberrymilk")
- process("coconut-strawberry-puree-foodprocessor", "strawberrymilk")
+// Icecream
+const strawberry_icecream = freeze(strawberry_shake).as("strawberry-icecream").tr(PL)
+edible(strawberry_icecream)
- // icecream
- out({ action: "passive", inputs: ["strawberrymilk-foodprocessor"], outputs: ["strawberry-icecream-foodprocessor"], tile: "freezer", duration: 20 })
- out({ action: "instant", inputs: ["strawberry-icecream-foodprocessor", "plate"], outputs: ["foodprocessor", "strawberry-icecream-plate"] })
- edible("strawberry-icecream-plate")
+// Mochi
+const rice_flour = process(rice.tr(FP)).as("rice-flour")
+const mochi_dough = cook(rice_flour.tr(POT), 5).as("mochi-dough")
+const strawberry_mochi = container_add(strawberry, mochi_dough).as("strawberry-mochi")
+edible(strawberry_mochi)
- // drinks
- out({ action: "instant", inputs: ["glass"], outputs: ["water-glass"], tile: "sink" })
- out({ action: "instant", inputs: ["glass", "milk-foodprocessor"], outputs: ["milk-glass", "foodprocessor"] })
- out({ action: "instant", inputs: ["glass", "strawberrymilk-foodprocessor"], outputs: ["strawberrymilk-glass", "foodprocessor"] })
+// Drinks
+edible(
+ strawberry_shake.tr(GL),
+ sink_fill(GL)
+)
- edible("water-glass")
- edible("strawberrymilk-glass")
+auto_trash()
+finish()
- auto_trash()
-}