You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

249 lines
5.5 KiB

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<Supplies>} 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<MenuItemName, MenuItem>} menu
* @property {Supplies} store
* @property {{ capacity: number, used: number, queue: string[] }} oven
* @property {Record<MenuItemName, number>} 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 };