The pack
renovationProgress
function renovationProgress():Pack<{renovationProgress:typeof kit}>
Install independent rules; no renderer or game-specific owner required.
Helpers
createRenovationProgress
function createRenovationProgress(config:RenovationConfig)
Create the economy from a catalogue. Throws on a bad id, duplicate ids, a negative or fractional price, a prerequisite that does not exist or is cyclic, or a slot whose area or kind does not exist.
Classes
RenovationProgress
class RenovationProgress
The renovation economy: credits, stored and installed products, unlocked areas and granted rewards, changed only by whole atomic baskets. Create it with createRenovationProgress.
readonly config:RenovationConfig— The catalogue it was created with (an owned copy).constructor(config:RenovationConfig)get state()— A copy of the current state; changing it changes nothing.owned(product:string,s=this.data)— Copies of a product the player has, stored plus installed.sdefaults to the live state.quote(actions:RenovationAction[]):RenovationResult— Quote and commit use the same atomic cart transition. A failed line spends nothing.transact(actions:RenovationAction[]):RenovationResult— Commit every line of the basket in order, or reject the whole basket with areasonand change nothing. A basket has 1 to 100 lines.apply(action:RenovationAction)— Commit one action as a single-line transaction.grant(reward:RenovationReward):RenovationResult— Grant a reward once. A repeatedidreturnsvalid: truewithduplicate: trueand changes nothing; a bad id, credits or items, credit overflow, storage over capacity or 100,000 receipts already held are rejected with a reason.serialize()— The save as text: the catalogueid, itsversion, the product ids it knew and the live state. The catalogue itself is not stored.restore(serialized:string):RenovationRestoreReport— Replace the live state with a save, fitted to the current catalogue. A save is refused only when it is not one of this game's: unparsable or malformed text throwsrenovation: not a save, another catalogueidor an unknown formatrenovation: incompatible save. The catalogue may have changed in any other way since the save was written, and the state is kept as far as it still makes sense: credits, receipts and revision are kept as they are; copies of removed products and removed areas are dropped; an installed product whose slot, kind or area changed or went returns to storage; starting areas, prerequisites of areas the player already had, and the starting stock of products new since the save are added. Storage over a lowered capacity is kept, and blocks buying and rewards until the player makes room. A refused or failing restore leaves the live state untouched. The report says what changed.save(storage:RenovationStorage,key=\renovation:${this.config.id}`)— Write the save to a storage adapter (anything with synchronoussetItem); storage exceptions propagate. The key defaults torenovation:`.load(storage:RenovationStorage,key=\renovation:${this.config.id}`):RenovationRestoreReport|false— Restore from a storage adapter: the restore report, orfalsewhen nothing is stored under the key. A bad save throws asRenovationProgress.restore` does.
Types
RenovationAction
type RenovationAction={type:'buy';product:string;quantity?:number}|{type:'place';product:string;slot:string}|{type:'store';slot:string}|{type:'unlock';area:string}
One line of a basket: buy copies of a product, place a stored product in a slot (any product already there returns to storage), store the product in a slot, or unlock an area.
RenovationArea
interface RenovationArea
An unlockable area. Its slots can be used only once it is unlocked.
id:string— Unique id, in the same form as a product's.cost:number— Credits to unlock it; a nonnegative safe integer.requires?:string[]— Ids of areas that must be unlocked first.needs?:string[]— Ids of products the player must own, stored or installed, to unlock it.
RenovationConfig
interface RenovationConfig
The authored catalogue. Saves are keyed on id and survive edits to everything else; see RenovationProgress.restore.
id:string— Names this game's saves. A save restores only into a catalogue with the same id; change it to start every player afresh.version?:number— Optional catalogue revision (nonnegative integer) written into saves and reported back by restore, so a host can tell which release a save came from. It never refuses a save.products:RenovationProduct[]— Everything that can be bought, stored and installed.areas:RenovationArea[]— The unlockable areas.slots:RenovationSlot[]— The places a product can be installed, each in an area and accepting one product kind.initialCredits?:number— Credits a new game starts with; default 0.initialAreas?:string[]— Areas unlocked from the start, and added to any restored save that lacks them; default none.initialInventory?:Record<string,number>— Stored copies per product a new game starts with, and given once to a restored save that predates the product; default none.inventoryCapacity?:number— Most copies the storage holds at once (installed copies do not count); default 1000.
RenovationProduct
interface RenovationProduct
Independent economy and scene-selection state. Hosts supply rewards and storage adapters.
id:string— Unique id: a letter or digit, then letters, digits,:,_or-, up to 100 characters. Saves are keyed on it.kind:string— Which slots take it: a slot accepts only products of its own kind.cost:number— Credits to buy one copy; a nonnegative safe integer.requires?:string[]— Ids of products the player must own, stored or installed, before this one can be bought.label?:string— Display name; authored metadata the rules never read.variant?:string— Variant name; authored metadata the rules never read.level?:number— Level; authored metadata the rules never read.
RenovationProgressApi
type RenovationProgressApi=typeof kit
Public independent rules and helpers exposed by the composed pack.
RenovationRestoreReport
interface RenovationRestoreReport
What RenovationProgress.restore changed so that a save made against another revision of the catalogue fits the current one.
changed:boolean— True when anything below is not empty. A save made against the same catalogue restores withchangedfalse.savedVersion?:number— Theversionthe catalogue had when the save was written, when it had one.dropped:{products:Record<string,number>;areas:string[]}— What the catalogue no longer has: copies lost per removed product (stored and installed) and removed area ids.unplaced:string[]— Saved slot ids that were emptied because the slot, its product, its kind or its area changed or went. A surviving product went back to storage.added:{areas:string[];items:Record<string,number>}— What the catalogue added: areas unlocked (starting areas, and prerequisites of areas the player already had) and starting stock given for new products.
RenovationResult
type RenovationResult={valid:true;duplicate:boolean;spent:number;state:RenovationState}|{valid:false;reason:string}
The outcome of a quote or transaction: valid: true with the credits spent, whether it was a duplicate (a reward already granted) and the resulting state, or valid: false with a reason code that names the first failure.
RenovationReward
interface RenovationReward
A reward from the host game, paid once per id.
id:string— Receipt id, in the same form as a product's: granting the same id again changes nothing.credits?:number— Credits to add; a nonnegative safe integer. Default 0.items?:Record<string,number>— Copies to add to storage, by product id; each count a whole number from 0 to 1000.
RenovationSlot
interface RenovationSlot
A place a product can be installed.
id:string— Unique id, in the same form as a product's.area:string— Id of the area it is in; it is usable only once that area is unlocked.kind:string— The product kind it accepts.
RenovationState
interface RenovationState
Everything that changes as the game is played; a save holds exactly this.
credits:number— Credits in hand; a nonnegative safe integer.inventory:Record<string,number>— Stored copies by product id; installed copies are not counted here.installed:Record<string,string>— The product id installed in each slot, by slot id; an empty slot has no entry.areas:string[]— Ids of the unlocked areas, in the order they were unlocked.receipts:string[]— Ids of the rewards already granted, so a repeat is ignored; at most 100,000.revision:number— Starts at 0 and rises by one for every committed basket and every new reward.
RenovationStorage
interface RenovationStorage
Anything with synchronous getItem and setItem, such as localStorage.
getItem(key:string):string|null— The text stored underkey, or null when there is none.setItem(key:string,value:string):void— Storevalueunderkey; may throw (a full or blocked store), and the exception propagates.


