# state.ludic - the ports, the data a game hands over, the numbers it may change, and the facts # the world a price depends on. Unbound: day one, no shortage, nobody buys beyond their list. export port ShopWorld { rep: fn() -> int # the player's standing, 0 to 100 day: fn() -> int = fn shop_day_one # the game day; the demand turns with the week buy_mult: fn() -> float = fn shop_one # a shortage on everything bought also_buys: fn(int, int) -> bool = fn shop_never # (vendor, item) taken beyond the vendor's list } function shop_day_one() -> int { return 1 } function shop_one() -> float { return 1.0 } function shop_never(v: int, it: int) -> bool { return false } export port ShopPurse { money: fn() -> int spend: fn(int) -> bool earn: fn(int) -> void } export port ShopPack { count: fn(int) -> int take: fn(int, int) -> bool add: fn(int, int) -> int room: fn(int) -> int = fn shop_no_limit } function shop_no_limit(it: int) -> int { return 2147483647 } # one vendor's shelves: what it sells, what it buys, and one thing it will not take (-1: none) export property ShopVendor { stock: []int = null buys: []int = null refuses: int = -1 } export state ShopState { shop_wants_n: int = 3 shop_want_mult: float = 1.5 shop_glut_mult: float = 0.6 shop_week_days: int = 7 shop_seed: int = 1013 shop_week_rolled: int = -1 shop_want_list: []int = null # shop_wants_n per vendor, -1 empty shop_full_list: []int = null # one per vendor, -1 none shop_dice: Rng = rng_new(0) shop_taken: []int = new []int # a vendor's picks while its week is rolled, kept shop_base: []int = null # an item's base price shop_sell_frac: []float = null # what fraction of the curve a vendor pays for it shop_vendor_list: []ShopVendor = null shop_at: int = -1 # the vendor at the counter, -1 none shop_buy_new: float = 1.15 shop_buy_best: float = 0.92 shop_sell_new: float = 0.62 shop_sell_best: float = 0.85 shop_trade_q: Queue = shop_trade_q__new() } # the curve: buying from `buy_new` of base at rep 0 down to `buy_best` at 100; selling the same way # the items: a base price and a sell fraction each (raw material pays less than something made) export function shop_config_items(shop_st: mut ShopState, prices: []int, sell: []float) -> void { shop_st.shop_base = prices shop_st.shop_sell_frac = sell } export function shop_config_curve(shop_st: mut ShopState, buy_new: float, buy_best: float, sell_new: float, sell_best: float) -> void { shop_st.shop_buy_new = buy_new shop_st.shop_buy_best = buy_best shop_st.shop_sell_new = sell_new shop_st.shop_sell_best = sell_best } @alloc_ok("at start: the vendors are bound once") export function shop_clear_vendors(shop_st: mut ShopState) -> void { shop_st.shop_vendor_list = new []ShopVendor } # a vendor; its number is the order added @alloc_ok("at start: the vendors are bound once") export function shop_add_vendor(shop_st: mut ShopState, stock: []int, buys: []int, refuses: int) -> int { if shop_st.shop_vendor_list == null { shop_clear_vendors(shop_st) } let v = new ShopVendor v.stock = stock v.buys = buys v.refuses = refuses push(shop_st.shop_vendor_list, v) return len(shop_st.shop_vendor_list) - 1 } export function shop_vendors(shop_st: ShopState) -> int { if shop_st.shop_vendor_list == null { return 0 } return len(shop_st.shop_vendor_list) } export function shop_items(shop_st: ShopState) -> int { if shop_st.shop_base == null { return 0 } return len(shop_st.shop_base) } export function shop_vendor_ok(shop_st: ShopState, v: int) -> bool { return v >= 0 and v < shop_vendors(shop_st) } export function shop_item_ok(shop_st: ShopState, it: int) -> bool { return it >= 0 and it < shop_items(shop_st) } export const SHOP_BOUGHT: int = 0 export const SHOP_SOLD: int = 1 # something changed hands: `n` of `item` at `price` each export property ShopTrade { what: int = 0 vendor: int = -1 item: int = 0 n: int = 0 price: int = 0 } export function shop_trades(shop_st: ShopState) -> Queue { return shop_st.shop_trade_q } function shop_trade_q__new() -> Queue { return queue_new("shop.trades") }