import { MenuItemState } from "./enums.js"; import { assert } from "./utils.js"; /** * @typedef {Object} SuppliesBase * @property {number} flour * @property {number} eggs * @property {number} oil * @property {number} butter * @property {number} milk * @property {number} yeast * @property {number} chocolate * @property {number} fruit * @property {number} sugar */ /** @typedef {SuppliesBase & {[key: string]: number}} Supplies */ /** * @typedef {'enabled' | 'disabled'} MenuItemStateValue */ /** * @typedef {Object} MenuItem * @property {Partial} ingredients * @property {number} oven_slots * @property {number} base_demand * @property {MenuItemStateValue} state */ /** * @typedef {'bread' | 'sweet_rolls' | 'vanilla_cake' | 'cookies' | 'fruit_muffins' | 'croissants' | 'chocolate_cookies' | 'chocolate_cake' | 'fruit_tart'} MenuItemName */ /** * @typedef {Object} GameState * @property {number} player_money * @property {{ day: number, phase: string, elapsed_ms: number, day_length_ms: number, tick_ms: number }} time * @property {Supplies} supplies * @property {Record} menu * @property {Supplies} store * @property {{ capacity: number, used: number, queue: string[] }} oven * @property {Record} prices */ /** * @typedef {Object} Command * @property {(game_state: GameState) => GameState} execute */ /** * Creates a new game state with default values * @returns {GameState} */ function init_game_state() { return { player_money: 0, time: { day: 1, phase: "planning", elapsed_ms: 0, day_length_ms: 30000, tick_ms: 250, }, supplies: { flour: 0, eggs: 0, oil: 0, butter: 0, milk: 0, yeast: 0, chocolate: 0, fruit: 0, sugar: 0, }, menu: { bread: { ingredients: { flour: 2, yeast: 1, milk: 1, }, oven_slots: 1, base_demand: 40, state: MenuItemState.ENABLED, }, sweet_rolls: { ingredients: { flour: 2, sugar: 1, butter: 1, milk: 1, }, oven_slots: 1, base_demand: 35, state: MenuItemState.ENABLED, }, vanilla_cake: { ingredients: { flour: 2, eggs: 2, sugar: 2, milk: 1, oil: 1, }, oven_slots: 2, base_demand: 25, state: MenuItemState.ENABLED, }, cookies: { ingredients: { flour: 1, eggs: 1, sugar: 1, butter: 1, }, oven_slots: 2, base_demand: 40, state: MenuItemState.ENABLED, }, fruit_muffins: { ingredients: { flour: 2, eggs: 1, sugar: 1, fruit: 1, }, oven_slots: 2, base_demand: 30, state: MenuItemState.ENABLED, }, croissants: { ingredients: { flour: 2, butter: 2, milk: 1, yeast: 1, }, oven_slots: 3, base_demand: 20, state: MenuItemState.ENABLED, }, chocolate_cookies: { ingredients: { flour: 1, eggs: 1, sugar: 1, butter: 1, chocolate: 1, }, oven_slots: 2, base_demand: 35, state: MenuItemState.ENABLED, }, chocolate_cake: { ingredients: { flour: 2, eggs: 2, sugar: 2, butter: 1, chocolate: 2, milk: 1, }, oven_slots: 3, base_demand: 12, state: MenuItemState.ENABLED, }, fruit_tart: { ingredients: { flour: 2, butter: 2, sugar: 1, eggs: 1, fruit: 2, }, oven_slots: 4, base_demand: 15, state: MenuItemState.ENABLED, }, }, store: { flour: 0.6, sugar: 0.4, yeast: 0.3, oil: 0.7, milk: 0.8, eggs: 0.9, butter: 1.2, fruit: 1.3, chocolate: 1.5, }, oven: { capacity: 4, used: 0, queue: [], }, prices: { bread: 4.0, sweet_rolls: 5.0, vanilla_cake: 9.0, cookies: 6.0, fruit_muffins: 6.5, croissants: 7.5, chocolate_cookies: 7.0, chocolate_cake: 14.0, fruit_tart: 12.0, }, }; } /** * Bakes an item if supplies and oven capacity allow * @param {GameState} game_state - The current game state * @param {MenuItemName} item_name - The name of the item to bake * @returns {GameState} The updated game state */ function bake_items(game_state, item_name) { const menu_item = game_state.menu[item_name]; const oven_slots = menu_item.oven_slots; const canFitInOven = game_state.oven.used + oven_slots <= game_state.oven.capacity; assert(canFitInOven, "oven must have capacity before baking"); assert(!!game_state, "game_state must be defined"); assert( game_state.menu[item_name].state === MenuItemState.ENABLED, "item must be bakeable with current supplies", ); // supplies update const updated_supplies = { ...game_state.supplies, }; for (const ingredient in menu_item.ingredients) { updated_supplies[ingredient] -= menu_item.ingredients[ingredient] ?? 0; } return { ...game_state, supplies: updated_supplies, oven: { ...game_state.oven, used: game_state.oven.used + oven_slots, }, }; } export { init_game_state, bake_items };