diff options
Diffstat (limited to 'data/recipes')
| -rw-r--r-- | data/recipes/default.ts | 302 | 
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() -}  |