Appearance
Cost curves
Cost curves price one or more resources from an owned count.
ts
import { costCurve, flat, geometric } from "@idlekitjs/economy/cost-curves";Lines
flat(resourceId, amount, options?) creates a fixed per-unit price.
ts
flat("currency:coins", 10);geometric(resourceId, { baseAmount, growth, round? }) creates a per-unit price that grows with the owned count.
ts
geometric("currency:coins", {
baseAmount: 100,
growth: 1.15,
round: "ceil",
});growth === 1 is linear. Invalid growth and negative amounts throw when the line or curve is created.
Curve
ts
const labCost = costCurve<State>({
getOwned: (state) => state.labsOwned,
lines: [
flat("currency:gems", 1),
geometric("currency:coins", { baseAmount: 100, growth: 1.15, round: "ceil" }),
],
});The curve exposes three methods:
| Method | Behavior |
|---|---|
costFor(state, quantity) | Total cost for quantity consecutive units |
next(state) | Cost for the next single unit |
maxAffordable(state, economy) | Largest whole quantity affordable right now |
costFor floors quantity. Non-finite or non-positive quantities return an empty cost.
maxAffordable reads spendable balances through the economy. Spendable means the resource balance minus its min.
Rounding
round is optional and belongs to each curve line:
ts
type Rounding = "none" | "floor" | "ceil" | "round";Rounding applies to each unit price before summing. This keeps the displayed unit price and the total for a bulk purchase consistent.
Rounded decreasing geometric curves (growth < 1 with per-unit rounding) throw when the curve is created.
Transaction usage
ts
const quantity = labCost.maxAffordable(state, economy);
const result = economy.execute(state, {
id: "buy:labs",
cost: labCost.costFor(state, quantity),
apply: (state) => {
state.labsOwned += quantity;
},
});The curve prices the action. The transaction settles it.