diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | data/demands.yaml | 15 | ||||
-rw-r--r-- | data/items.yaml | 78 | ||||
-rw-r--r-- | data/map.yaml | 21 | ||||
-rw-r--r-- | data/recipes.ts | 118 | ||||
-rw-r--r-- | data/tiles.yaml | 30 | ||||
-rw-r--r-- | server/src/data.rs | 19 | ||||
-rw-r--r-- | server/src/game.rs | 13 | ||||
-rw-r--r-- | test-client/tiles.ts | 23 |
9 files changed, 135 insertions, 183 deletions
@@ -2,3 +2,4 @@ .vscode/ /test-client/*.js /specs/*.html +/data/recipes.yaml diff --git a/data/demands.yaml b/data/demands.yaml index 375eeb8b..08331587 100644 --- a/data/demands.yaml +++ b/data/demands.yaml @@ -1,6 +1,9 @@ -- { from: burger-meal, to: dirty-plate, duration: 15 } -- { from: tomatoburger-meal, to: dirty-plate, duration: 20 } -- { from: tomatosteak-meal, to: dirty-plate, duration: 20 } -- { from: steak-meal, to: dirty-plate, duration: 15 } -- { from: bread-meal, to: dirty-plate, duration: 15 } -- { from: sliced-tomato-meal, to: dirty-plate, duration: 10 } +- { from: bread-plate, to: dirty-plate, duration: 10 } +- { from: steak-plate, to: dirty-plate, duration: 10 } +- { from: sliced-tomato-plate, to: dirty-plate, duration: 10 } + +- { from: bread-steak-plate, to: dirty-plate, duration: 15 } +- { from: bread-sliced-tomato-plate, to: dirty-plate, duration: 15 } +- { from: sliced-tomato-steak-plate, to: dirty-plate, duration: 15 } + +- { from: bread-sliced-tomato-steak-plate, to: dirty-plate, duration: 20 } diff --git a/data/items.yaml b/data/items.yaml deleted file mode 100644 index ddca5e11..00000000 --- a/data/items.yaml +++ /dev/null @@ -1,78 +0,0 @@ -# tomato pipeline -tomato: - traits: - - raw - expires: 5 -sliced-tomato: - traits: - - food -sliced-tomato-meal: - traits: - - meal -# bread pipeline -flour: - traits: - - raw - expires: 180 -dough: - traits: - - bakeable -bread: - traits: - - food -bread-meal: - traits: - - meal -# steak pipeline -raw-steak: - traits: - - raw - expires: 2 -steak: - traits: - - food -steak-meal: - traits: - - meal - -# combination meals -tomatosteak-meal: - traits: - - meal -burger-meal: - traits: - - meal -tomatoburger-meal: - traits: - - meal - -# containers -glass: - traits: - - container - - cup - - empty-cup -water: - traits: - - container - - cup -plate: - traits: - - container - contains: - - food - - glass -dirty-glass: - traits: - - dirty - - glass -dirty-plate: - traits: - - dirty - -# liquid -liquid-water: - traits: - - raw - - liquid - expires: 1000 diff --git a/data/map.yaml b/data/map.yaml index aa065a47..de121cc4 100644 --- a/data/map.yaml +++ b/data/map.yaml @@ -3,19 +3,19 @@ map: - "|ctc.ctc.ctc.ctc.ctc.|" - "|.....c..............|" - "|c...c...+--www---dd-+" - - "|tc.ctc..|##...CC#..D|" - - "|c...c...w........~.S|" + - "|tc.ctc..|SS...CC#..X|" + - "|c...c...w........~.R|" - "|c.......w..######..T|" - "|tc......w..........F|" - - "|c.....ct|##ss#oopp#X|" + - "|c.....ct|##ss#oo####|" - "+---dd---+-----------+" - "......................" - ".........!............" - "......................" tiles: - "~": chef-spawn - "!": customer-spawn + "~": floor + "!": floor ".": floor "+": wall "-": wall @@ -27,10 +27,17 @@ tiles: "w": window "s": sink "o": oven - "p": pan + "S": stove "C": cuttingboard - "S": raw-steak-crate + "R": raw-steak-crate "T": tomato-crate "F": flour-crate "D": dirty-plate-crate "X": trash + +chef_spawn: "~" +customer_spawn: "!" + +items: + "S": pot + "w": plate diff --git a/data/recipes.ts b/data/recipes.ts index dcd73d8e..534f1e6d 100644 --- a/data/recipes.ts +++ b/data/recipes.ts @@ -3,74 +3,102 @@ interface Recipe { tile?: string, - inputs: string[], - outputs: string[], + inputs: (string | null)[], + outputs: (string | null)[], action: "instant" | "passive" | "active" duration?: number + warn?: boolean } const all_items = new Set<string>() +function auto_trash() { + for (const ifull of all_items) { + let [i, ic] = get_container(ifull) + if (i == "plate") continue + if (i == "pot") continue + if (i == "dirty") continue + if (ic == "plate") ic = "dirty-plate" + out({ + action: "instant", + tile: "trash", + inputs: [ifull], + outputs: [ic] + }) + } +} + function out(r: Recipe) { - r.inputs.forEach(i => all_items.add(i)) - r.outputs.forEach(i => all_items.add(i)) - console.log(`- { tile: ${r.tile ?? null}, inputs: ${JSON.stringify(r.inputs)}, outputs: ${JSON.stringify(r.outputs)}, action: !${r.action + " " + (r.duration ?? "")} }`); + r.inputs.forEach(i => i ? all_items.add(i) : void 0) + r.outputs.forEach(i => i ? all_items.add(i) : void 0) + console.log(`- { tile: ${r.tile ?? null}, inputs: ${JSON.stringify(r.inputs.filter(e => e))}, outputs: ${JSON.stringify(r.outputs.filter(e => e))}, action: !${r.action + " " + (r.duration ?? "")}, warn: ${r.warn ?? false} }`); } -type Component = (e: string) => void -const cut = (new_name?: string): Component => e => { - out({ action: "active", duration: 2, tile: "cuttingboard", inputs: [e], outputs: [new_name ?? ("sliced-" + e)] }) +function cut(from: string, to?: string) { + out({ action: "active", duration: 2, tile: "cuttingboard", inputs: [from], outputs: [to ?? ("sliced-" + from)] }) } -const cook = (new_name?: string): Component => e => { - const i = e + "-pot" - const o = (new_name ?? ("cooked-" + e)) + "-pot" - out({ action: "instant", inputs: ["pot", e], outputs: [i] }) - out({ action: "passive", duration: 2, tile: "stove", inputs: [i], outputs: [o] }) +function cook(from: string, to?: string) { + const i = from + "-pot" + const o = (to ?? ("cooked-" + from)) + "-pot" + out({ action: "instant", inputs: ["pot", from], outputs: [i] }) + out({ action: "passive", duration: 10, tile: "stove", inputs: [i], outputs: [o] }) + out({ action: "passive", duration: 10, tile: "stove", inputs: [o], outputs: ["burned-pot"], warn: true }) } -const crate: Component = e => out({ action: "instant", tile: e + "-crate", inputs: [], outputs: [e], }) - -function item(name: string, ...components: Component[]) { - for (const f of components) { - f(name) - } +function bake(from: string, to?: string) { + const o = (to ?? ("cooked-" + from)) + out({ action: "passive", duration: 20, tile: "oven", inputs: [from], outputs: [o] }) + out({ action: "passive", duration: 20, tile: "oven", inputs: [o], outputs: ["burned"], warn: true }) +} +function crate(item: string) { + out({ action: "instant", tile: item + "-crate", inputs: [], outputs: [item], }) } +function get_container(ifull: string): [string, string | null] { + const iparts = ifull.split("-") + const ic = iparts.pop() + if (ic && iparts.length && ["pot", "plate"].includes(ic)) return [iparts.join("-"), ic] + return [ifull, null] +} function combine(container: string, ...inputs: string[]) { - const open = inputs.map(i => [i]) + const open = inputs.map(ifull => { + const [i, ic] = get_container(ifull) + out({ action: "instant", inputs: [container, ifull], outputs: [i + "-" + container, ic] }) + return [i] + }) + const seen = new Set<string>() while (1) { - const e = open.pop() - if (!e) break; - const cur = e.join("-") + "-" + container - for (const i of inputs) { - if (e.includes(i)) continue - const parts = [...e, i] + 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 + if (seen.has(rkey)) continue + seen.add(rkey) + + const parts = [...cur, i] parts.sort() const o = parts.join("-") + "-" + container - if (all_items.has(o)) continue open.push(parts) out({ action: "instant", - inputs: [cur, i], - outputs: [o] + inputs: [c, ifull], + outputs: [o, ic] }) } } } -item("tomato", cut(), crate, cook("tomato-soop")) -combine("plate", "steak", "sliced-tomato", "bread") +out({ action: "active", duration: 3, inputs: ["flour"], outputs: ["dough"] }) +out({ action: "active", duration: 2, tile: "sink", inputs: ["dirty-plate"], outputs: ["plate"] }) -for (const i of all_items) { - const parts = i.split("-"); - const container = parts.pop()!; - if (parts.length >= 1 && ["pot", "plate"].includes(container)) { - out({ - action: "instant", - tile: "trash", - inputs: [i], - outputs: [container] - }) - } else { - out({ action: "instant", tile: "trash", inputs: [i], outputs: [] }) - } -} +crate("tomato") +crate("raw-steak") +crate("flour") +crate("dirty-plate") +cut("tomato") +bake("dough", "bread") +cook("raw-steak", "steak") +combine("plate", "steak-pot", "sliced-tomato", "bread") +auto_trash() diff --git a/data/tiles.yaml b/data/tiles.yaml deleted file mode 100644 index 078a6f29..00000000 --- a/data/tiles.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# kitchen
-- counter
-- watercooler:
- - accepts:
- - empty-cup
-- oven:
- - accepts:
- - bakeable
-- service:
- - accepts:
- - container
-
-# supply
-- tomato-bag:
- - generates:
- - tomato
-- flour-bag:
- - generates:
- - flour
-- freezer:
- - generates:
- - steak
-- sink:
- - accepts:
- - dirty
- - cup
-
-# customers
-- table
-- chair
diff --git a/server/src/data.rs b/server/src/data.rs index fd268cb5..9c200e5b 100644 --- a/server/src/data.rs +++ b/server/src/data.rs @@ -31,7 +31,10 @@ pub struct RecipeDecl { #[derive(Debug, Clone, Deserialize)] pub struct InitialMap { map: Vec<String>, - tiles: HashMap<String, String>, + tiles: HashMap<char, String>, + items: HashMap<char, String>, + chef_spawn: char, + customer_spawn: char, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -55,7 +58,7 @@ pub struct Gamedata { pub item_names: Vec<String>, pub tile_names: Vec<String>, #[serde(skip)] - pub initial_map: HashMap<IVec2, TileIndex>, + pub initial_map: HashMap<IVec2, (TileIndex, Option<ItemIndex>)>, pub chef_spawn: Vec2, pub customer_spawn: Vec2, } @@ -121,17 +124,17 @@ pub fn build_gamedata( for (y, line) in map_in.map.iter().enumerate() { for (x, tile) in line.trim().char_indices() { let pos = IVec2::new(x as i32, y as i32); - let mut tilename = map_in.tiles[&tile.to_string()].clone(); - if tilename == "chef-spawn" { + if tile == map_in.chef_spawn { chef_spawn = pos.as_vec2(); - tilename = "floor".to_owned(); } - if tilename == "customer-spawn" { + if tile == map_in.customer_spawn { customer_spawn = pos.as_vec2(); - tilename = "floor".to_owned(); } + let tilename = map_in.tiles[&tile].clone(); + let itemname = map_in.items.get(&tile).cloned(); let tile = TileIndex(register(&tile_names, tilename)); - initial_map.insert(pos, tile); + let item = itemname.map(|i| ItemIndex(register(&item_names, i))); + initial_map.insert(pos, (tile, item)); } } diff --git a/server/src/game.rs b/server/src/game.rs index e4693e4a..973b257b 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -54,8 +54,17 @@ impl Game { players: Default::default(), tiles: Default::default(), }; - for (&p, &t) in &gamedata.initial_map { - g.tiles.insert(p, t.into()); + for (&p, (tile, item)) in &gamedata.initial_map { + g.tiles.insert( + p, + Tile { + kind: *tile, + item: item.map(|i| Item { + kind: i, + active: None, + }), + }, + ); } g } diff --git a/test-client/tiles.ts b/test-client/tiles.ts index 7db8f2a3..42fba268 100644 --- a/test-client/tiles.ts +++ b/test-client/tiles.ts @@ -92,24 +92,33 @@ const door: Component = c => { } const plate = [circle(0.4, "#b6b6b6", "#f7f7f7", 0.02)]; +const pot = [circle(0.35, "rgb(29, 29, 29)", "rgb(39, 39, 39)", 0.04)]; +const burned = [circle(0.3, "rgb(61, 18, 0)"), cross(0.2, "red", 0.02)] export const FALLBACK_ITEM: Component[] = [circle(0.3, "#f0f")]; export const ITEMS: { [key: string]: Component[] } = { + "pot": pot, "raw-steak": [circle(0.3, "#cc3705")], + "raw-steak-pot": [...pot, circle(0.3, "#cc3705")], + "steak-pot": [...pot, circle(0.3, "#702200")], + "burned-pot": [...pot, ...burned], "steak": [circle(0.3, "#702200")], "flour": [circle(0.3, "#d8c9c2")], "dough": [circle(0.3, "#b38d7d")], "bread": [circle(0.3, "#853e20")], "tomato": [circle(0.3, "#d63838")], + "burned": burned, "sliced-tomato": [circle(0.3, "#d16363", "#d63838", 0.08)], "plate": plate, "dirty-plate": [circle(0.4, "#947a6f", "#d3a187", 0.02)], - "steak-meal": [...plate, ...arrange_items("steak")], - "bread-meal": [...plate, ...arrange_items("bread")], - "burger-meal": [...plate, ...arrange_items("bread", "steak")], - "sliced-tomato-meal": [...plate, ...arrange_items("sliced-tomato")], - "tomatosteak-meal": [...plate, ...arrange_items("tomato", "steak")], - "tomatoburger-meal": [...plate, ...arrange_items("bread", "steak", "tomato")], + + "steak-plate": [...plate, ...arrange_items("steak")], + "bread-plate": [...plate, ...arrange_items("bread")], + "sliced-tomato-plate": [...plate, ...arrange_items("sliced-tomato")], + "bread-steak-plate": [...plate, ...arrange_items("bread", "steak")], + "bread-sliced-tomato-plate": [...plate, ...arrange_items("bread", "sliced-tomato")], + "sliced-tomato-steak-plate": [...plate, ...arrange_items("sliced-tomato", "steak")], + "bread-sliced-tomato-steak-plate": [...plate, ...arrange_items("bread", "sliced-tomato", "steak")], } const table = [base("rgb(133, 76, 38)")]; @@ -130,7 +139,7 @@ export const TILES: { [key: string]: Component[] } = { "trash": [...floor, circle(0.4, "rgb(20, 20, 20)"), cross(0.3, "rgb(90, 36, 36)")], "sink": [base("rgb(131, 129, 161)", "rgb(177, 174, 226)", 0.2)], "oven": [base("rgb(241, 97, 61)", "rgb(109, 84, 84)", 0.3)], - "pan": [...counter, circle(0.4, "#444", "#999")], + "stove": [...counter, circle(0.4, "#444", "#999")], "flour-crate": crate("flour"), "dirty-plate-crate": crate("dirty-plate"), "raw-steak-crate": crate("raw-steak"), |