@patterkit/play-helpers 0.9.5 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/patterplay.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";var Patterplay=(()=>{var Ie=Object.defineProperty;var pn=Object.getOwnPropertyDescriptor;var un=Object.getOwnPropertyNames;var fn=Object.prototype.hasOwnProperty;var gn=(r,e)=>{for(var t in e)Ie(r,t,{get:e[t],enumerable:!0})},hn=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of un(e))!fn.call(r,s)&&s!==t&&Ie(r,s,{get:()=>e[s],enumerable:!(n=pn(e,s))||n.enumerable});return r};var mn=r=>hn(Ie({},"__esModule",{value:!0}),r);var ar={};gn(ar,{Checkpoint:()=>ue,DEFAULT_PAD_AFTER:()=>j,Engine:()=>ke,Flow:()=>_,SAVE_SCHEMA:()=>z,applyLiveBundle:()=>Ut,buildTagIndex:()=>we,compareStages:()=>W,createAudioResolver:()=>cn,createBundleInspector:()=>ln,createDebugLink:()=>_t,createPropertyInspector:()=>on,createStateLogger:()=>Ht,describeBundle:()=>Ee,deserializeState:()=>De,diffState:()=>re,effectiveGameData:()=>Bt,extensionDecls:()=>Mt,extensionSettings:()=>Tt,extensionsOf:()=>Ft,gameDataFields:()=>Lt,gameDataValue:()=>qe,getProperty:()=>$t,loadState:()=>_e,nextStage:()=>J,resolveSceneRef:()=>ve,saveState:()=>He,sceneAddressIndex:()=>Fe,serializeState:()=>Ce,setProperties:()=>Vt,setProperty:()=>jt,snapshotState:()=>We,stageIndex:()=>U});function te(r,e){return r!==void 0&&Object.prototype.hasOwnProperty.call(r,e)?r[e]:void 0}function V(r){switch(r[0]){case"b":return{kind:"bool",value:r[1]};case"n":return{kind:"number",value:r[1]};case"s":return{kind:"string",value:r[1]};case"sv":return{kind:"scopedvar",scope:r[1],name:r[2]};case"u":return{kind:"unary",op:r[1],operand:V(r[2])};case"bin":return{kind:"binary",op:r[1],left:V(r[2]),right:V(r[3])};case"call":{let e=r.slice(2).map(V);return{kind:"call",name:r[1],args:e}}case"fd":return{kind:"flagdelta",sign:r[1],name:r[2]}}}var b=class extends Error{constructor(e){super(e),this.name="EvalError"}};function ge(r,e,t){let n=new Map(t.scopes.map(i=>[i.token,i.missing??"false"])),s=i=>{switch(i.kind){case"bool":return i.value;case"number":return i.value;case"string":return i.value;case"scopedvar":{let o=te(e.scopes,i.scope);if(o===void 0)return!1;let a=typeof o.get=="function"?o.get(i.name):te(o,i.name);if(a===void 0){if(n.get(i.scope)==="throw")throw new b(`@${i.scope}.${i.name} is not declared on the current ${i.scope}.`);return!1}return a}case"call":{if(i.name==="advance"&&!te(t.functions,i.name)){let a=i.args[0];if(i.args.length!==1||a===void 0)throw new b(`advance() takes exactly 1 argument, got ${i.args.length}`);let l=Oe(a,e);if(l===void 0)throw new b("advance() needs a quality reference (@scope.name of a quality property)");let c=B(s(a),l,"advance");return l[Math.min(c+1,l.length-1)]}let o=te(t.functions,i.name);if(!o)throw new b(`unknown function '${i.name}'`);return o.eval(i.args,{evaluate:s,ctx:e})}case"flagdelta":throw new b("flagdelta node is only valid as an argument to a flag-delta function");case"unary":{if(i.op==="not"){let a=s(i.operand);if(typeof a!="boolean")throw new b(`'not' requires a boolean operand, got ${typeof a}`);return!a}let o=s(i.operand);if(typeof o!="number")throw new b(`unary '-' requires a numeric operand, got ${typeof o}`);return-o}case"binary":{if(i.op==="and"){let d=s(i.left);if(typeof d!="boolean")throw new b(`'and' requires boolean operands, left is ${typeof d}`);if(!d)return!1;let f=s(i.right);if(typeof f!="boolean")throw new b(`'and' requires boolean operands, right is ${typeof f}`);return f}if(i.op==="or"){let d=s(i.left);if(typeof d!="boolean")throw new b(`'or' requires boolean operands, left is ${typeof d}`);if(d)return!0;let f=s(i.right);if(typeof f!="boolean")throw new b(`'or' requires boolean operands, right is ${typeof f}`);return f}let o=s(i.left),a=s(i.right),l=Oe(i.left,e),c=Oe(i.right,e),p=l??c;if(p!==void 0){if(l&&c&&!yn(l,c)&&(i.op===">"||i.op===">="||i.op==="<"||i.op==="<="))throw new b(`'${i.op}' compares two different qualities, whose stage orders are unrelated`);switch(i.op){case">":return B(o,p,">")>B(a,p,">");case">=":return B(o,p,">=")>=B(a,p,">=");case"<":return B(o,p,"<")<B(a,p,"<");case"<=":return B(o,p,"<=")<=B(a,p,"<=");case"+":case"-":case"*":case"/":throw new b(`'${i.op}' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`);default:break}}switch(i.op){case"==":return Xe(o,a);case"!=":return!Xe(o,a);case">":return G(o,a,">"),o>a;case">=":return G(o,a,">="),o>=a;case"<":return G(o,a,"<"),o<a;case"<=":return G(o,a,"<="),o<=a;case"+":if(typeof o=="number"&&typeof a=="number"||typeof o=="string"&&typeof a=="string")return o+a;throw new b(`'+' requires two numbers or two strings, got ${typeof o} and ${typeof a}`);case"-":return G(o,a,"-"),o-a;case"*":return G(o,a,"*"),o*a;case"/":if(G(o,a,"/"),a===0)throw new b("division by zero");return o/a}}}};return s(r)}function Xe(r,e){if(Array.isArray(r)||Array.isArray(e)){if(!Array.isArray(r)||!Array.isArray(e)||r.length!==e.length)return!1;let t=[...r].sort(),n=[...e].sort();for(let s=0;s<t.length;s++)if(t[s]!==n[s])return!1;return!0}return r===e}function G(r,e,t){if(typeof r!="number"||typeof e!="number")throw new b(`'${t}' requires numeric operands, got ${typeof r} and ${typeof e}`)}function Oe(r,e){if(!(r.kind!=="scopedvar"||e.qualities===void 0))return e.qualities(r.scope,r.name)}function B(r,e,t){if(typeof r!="string")throw new b(`'${t}' on a quality compares stages, got ${typeof r}`);let n=e.indexOf(r);if(n<0)throw new b(`"${r}" is not a stage of this quality (stages: ${e.join(", ")})`);return n}var yn=(r,e)=>r.length===e.length&&r.every((t,n)=>t===e[n]);function ne(r){if(Number.isNaN(r)||!Number.isFinite(r))return 0;let e=Math.trunc(r)%4294967296;return e<0?e+4294967296:e}function Pe(r){let e=ne(r);return{next(){e=e+1831565813>>>0;let t=Math.imul(e^e>>>15,1|e);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296},state(){return e}}}var Ne=r=>Array.isArray(r)?r:r.stages??[],bn=r=>Array.isArray(r)?"flags":r==null?"nothing":typeof r;function U(r,e){return typeof e=="string"?Ne(r).indexOf(e):-1}function Ae(r,e){if(typeof e!="string")throw new b(`a stage is a name, got ${bn(e)}`);let t=r.indexOf(e);if(t<0)throw new b(`"${e}" is not a stage of this quality (stages: ${r.join(", ")})`);return t}function W(r,e,t){let n=Ne(r),s=Ae(n,e)-Ae(n,t);return s<0?-1:s>0?1:0}function J(r,e){let t=Ne(r);return t[Math.min(Ae(t,e)+1,t.length-1)]}function Le(r,e,t){switch(r.type){case"boolean":return typeof e=="boolean";case"number":return typeof e=="number";case"string":case"text":case"multiline":return typeof e=="string";case"enum":return typeof e!="string"?!1:e===""&&t?.noneChosen?!0:!Array.isArray(r.values)||r.values.includes(e);case"flags":return Array.isArray(e)&&e.every(n=>typeof n=="string"&&(!Array.isArray(r.values)||r.values.includes(n)));case"quality":return typeof e=="string"&&(!Array.isArray(r.stages)||r.stages.includes(e));default:return!0}}var vn={name:"check_flags",count:r=>Math.max(1,r.args.length-1)},Sn=[vn];function Ze(r,e,t){let n=t?.countingCalls??Sn;return he(r,t?.want??!0,e,n)}function he(r,e,t,n){if(r.kind==="binary"&&(r.op==="and"||r.op==="or")){let s=he(r.left,e,t,n),i=he(r.right,e,t,n);return r.op==="and"===e?s>0&&i>0?s+i:0:Math.max(s,i)}if(r.kind==="unary"&&r.op==="not")return he(r.operand,!e,t,n);if(r.kind==="call"){let s=n.find(i=>i.name===r.name);if(s){let i=s.count(r),o=t(r);return e?o?i:0:o?0:1}}return t(r)===e?1:0}function re(r,e){let t=[],n=new Set([...Object.keys(r),...Object.keys(e)]);for(let s of[...n].sort()){let i=r[s],o=e[s];JSON.stringify(i)!==JSON.stringify(o)&&t.push({path:s,from:i,to:o})}return t}var et=r=>r===void 0?"<unset>":JSON.stringify(r),tt=r=>r.pathPrefix??r.bag.pathPrefix;function Be(r,e={}){let t=e.sink??(d=>console.log(d)),n=e.label??"",s=d=>{t(`${n}${d.path}: ${et(d.from)} -> ${et(d.to)}`)},i=()=>{let d={};for(let f of r.mounts()){let g=tt(f);for(let[y,u]of Object.entries(f.bag.values))d[g+y]=u}return Object.assign(d,r.extra?.()??{}),structuredClone(d)},o=i(),a=[],l=[],c=(d,f)=>f.onAudit(g=>{let y=structuredClone({path:d+g.name,from:g.prev,to:g.next});s(y),a.push(y),o[y.path]=structuredClone(g.next)}),p=()=>{let d=r.mounts();if(!(l.length===d.length&&d.every((g,y)=>l[y].bag===g.bag))){for(let g of l)g.off();l=d.map(g=>({bag:g.bag,off:c(tt(g),g.bag)}))}};return p(),{snapshot:i,capture(){let d=i(),f=re(o,d);for(let y of f)s(y);let g=[...a,...f];return a=[],o=d,p(),g},dispose(){for(let d of l)d.off();l=[],a=[]}}}var $=class r{values=Object.create(null);decls=new Map;subscribers=new Set;auditors=new Set;norm;pathPrefix;constructor(e=[],t){this.norm=t?.normalise??(n=>n.toLowerCase()),this.pathPrefix=t?.pathPrefix??"",this.seed(e)}seed(e){for(let t of e){let n=this.norm(t.name);this.decls.set(n,t),this.values[n]=structuredClone(t.default??K(t))}}get(e){return this.values[this.norm(e)]}normalise(e){return this.norm(e)}writable(e){return this.decls.get(this.norm(e))?.writable!==!1}set(e,t,n){let s=this.norm(e);if(!n?.host&&!this.writable(s))throw new Error(`'${e}' is read-only`);let i={name:s,prev:this.values[s],next:t,silent:n?.silent??!1,reason:n?.reason};this.values[s]=t;for(let o of[...this.auditors])o(i);if(!i.silent)for(let o of[...this.subscribers])o(i);return i}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}onAudit(e){return this.auditors.add(e),()=>this.auditors.delete(e)}rows(){return[...this.decls.entries()].map(([e,t])=>rt(t,this.get(e),void 0,e,this.pathPrefix))}declarations(){return[...this.decls.values()]}clone(){let e=new r([],{normalise:this.norm,pathPrefix:this.pathPrefix});return e.decls=new Map(this.decls),Object.assign(e.values,structuredClone(this.values)),e}reseed(e){for(let t of Object.keys(this.values))delete this.values[t];this.decls.clear(),this.seed(e)}save(){return structuredClone(this.values)}load(e,t){let n=new Map;for(let[i,o]of Object.entries(e)){let a=this.norm(i);this.values[a]=structuredClone(o),n.set(a,o)}let s=[];if(!t?.refit)return s;for(let[i,o]of this.decls){if(!n.has(i))continue;let a=n.get(i);Le(o,a)||(this.values[i]=structuredClone(K(o)),s.push({name:i,value:a}))}return s}};function rt(r,e,t,n,s=""){let i=n??r.name.toLowerCase();return{name:i,path:s+i,type:r.type,value:e,default:r.default??K(r),...r.values!==void 0?{values:r.values}:{},...r.stages!==void 0?{stages:r.stages}:{},writable:t??r.writable??!0}}var xn=r=>r.toLowerCase(),Me=1,me=class{scopes=new Map;parked=new Map;parkedRefit=new Set;misfits=[];rev=0;get revision(){return this.rev}defineOwned(e,t,n){let s=typeof n=="string"?{pathPrefix:n}:n??{},i=new $(t,{pathPrefix:s.pathPrefix??`${e}.`,...s.normalise?{normalise:s.normalise}:{}});return this.mountOwned(e,i,s.owner!==void 0?{owner:s.owner}:void 0)}mountOwned(e,t,n){this.assertFree(e,n?.owner),this.scopes.set(e,{kind:"owned",bag:t,...n?.owner!==void 0?{owner:n.owner}:{}}),this.rev++;let s=this.parked.get(e);return s&&(this.note(e,t.load(s,{refit:this.parkedRefit.has(e)})),this.parked.delete(e),this.parkedRefit.delete(e)),this}remove(e,t){let n=this.scopes.get(e);if(!n)throw new Error(`unknown scope '@${e}'`);return t?.keep&&n.kind==="owned"&&(this.parked.set(e,n.bag.save()),this.parkedRefit.delete(e)),this.scopes.delete(e),this.rev++,this}discardParked(e){if(e===void 0)this.parked.clear(),this.parkedRefit.clear();else for(let t of[...this.parked.keys()])t.startsWith(e)&&(this.parked.delete(t),this.parkedRefit.delete(t));return this}takeMisfits(e){if(!e){let n=this.misfits;return this.misfits=[],n}let t=this.misfits.filter(n=>e(n.scope));return this.misfits=this.misfits.filter(n=>!e(n.scope)),t}note(e,t){for(let n of t)this.misfits.push({scope:e,name:n.name,value:n.value})}ownedBag(e){let t=this.scopes.get(e);if(!t||t.kind!=="owned")throw new Error(`'@${e}' is not an owned scope`);return t.bag}reseedOwned(e,t){return this.ownedBag(e).reseed(t),this}defineForeign(e,t,n=[],s=!0){let i=typeof s=="boolean"?{writable:s}:s;this.assertFree(e,i.owner);let o=i.normalise??xn,a=new Map;for(let l of n)a.set(o(l.name),l);return this.scopes.set(e,{kind:"foreign",resolver:t,decls:a,scopeWritable:i.writable??!0,norm:o,...i.owner!==void 0?{owner:i.owner}:{}}),this.rev++,this}has(e){return this.scopes.has(e)}get(e,t){let n=this.scopes.get(e);if(n)return n.kind==="owned"?n.bag.get(t):n.resolver.get(n.norm(t))}set(e,t,n,s){let i=this.scopes.get(e);if(!i)throw new Error(`unknown scope '@${e}'`);if(i.kind==="owned"){if(!s?.host&&!i.bag.writable(t))throw new Error(`'@${e}.${t}' is read-only`);i.bag.set(t,n,s?.host?{host:!0}:void 0);return}let o=i.norm(t);if(!i.resolver.set)throw new Error(`'@${e}.${t}' is read-only`);if(!s?.host&&!this.foreignWritable(i,o))throw new Error(`'@${e}.${t}' is read-only`);i.resolver.set(o,n)}foreignWritable(e,t){return e.resolver.set?e.decls.get(t)?.writable??e.scopeWritable:!1}listProperties(){let e=[];for(let[t,n]of this.scopes){let s=n.owner!==void 0?{owner:n.owner}:{};if(n.kind==="owned")for(let i of n.bag.rows())e.push({scope:t,...s,...i});else for(let[i,o]of n.decls)e.push({scope:t,...s,...rt(o,n.resolver.get(i),this.foreignWritable(n,i),i,`${t}.`)})}return e}toEvalContext(e,t){let n=this.view(t?.aliases),s={};for(let[o,a]of n)s[o]=a.kind==="owned"?a.bag.values:a.resolver;let i=this.qualityLadders(n);return i.size===0?{scopes:s,host:e}:{scopes:s,host:e,qualities:(o,a)=>{let l=n.get(o);return l?i.get(o)?.get(wn(l)(a)):void 0}}}view(e){let t=new Map(this.scopes);for(let[n,s]of Object.entries(e??{})){let i=this.scopes.get(s);if(!i)throw new Error(`alias '@${n}' names '${s}', which is not registered`);t.set(n,i)}return t}qualityLadders(e){let t=new Map;for(let[n,s]of e)for(let[i,o]of nt(s)){if(o.type!=="quality"||o.stages===void 0)continue;let a=t.get(n);a||(a=new Map,t.set(n,a)),a.set(i,o.stages)}return t}toSchema(e){let t=new Map;for(let[n,s]of this.view(e?.aliases)){let i=nt(s);if(i.length===0)continue;let o=new Map;for(let[a,l]of i)o.set(a,{type:l.type,enumValues:l.values,...l.stages!==void 0?{stages:l.stages}:{}});t.set(n,o)}return{properties:t}}save(){let e={};for(let[t,n]of this.scopes)n.kind==="owned"&&(e[t]=n.bag.save());for(let[t,n]of this.parked)e[t]=structuredClone(n);return e}load(e,t){t?.keepParked||(this.parked.clear(),this.parkedRefit.clear());let n=t?.refit===!0;for(let[s,i]of Object.entries(e)){let o=this.scopes.get(s);o?.kind==="owned"?this.note(s,o.bag.load(i,{refit:n})):o||(this.parked.set(s,structuredClone(i)),n?this.parkedRefit.add(s):this.parkedRefit.delete(s))}}saveFragment(){return{version:Me,scopes:this.save()}}loadFragment(e){if(e.version!==Me)throw new Error(`unsupported owned-state fragment version ${e.version} (supported: ${Me})`);this.load(e.scopes)}assertFree(e,t){let n=this.scopes.get(e);if(!n)return;let s=n.owner!==void 0?` by ${n.owner}`:"",i=t!==void 0?` (wanted by ${t})`:"";throw new Error(`scope '@${e}' is already registered${s}${i}`)}};function nt(r){return r.kind==="foreign"?[...r.decls.entries()]:r.bag.declarations().map(e=>[r.bag.normalise(e.name),e])}function wn(r){return r.kind==="foreign"?r.norm:e=>r.bag.normalise(e)}function K(r){if(r.default!==void 0)return r.default;switch(r.type){case"boolean":return!1;case"number":return 0;case"string":case"text":case"multiline":return"";case"enum":return r.values?.[0]??"";case"flags":return[];case"quality":return r.stages?.[0]??"";default:return!1}}var st=[{token:"patter",engine:"Patterplay",means:"Patter's shared globals"},{token:"story",engine:"Storylet Engine",means:"the Storylet Engine's shared @story properties"}];function se(r){return r.ctx.host??{}}var Te={defaultScope:"patter",scopes:[{token:"patter"},{token:"scene"}],functions:{random:{minArgs:2,maxArgs:2,returnType:"number",eval(r,e){if(r.length!==2)throw new b("random(a, b) requires exactly 2 arguments");let t=se(e).nextRandom;if(!t)throw new b("random() called without a PRNG in context");let n=e.evaluate(r[0]),s=e.evaluate(r[1]);if(typeof n!="number"||typeof s!="number")throw new b("random(a, b) arguments must be numbers");if(!Number.isInteger(n)||!Number.isInteger(s))throw new b("random(a, b) arguments must be integers");let i=Math.min(n,s),o=Math.max(n,s);return Math.floor(t()*(o-i+1))+i}},check_flags:{minArgs:1,returnType:"boolean",flagDeltaArgs:!0,validate:ot("check_flags"),eval(r,e){let t=it(r[0],e,"check_flags");for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new b("check_flags() flag args must be +flagName or -flagName");if(s.sign==="+"?!t.includes(s.name):t.includes(s.name))return!1}return!0}},set_flags:{minArgs:1,returnType:"flags",flagDeltaArgs:!0,validate:ot("set_flags"),eval(r,e){let t=[...it(r[0],e,"set_flags")];for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new b("set_flags() flag args must be +flagName or -flagName");if(s.sign==="+")t.includes(s.name)||t.push(s.name);else{let i=t.indexOf(s.name);i>=0&&t.splice(i,1)}}return t}},visits:{minArgs:1,maxArgs:1,returnType:"number",validate:be("visits"),eval:(r,e)=>se(e).visits?.(ye(r,e,"visits"))??0},seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:be("seen"),eval:(r,e)=>(se(e).visits?.(ye(r,e,"seen"))??0)>0},patter_visits:{minArgs:1,maxArgs:1,returnType:"number",validate:be("patter_visits"),eval:(r,e)=>se(e).patterVisits?.(ye(r,e,"patter_visits"))??0},patter_seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:be("patter_seen"),eval:(r,e)=>(se(e).patterVisits?.(ye(r,e,"patter_seen"))??0)>0}}},Fr=st.map(r=>r.token).filter(r=>r!=="patter"&&r!=="scene");function at(r,e){let t=r.replace(/^@/,"").split(".");return t.length===2&&e(t[0])?{scope:t[0],name:t[1].toLowerCase()}:{scope:"patter",name:t.join(".").toLowerCase()}}function ye(r,e,t){let n=e.evaluate(r[0]);if(typeof n!="string")throw new b(`${t}(id) requires a string node id`);return n}function be(r){return(e,t)=>{let n=e[0];n&&n.kind!=="string"&&t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(id): the argument must be a string id literal (a scene / block / node id)`})}}function it(r,e,t){if(!r)throw new b(`${t}() requires at least one argument (the flags variable)`);let n=e.evaluate(r);if(Array.isArray(n))return n;if(n===!1||n===null||n===void 0)return[];throw new b(`${t}() first argument must be a flags property`)}function ot(r){return(e,t)=>{if(e.length===0)return;let n=e[0];if(n.kind!=="scopedvar"){t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(): first argument must be a flags property reference (@name or @scope.name)`});return}let s=t.schema.properties.get(n.scope)?.get(n.name);if(s&&s.type!=="flags"){let i=n.scope===t.defaultScope?n.name:`${n.scope}.${n.name}`;t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(): '@${i}' is not a flags property (got ${s.type})`});return}for(let i=1;i<e.length;i++){let o=e[i];o.kind!=="flagdelta"?t.report({path:[...t.path,"args",i],kind:"wrong-arg-type",severity:"error",message:`${r}(): argument ${i+1} must be +flagName or -flagName`}):s?.type==="flags"&&s.enumValues&&!s.enumValues.includes(o.name)&&t.report({path:[...t.path,"args",i],kind:"unknown-flag-name",severity:"error",message:`${r}(): unknown flag '${o.name}'`,reference:o.name})}}}var kn=/^@[A-Za-z0-9_.]+$/;function*En(r){let e="",t=0;for(;t<r.length;){let n=r[t];if(n==="{"&&r[t+1]==="{"){e+="{",t+=2;continue}if(n==="}"&&r[t+1]==="}"){e+="}",t+=2;continue}if(n==="{"){let s=r.indexOf("}",t+1);if(s!==-1){let i=r.slice(t,s+1),o=r.slice(t+1,s).trim();if(o.startsWith("@")){e&&(yield{kind:"text",value:e},e=""),yield{kind:"slot",raw:i,inner:o,ref:kn.test(o)?o:void 0},t=s+1;continue}e+=i,t=s+1;continue}}e+=n,t+=1}e&&(yield{kind:"text",value:e})}function Cn(r){return Array.isArray(r)?r.join(", "):typeof r=="boolean"?r?"true":"false":String(r)}function Dn(r){return r===" "||r===" "||r===`
|
|
2
|
-
`||r==="\r"||r==="\f"||r==="\v"}function Rn(r){let e="",t=!1;for(let n of r){if(Dn(n)){t=!0;continue}t&&e.length>0&&(e+=" "),t=!1,e+=n}return e}function lt(r,e,t){if(e.length===0||r.indexOf(e)<0)return r;let n="",s=0,i=!1;for(;s<r.length;){if(r.startsWith(e,s)){let o=r.indexOf(t,s+e.length);if(o>=0){s=o+t.length,i=!0;continue}n+=r.slice(s);break}n+=r[s],s+=1}return i?Rn(n):r}function ct(r,e){if(r.indexOf("{")<0)return r;let t="";for(let n of En(r)){if(n.kind==="text"){t+=n.value;continue}if(!n.ref){t+=n.raw;continue}let s=e(n.ref);t+=s===void 0?"":Cn(s)}return t}function q(r,e){for(let t of r){e(t);let n=t.children;n&&q(n,e)}}function In(r){return r.toLowerCase().replace(/['’]/g,"").replace(/[^a-z0-9-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function E(r){let e=r.gameId?.trim();return e||In(r.name)}function Fe(r){let e=new Map;for(let[t,n]of Object.entries(r))e.set(E(n),t);return e}function ve(r,e,t){return(t??Fe(r)).get(e)??(Object.hasOwn(r,e)?e:void 0)}var j=.6;function Se(r){return`cast:${r}`}function xe(r){return`qualifier:${r}`}function dt(r,e){return`speaker:${r}:${e}`}var pt="speaker:pattern",ut="{name} ({qualifier})";function ft(r,e,t){return r.split("{name}").map(n=>n.split("{qualifier}").join(t)).join(e)}var $e={open:"[",close:"]"},gt="SFX",z="patter/save@0",ie=3;function oe(r){let e=new Set,t=[];for(let n of r)e.has(n)||(e.add(n),t.push(n));return t}function we(r){let e=new Map,t=(n,s)=>{let i=oe([...s,...n.tags??[]]);if(e.set(n.id,i),n.type==="group"&&n.prompt&&e.set(n.prompt.id,oe([...i,...n.prompt.tags??[]])),n.type==="group")for(let o of n.children)t(o,i);else for(let o of n.beats??[])e.set(o.id,oe([...i,...o.tags??[]]))};for(let n of Object.values(r.scenes)){let s=oe(n.tags??[]);e.set(n.id,s);for(let i of n.blocks){let o=oe([...s,...i.tags??[]]);e.set(i.id,o);for(let a of i.children)t(a,o)}}return e}var ht=r=>r.kind==="line"||r.kind==="text",ae=r=>typeof r=="number"&&Number.isFinite(r)?r:void 0;function mt(r){let e=new Map,t=(i,o,a)=>{let l=i.kind==="gameEvent"?void 0:ae(i.padAfter),c=l??o;a&&c<0&&(c=0),e.set(i.id,l!==void 0?{own:l,resolved:c}:{resolved:c})},n=(i,o)=>{let a=ae(i.padAfterDefault)??o;if(i.type==="group"){i.prompt&&t(i.prompt,a,!1);for(let p of i.children)n(p,a);return}let l=i.beats??[],c=-1;l.forEach((p,d)=>{ht(p)&&(c=d)}),l.forEach((p,d)=>{ht(p)&&t(p,a,d===c)})},s=ae(r.padAfterDefault)??j;for(let i of Object.values(r.scenes)){let o=ae(i.padAfterDefault)??s;for(let a of i.blocks){let l=ae(a.padAfterDefault)??o;for(let c of a.children)n(c,l)}}return e}var yt=new WeakMap,bt=new WeakMap;function On(r){let e=bt.get(r);return e||(e=we(r),bt.set(r,e)),e}var vt=new WeakMap;function Pn(r){let e=vt.get(r);return e||(e=mt(r),vt.set(r,e)),e}var St=new WeakMap;function An(r){let e=St.get(r);if(e)return e;e=new Map;for(let t of Object.values(r.scenes))for(let n of t.blocks)q(n.children,s=>{if(s.type==="group"){s.prompt&&e.set(s.prompt.id,s.prompt);return}for(let i of s.beats??[])e.set(i.id,i)});return St.set(r,e),e}function H(r,e){return r.tagIndex.get(e)?.slice()}var de="Patter",le=r=>r.replace(/%/g,"%25").replace(/\//g,"%2F"),Nn=r=>r.replace(/%2F/g,"/").replace(/%25/g,"%"),xt=Symbol("ownsRegistry"),P={stage:r=>`patter/scene/${le(r)}`,flow:r=>`patter/flow/${le(r)}/`,flowGlobals:r=>`patter/flow/${le(r)}/patter`,flowScene:(r,e)=>`patter/flow/${le(r)}/scene/${le(e)}`},ue=class{constructor(e){this.journal=e}journal},ke=class r{host;defaultSeed;flowsById=new Map;allStrings;currentLocale;sourceDebug;sceneGameIdToId=new Map;blockGameIdToId=new Map;creationOptions;engineLog=[];engineSeq=0;engineTraceHandlers=new Set;constructor(e,t={}){this.creationOptions=t;let n=t.locale??e.locales.default,s=e.strings;this.allStrings=s,this.currentLocale=n;let i=s[n]??{},o=s[e.locales.default]??{},a=e.localisation,l=a?.mode==="ids"&&!a.sourceDebug;this.sourceDebug=a?.mode==="ids"&&!!a.sourceDebug,this.sourceDebug&&typeof console<"u"&&console.warn("[Patterplay] source-only DEBUG build: strings are the source language for debugging, not a shippable localised build.");let c=new Map;for(let m of e.cast??[])m.displayName&&c.set(m.name,m.displayName);let p=new Map;for(let m of e.qualifiers??[])m?.gameId&&p.set(m.gameId,m.name);let d=new Map;for(let m of e.cast??[])for(let[S,O]of Object.entries(m.qualifierLabels??{}))typeof O=="string"&&d.set(`${m.name}\0${S}`,O);let f=e.speakerPattern??ut;this.defaultSeed=(t.seed??2654435769)>>>0;let g=new Map,y=new Map,u=new Map;for(let[m,S]of Object.entries(e.scenes)){this.sceneGameIdToId.set(E(S),m);let O=new Map;for(let D of S.blocks)y.set(D.id,{sceneId:m}),u.set(D.id,D),O.set(E(D),D.id),q(D.children,fe=>g.set(fe.id,fe));this.blockGameIdToId.set(m,O)}let w=e.properties??[],I=w.filter(m=>m.shared??!0).map(Ct),R=w.filter(m=>!(m.shared??!0)).map(Ct),N=new Set(I.map(m=>m.name.toLowerCase())),k=t.registry??new me,L=!t.registry||t[xt]===!0,T=new $(I,{pathPrefix:"@patter."}),F=[],h=[];try{k.mountOwned("patter",T,{owner:de}),h.push("patter");let m=new Set;for(let[S,O]of Object.entries(Dt(t))){let D=e.scopeRegistry?.scopes.find(dn=>dn.token===S),fe=(D?.declarations??[]).map(Pt);k.defineForeign(S,O,fe,{writable:D?.writable??!0,owner:de}),h.push(S),m.add(S)}for(let S of L?e.scopeRegistry?.scopes??[]:[]){if(m.has(S.token)||k.has(S.token))continue;let O=(S.declarations??[]).map(D=>Mn(D,S.writable));k.defineOwned(S.token,O,{owner:de}),h.push(S.token),F.push(S.token)}}catch(m){for(let S of h)k.remove(S,{keep:!0});throw m}let C=new Map;for(let[m,S]of Object.entries(e.scenes)){let O=new Set((S.sceneProps??[]).filter(D=>D.shared??!1).map(D=>D.name.toLowerCase()));C.set(m,O)}this.host={logEnabled:t.log??!1,tracing:t.log??!1,emitEngine:(m,S,O)=>this.emitEngine(m,S,O),bundle:e,emitIds:l,strings:i,defaultStrings:o,castDisplay:c,qualifierDisplay:p,speakerLabels:d,speakerPattern:f,nodeIndex:g,blockIndex:y,blockById:u,sceneGameIdToId:this.sceneGameIdToId,blockGameIdToId:this.blockGameIdToId,tagIndex:On(e),padIndex:Pn(e),registry:k,ownsRegistry:L,patterBag:T,hostScopes:F,patterSharedDecls:I,patterLocalDecls:R,patterSharedNames:N,sceneSharedNames:C,sharedVisits:new Map,qualityLadders:new Map,sharedSelectors:new Map,stageBags:new Map,journal:null,customRng:t.rng,onDryChoice:t.onDryChoice,onError:t.onError??(m=>console.warn(`Patterplay: ${m.kind} on ${m.node} in flow '${m.flow}' failed, played through: ${m.message}`)),reportRefits:()=>{let m=k.takeMisfits(S=>S==="patter"||S.startsWith("patter/")||F.includes(S));if(m.length!==0)if(t.onRefit)t.onRefit(m);else for(let S of m)console.warn(`Patterplay: the save's ${S.scope}.${S.name} was ${JSON.stringify(S.value)}, which no longer fits its declaration; it is back at its default`)},replayPromptOnChoose:t.replayPromptOnChoose??!1,captionsOn:t.closedCaptions??!0,captionOpen:(e.closedCaptions??$e).open,captionClose:(e.closedCaptions??$e).close,captionCharacter:e.closedCaptions?.character||gt,refSplitCache:new Map,refSplitRevision:k.revision},this.host.reportRefits()}get locale(){return this.currentLocale}get isSourceDebug(){return this.sourceDebug}get buildId(){return this.host.bundle.content?.hash??""}setLocale(e){this.currentLocale=e,this.host.strings=this.allStrings[e]??{}}replaceStrings(e){this.allStrings=e.strings,this.host.strings=this.allStrings[this.currentLocale]??{},this.host.defaultStrings=this.allStrings[this.host.bundle.locales.default]??{}}hotSwap(e){this.refuseInCheckpoint("hotSwap");let t=this.saveGame(),n=l=>(l.setLocale(this.currentLocale),l.setClosedCaptions(this.host.captionsOn),l),s=()=>new r(e,{...this.creationOptions,registry:this.host.registry,[xt]:this.host.ownsRegistry}),i=new Set(["patter",...this.host.hostScopes]),o=this.host.ownsRegistry?void 0:Object.fromEntries(Object.entries(this.host.registry.save()).filter(([l])=>i.has(l)||l.startsWith("patter/")));this.release(!0),o&&this.host.registry.load(o,{keepParked:!0,refit:!0});let a=s();try{return a.loadGame(t),n(a)}catch{a.release(!0);let l=this.host.ownsRegistry?t.registry:o;l&&this.host.registry.load(l,{keepParked:!0,refit:!0});let c=s();for(let[p,d]of Object.entries(t.flows)){let f=d.cursor.currentSceneId;try{c.openFlow(p,f!==null?{scene:f}:{})}catch{}}return n(c)}}get closedCaptions(){return this.host.captionsOn}setClosedCaptions(e){this.host.captionsOn=e}openFlow(e,t={}){this.assertExternalScopes();let{sceneId:n,blockId:s}=this.resolveOpenAddress(t.scene,t.block),i=this.flowsById.get(e),o=this.host.journal;if(o&&i&&!i.isClosed)throw new Error(`openFlow would replace the open flow '${e}', which can't be undone while a checkpoint is open`);i?.close();let a=new _(e,this.host,t.seed??this.defaultSeed);return o&&(o.flows.add(a),o.opened.add(a),o.undo.push(()=>{a.close(),i?this.flowsById.set(e,i):this.flowsById.delete(e)})),this.flowsById.set(e,a),a.begin(n,s),a}runFlow(e,t,n){let s=this.flowsById.get(e);if(!s)return this.openFlow(e,{scene:t,block:n}).advanceToStop().played;if(!s.goto(t,n))throw new Error(`runFlow: address not found: ${t}${n===void 0?"":` / ${n}`}`);return s.advanceToStop().played}assertExternalScopes(){for(let e of this.host.bundle.externalScopes??[])if(!this.host.registry.has(e))throw new Error(`this content names @${e}, which no engine on this registry registered: give every engine the game's one registry`)}resolveOpenAddress(e,t){if(e!==void 0){let n=je(this.host,e);if(n===void 0)throw new Error(`unknown scene: ${e}`);if(t===void 0)return{sceneId:n};let s=Ve(this.host,n,t);if(s===void 0)throw new Error(`unknown block: ${t}`);return{sceneId:n,blockId:s}}if(t!==void 0){if(!this.host.blockIndex.has(t))throw new Error(`unknown block: ${t}`);return{blockId:t}}if(Object.keys(this.host.bundle.scenes).length===0)throw new Error("no scenes in bundle");return{}}resolveSceneRef(e){if(e!=null)return je(this.host,e)??e}resolveBlockRef(e,t){if(t!=null)return e==null?t:Ve(this.host,e,t)}sceneAddress(e){let t=this.host.bundle.scenes[e];return t?E(t):void 0}blockAddress(e){let t=this.host.blockById.get(e);return t?E(t):void 0}tagsForBeat(e){return H(this.host,e)??[]}tagsForScene(e){let t=this.resolveSceneRef(e);return(t!=null?H(this.host,t):void 0)??[]}tagsForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t);return(s!=null?H(this.host,s):void 0)??[]}gameDataForScene(e){let t=this.resolveSceneRef(e);return{...(t!=null?this.host.bundle.scenes[t]:void 0)?.gameData}}gameDataForBlock(e,t){let n=this.resolveBlockRef(this.resolveSceneRef(e),t);return{...(n!=null?this.host.blockById.get(n):void 0)?.gameData}}extensionsForScene(e){let t=this.resolveSceneRef(e);return{...(t!=null?this.host.bundle.scenes[t]:void 0)?.extensions}}extensionsForBlock(e,t){let n=this.resolveBlockRef(this.resolveSceneRef(e),t);return{...(n!=null?this.host.blockById.get(n):void 0)?.extensions}}extensionsForSnippet(e){let t=this.host.nodeIndex.get(e);return t?.type==="snippet"?{...t.extensions}:{}}getCast(){let e=[];for(let t of this.host.bundle.cast??[])t?.name&&e.push(t.name);return e}castForScene(e){let t=this.resolveSceneRef(e),n=t!=null?this.host.bundle.scenes[t]:void 0;if(!n)return[];let s=new Set;for(let i of n.blocks)wt(i.children,s);return[...s]}castForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t),i=s!=null?this.host.blockById.get(s):void 0;if(!i)return[];let o=new Set;return wt(i.children,o),[...o]}getOutline(){return Object.values(this.host.bundle.scenes).map(e=>({id:e.id,...E(e)?{gameId:E(e)}:{},name:e.name,...kt(e.gameData),...M(e.extensions),...this.tagsField(e.id),blocks:e.blocks.map(t=>({id:t.id,...E(t)?{gameId:E(t)}:{},name:t.name,...kt(t.gameData),...M(t.extensions),...this.tagsField(t.id),children:t.children.map(n=>this.outlineNode(n))}))}))}getBeatSequence(){let e=[];for(let t of Object.values(this.host.bundle.scenes))for(let n of t.blocks)q(n.children,s=>{if(s.type==="snippet")for(let i of s.beats??[])e.push({sceneId:t.id,blockId:n.id,snippetId:s.id,beat:this.beatInfo(i)})});return e}outlineNode(e){return e.type==="group"?{type:"group",id:e.id,...this.tagsField(e.id),...e.selector?{selector:e.selector}:{},...e.prompt?{prompt:this.beatInfo(e.prompt)}:{},children:e.children.map(t=>this.outlineNode(t))}:{type:"snippet",id:e.id,...this.tagsField(e.id),beats:(e.beats??[]).map(t=>this.beatInfo(t)),...e.jump?{jumpTo:e.jump.to,...e.jump.mode?{jumpMode:e.jump.mode}:{}}:{}}}beatInfo(e){let t=H(this.host,e.id),n={id:e.id,kind:e.kind};if(e.kind==="line"){if(e.character!==void 0){n.character=e.character;let i=this.host.defaultStrings[Se(e.character)]??this.host.castDisplay.get(e.character);i!==void 0&&(n.characterName=i)}if(e.direction!==void 0&&(n.direction=e.direction),e.qualifier!==void 0){n.qualifier=e.qualifier;let i=this.host.defaultStrings[xe(e.qualifier)]??this.host.qualifierDisplay.get(e.qualifier);i!==void 0&&(n.qualifierName=i)}let s=ce(this.host,e.character,e.qualifier,!0);s!==void 0&&(n.speakerLabel=s)}if(e.kind==="line"||e.kind==="text"){let s=this.host.padIndex.get(e.id);n.padAfter=s?.resolved??j,s?.own!==void 0&&(n.ownPadAfter=s.own);let i=this.host.defaultStrings[e.id];i!==void 0&&(n.text=i)}return e.gameData&&Object.keys(e.gameData).length&&(n.gameData=e.gameData),e.extensions&&Object.keys(e.extensions).length&&(n.extensions=e.extensions),t&&t.length&&(n.tags=t),n}tagsField(e){let t=H(this.host,e);return t&&t.length?{tags:t}:{}}getFlow(e){return this.flowsById.get(e)}flows(){return[...this.flowsById.values()]}listBags(){let e=[{bag:this.host.patterBag}];for(let[t,n]of this.host.stageBags)e.push({bag:n,pathPrefix:`@scene:${t}.`});return e}checkpoint(){if(this.host.journal)throw new Error("a checkpoint is already open: roll it back or commit it first");let e={undo:[],flows:new Set,opened:new Set,selectors:new Set,flowSelectors:new Map};return this.host.journal=e,new ue(e)}rollback(e){this.endCheckpoint(e);let t=e.journal.undo;for(let n=t.length-1;n>=0;n--)t[n]();r.forget(e.journal)}commit(e){this.endCheckpoint(e),r.forget(e.journal)}get inCheckpoint(){return this.host.journal!==null}endCheckpoint(e){if(this.host.journal!==e.journal)throw new Error("that checkpoint is not the open one");this.host.journal=null}static forget(e){e.undo=[],e.flows.clear(),e.opened.clear(),e.selectors.clear(),e.flowSelectors.clear()}refuseInCheckpoint(e){if(this.host.journal)throw new Error(`${e} can't be undone, so it isn't allowed while a checkpoint is open`)}captureFlow(e){let t=this.flowsById.get(e);if(!t)throw new Error(`no open flow '${e}' to capture`);return{version:ie,...t.snapshot(),...Fn(e,this.host.registry.save())}}restoreFlow(e,t){this.refuseInCheckpoint("restoreFlow");let n=t.version;if(n!==2&&n!==ie)throw new Error(`unsupported flow state version: ${String(n)}`);let s=t.cursor;if(typeof s!="object"||s===null)throw new Error("malformed flow state: no cursor");if(this.flowsById.has(e))throw new Error(`a flow '${e}' is already open; close it before restoring another under that id`);this.assertExternalScopes();let i=P.flow(e);this.host.registry.discardParked(i),this.host.registry.load(Nt(e,t),{keepParked:!0,refit:!0});let o=new _(e,this.host,this.defaultSeed);try{o.restore(t)}catch(a){throw o.close(),this.host.registry.discardParked(i),a}return this.flowsById.set(e,o),this.host.reportRefits(),o}closeFlow(e){this.refuseInCheckpoint("closeFlow"),this.flowsById.get(e)?.close(),this.flowsById.delete(e)}reset(){this.refuseInCheckpoint("reset");for(let e of this.flowsById.values())e.close();this.flowsById.clear(),this.host.patterBag.reseed(this.host.patterSharedDecls),this.host.sharedVisits.clear(),this.host.sharedSelectors.clear();for(let e of this.host.stageBags.keys())this.host.registry.remove(P.stage(e));this.host.stageBags.clear(),this.host.registry.discardParked("patter/")}release(e){for(let n of this.flowsById.values())n.releaseBags(e),n.close();this.flowsById.clear();let t=this.host.registry;for(let n of this.host.stageBags.keys())t.remove(P.stage(n),{keep:e});this.host.stageBags.clear();for(let n of["patter",...this.host.hostScopes])t.has(n)&&t.remove(n,{keep:e});for(let n of Object.keys(Dt(this.creationOptions)))t.has(n)&&t.remove(n)}getProperty(e){let{scope:t,name:n}=this.splitShared(e);return this.host.registry.get(t,n)}setProperty(e,t){let{scope:n,name:s}=this.splitShared(e),i=this.host.journal?this.host.registry.get(n,s):void 0;this.host.registry.set(n,s,t,{host:!0}),this.host.journal&&i!==void 0&&this.host.journal.undo.push(()=>this.host.registry.set(n,s,i,{host:!0}))}stageIndex(e,t){return U(this.ladderOf(e),t)}compareStages(e,t,n){return W(this.ladderOf(e),t,n)}nextStage(e,t){return J(this.ladderOf(e),t)}ladderOf(e){let{scope:t,name:n}=this.splitShared(e),s=Bn(this.host,t,n);if(!s)throw new Error(`'${e}' is not a quality`);return s}log(){return this.engineLog}clearLog(){this.engineLog.length=0}onTrace(e){return this.engineTraceHandlers.add(e),this.host.tracing=!0,()=>{this.engineTraceHandlers.delete(e),this.host.tracing=this.host.logEnabled||this.engineTraceHandlers.size>0}}emitEngine(e,t,n){for(let s of this.engineTraceHandlers)s(e,t);this.host.logEnabled&&this.engineLog.push({...t,flow:e,seq:this.engineSeq++,...n?{scene:n}:{}})}getVisitCounts(){return Object.fromEntries(this.host.sharedVisits)}listProperties(){return this.host.patterSharedDecls.map(e=>({name:e.name,path:`@patter.${e.name}`,type:e.type,values:e.values,stages:e.stages,value:this.getProperty(`@${e.name}`),default:K(e),writable:e.writable??!0}))}splitShared(e){let t=At(this.host,e);if(t.scope==="scene")throw new Error(`'${e}': @scene properties are scene-scoped - read/write them on a Flow, not the Engine`);return t}save(){return{patter:this.host.patterBag.save()}}load(e){e.patter&&this.host.patterBag.load(e.patter)}saveGame(){let e={};for(let[t,n]of this.flowsById)e[t]=n.snapshot();return{version:ie,...this.host.ownsRegistry?{registry:this.host.registry.save()}:{},sharedVisits:Object.fromEntries(this.host.sharedVisits),sharedSelectors:It(this.host.sharedSelectors),flows:e}}loadGame(e){this.refuseInCheckpoint("loadGame");let t=e.version;if(t!==2&&t!==ie)throw new Error(`unsupported save version: ${String(t)}`);let n=e.flows;if(typeof n!="object"||n===null||Array.isArray(n))throw new Error("malformed save: no flows");this.assertExternalScopes();let s=this.host.registry;for(let[o,a]of this.flowsById)a.releaseBags(o in e.flows),a.close();this.flowsById.clear();for(let o of this.host.stageBags.keys())s.remove(P.stage(o),{keep:!0});this.host.stageBags.clear();let i=e.version===2?Tn(e):e.registry;i&&(this.host.ownsRegistry?s.load(i,{refit:!0}):s.load(i,{keepParked:!0,refit:!0})),this.host.sharedVisits.clear();for(let[o,a]of Object.entries(e.sharedVisits??{}))this.host.sharedVisits.set(o,a);this.host.sharedSelectors.clear();for(let[o,a]of Ot(e.sharedSelectors))this.host.sharedSelectors.set(o,a);for(let[o,a]of Object.entries(e.flows)){let l=new _(o,this.host,this.defaultSeed);l.restore(a),this.flowsById.set(o,l)}this.host.reportRefits()}},_=class{id;host;local;registered=new Set;rngState;started=!1;flowEnded=!1;closed=!1;currentSceneId=null;stack=[];activeSnippet=null;beatIndex=0;pendingChoice=null;pendingPrompt=null;pendingPromptOwnerId=null;selectors=new Map;visitCounts=new Map;sceneBags=new Map;patterResolver={get:e=>this.host.patterSharedNames.has(e)?this.host.patterBag.get(e):this.local.get(e),set:(e,t)=>{this.host.patterSharedNames.has(e)?this.host.registry.set("patter",e,t):this.local.set(e,t)}};sceneResolver={get:e=>{let t=this.currentSceneId;if(t!==null)return this.sceneBagFor(t,e)?.get(e)},set:(e,t)=>{let n=this.currentSceneId;if(n===null)return;let s=this.sceneBagFor(n,e);s&&s.set(e,t)}};evalCtx;ctxRevision=-1;registryQualities;flowLog=[];flowSeq=0;constructor(e,t,n){this.id=e,this.host=t,this.rngState=ne(n),this.local=this.newLocal(),this.evalCtx={scopes:{},host:{nextRandom:this.rng,visits:s=>this.visitCounts.get(s)??0,patterVisits:s=>this.host.sharedVisits.get(s)??0},qualities:(s,i)=>this.stagesFor(s,i)}}context(){let e=this.host.registry;if(e.revision!==this.ctxRevision){let t=e.toEvalContext(),n=this.evalCtx.scopes;for(let s of Object.keys(n))delete n[s];Object.assign(n,t.scopes),n.patter=this.patterResolver,n.scene=this.sceneResolver,this.registryQualities=t.qualities,this.ctxRevision=e.revision}return this.evalCtx}stagesFor(e,t){let n=t.toLowerCase();if(e==="patter")return pe(this.host,"patter",()=>[...this.host.patterSharedDecls,...this.host.patterLocalDecls]).get(n);if(e==="scene"){let s=this.currentSceneId;return s==null?void 0:pe(this.host,`scene/${s}`,()=>this.host.bundle.scenes[s]?.sceneProps).get(n)}return this.registryQualities?.(e,t)??pe(this.host,`host/${e}`,()=>this.host.bundle.scopeRegistry?.scopes.find(s=>s.token===e)?.declarations).get(n)}begin(e,t){if(this.host.journal&&!this.host.journal.opened.has(this))throw new Error("a flow can't be started or reset while a checkpoint is open");if(this.releaseBags(!1),this.host.registry.discardParked(P.flow(this.id)),this.mountLocal(),this.selectors.clear(),this.visitCounts.clear(),this.stack=[],this.currentSceneId=null,this.flowEnded=!1,this.activeSnippet=null,this.beatIndex=0,this.clearPending(),this.started=!0,t){let n=this.host.blockIndex.get(t);if(!n)throw new Error(`unknown block: ${t}`);this.enterSceneSetup(n.sceneId),this.stack=[{sceneId:n.sceneId,containerId:t,index:0}],this.enter(t)}else{let n=e??Object.keys(this.host.bundle.scenes)[0],s=n?this.host.bundle.scenes[n]:void 0;if(!s)throw new Error(n?`unknown scene: ${n}`:"no scenes in bundle");this.enterSceneSetup(n);let i=s.blocks[0];i&&(this.stack=[{sceneId:n,containerId:i.id,index:0}],this.enter(i.id))}this.settle()}reset(e,t){this.begin(e,t)}start(e,t){this.reset(e,t)}goto(e,t){if(this.closed)return!1;if(this.touch(),e==="END")return this.started=!0,this.clearPending(),this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!0,this.stack=[],!0;let n=je(this.host,e);if(n===void 0)return!1;let s;return t!==void 0&&(s=Ve(this.host,n,t),s===void 0)?!1:this.started?(this.clearPending(),this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!1,this.enterTarget(s??n,"jump"),this.settle(),!0):(this.begin(n,s),!0)}close(){this.releaseBags(!1),this.closed=!0,this.flowEnded=!0,this.stack=[],this.activeSnippet=null,this.beatIndex=0,this.clearPending()}clearPending(){this.pendingChoice=null,this.pendingPrompt=null,this.pendingPromptOwnerId=null}touch(){let e=this.host.journal;if(!e||e.flows.has(this))return;e.flows.add(this);let{rngState:t,started:n,flowEnded:s,currentSceneId:i,activeSnippet:o,beatIndex:a,pendingChoice:l,pendingPrompt:c,pendingPromptOwnerId:p}=this,d=this.stack.map(f=>({...f}));e.undo.push(()=>{Object.assign(this,{rngState:t,started:n,flowEnded:s,currentSceneId:i,activeSnippet:o,beatIndex:a,pendingChoice:l,pendingPrompt:c,pendingPromptOwnerId:p,stack:d})})}get isClosed(){return this.closed}get currentScene(){return this.currentSceneId}advance(){if(this.closed)return{type:"end"};if(!this.started)throw new Error("flow has not been started");if(this.touch(),this.pendingPrompt){let e=this.pendingPrompt;return this.pendingPrompt=null,this.pendingPromptOwnerId=null,e.shown?this.promptResult(e.beat,e.shown):this.beatResult(e.beat)}return this.settle(),this.flowEnded?{type:"end"}:this.pendingChoice?{type:"choice",groupId:this.pendingChoice.groupId,options:this.pendingChoice.options}:this.activeSnippet?this.beatResult(this.activeSnippet.beats[this.beatIndex++]):(this.flowEnded=!0,{type:"end"})}advanceToStop(){let e=[];for(;;){let t=this.advance();if(t.type==="choice"||t.type==="end")return{played:e,stop:t};e.push(t)}}settle(){let e=0;for(;;){if(++e>1e4)throw new Error("flow did not settle after 10000 transitions - likely a jump cycle with no deliverable content");if(this.flowEnded||this.pendingChoice)return;if(this.activeSnippet){if(this.beatIndex<(this.activeSnippet.beats?.length??0))return;this.runEffects(this.activeSnippet.onExit,this.activeSnippet.id);let i=this.activeSnippet.jump;this.activeSnippet=null,this.beatIndex=0,this.resolveJump(i);continue}let t=this.stack[this.stack.length-1];if(!t){this.flowEnded=!0;return}t.sceneId!==this.currentSceneId&&(this.currentSceneId=t.sceneId);let n=this.childrenOf(t.containerId);if(!n){this.stack.pop();continue}let s=t.index;for(;t.index<n.length&&!this.eligible(n[t.index]);)t.index++;if(this.host.tracing&&t.index!==s&&this.emit({type:"select",group:t.containerId,selector:"run",children:n.slice(s,t.index+1).map((i,o)=>({id:i.id,eligible:s+o===t.index})),picked:n[t.index]?.id??null}),t.index>=n.length){this.stack.pop();continue}this.enterChild(n[t.index++])}}listBags(){let e=[{bag:this.local,pathPrefix:`${this.id}/@patter.`}];for(let[t,n]of this.sceneBags)e.push({bag:n,pathPrefix:`${this.id}/@scene:${t}.`});return e}log(){return this.flowLog}clearLog(){this.flowLog.length=0}emit(e){let t=this.currentSceneId??void 0;this.host.emitEngine(this.id,e,t),this.host.logEnabled&&this.flowLog.push({...e,seq:this.flowSeq++,...t?{scene:t}:{}})}getVisitCounts(){return Object.fromEntries(this.visitCounts)}stepFor(e){let t=An(this.host.bundle).get(e);return t?this.beatResult(t):void 0}getChoices(){return this.pendingChoice?.options??[]}choose(e){let t=this.pendingChoice;if(!t)throw new Error("no choice is pending");let n=t.options.find(o=>o.id===e);if(!n)throw new Error(`unknown choice option: ${e}`);if(!n.eligible)throw new Error(`choice option is not eligible: ${e}`);this.touch();let s=t.byId.get(e);this.host.tracing&&this.emit({type:"chose",group:t.groupId,option:e}),this.pendingChoice=null;let i=this.host.replayPromptOnChoose?this.authoredPromptOf(s):void 0;this.pendingPrompt=i&&n.prompt?{beat:i,shown:{...n.prompt}}:null,this.pendingPromptOwnerId=this.pendingPrompt?s.id:null,this.enterChild(s)}isEnded(){return this.flowEnded}getProperty(e){let{scope:t,name:n}=this.splitRef(e);return t==="patter"?this.patterResolver.get(n):t==="scene"?this.sceneResolver.get(n):this.host.registry.get(t,n)}setProperty(e,t){this.writeProperty(e,t,!0)}stageIndex(e,t){return U(this.ladderOf(e),t)}compareStages(e,t,n){return W(this.ladderOf(e),t,n)}nextStage(e,t){return J(this.ladderOf(e),t)}ladderOf(e){let{scope:t,name:n}=this.splitRef(e);this.context();let s=this.stagesFor(t,n);if(!s)throw new Error(`'${e}' is not a quality`);return s}writeProperty(e,t,n){let{scope:s,name:i}=this.splitRef(e),o=this.host.journal;if(s==="patter"){if(o){let a=this.host.patterSharedNames.has(i),l=a?this.host.patterBag.get(i):this.local.get(i),c=this.local;l!==void 0&&o.undo.push(a?()=>this.host.registry.set("patter",i,l):()=>c.set(i,l))}this.patterResolver.set(i,t)}else if(s==="scene"){if(this.currentSceneId===null)throw new Error(`'${e}': the flow has not entered a scene yet`);if(o){let a=this.sceneBagFor(this.currentSceneId,i),l=a?.get(i);a&&l!==void 0&&o.undo.push(()=>a.set(i,l))}this.sceneResolver.set(i,t)}else{let a=o?this.host.registry.get(s,i):void 0;this.host.registry.set(s,i,t,n?{host:!0}:void 0),o&&a!==void 0&&o.undo.push(()=>this.host.registry.set(s,i,a,{host:!0}))}}snapshot(){return{rngState:this.rngState,visits:Object.fromEntries(this.visitCounts),cursor:{flowEnded:this.flowEnded,currentSceneId:this.currentSceneId,stack:this.stack.map(e=>{let t=this.childrenOf(e.containerId)?.[e.index];return t?{...e,nextId:t.id}:{...e}}),activeSnippetId:this.activeSnippet?.id??null,beatIndex:this.beatIndex,pendingChoice:this.pendingChoice?{groupId:this.pendingChoice.groupId,options:this.pendingChoice.options.map(({extensions:e,...t})=>({...t}))}:null,pendingPromptOwnerId:this.pendingPromptOwnerId,...this.pendingPrompt?.shown?{pendingPrompt:Ln(this.pendingPrompt.shown)}:{},selectors:It(this.selectors)}}}restore(e){if(this.host.journal)throw new Error("a flow can't be restored while a checkpoint is open");this.restoreCursor(e),this.releaseBags(!0),this.mountLocal();for(let t of new Set([this.currentSceneId,...this.stack.map(n=>n.sceneId)]))t!==null&&this.host.bundle.scenes[t]&&this.ensureSceneBags(t)}restoreCursor(e){this.rngState=ne(e.rngState),this.visitCounts=new Map(Object.entries(e.visits??{}));let t=e.cursor;if(this.started=!0,this.flowEnded=t.flowEnded,this.beatIndex=t.beatIndex,this.currentSceneId=t.currentSceneId,this.stack=t.stack.map(n=>{let{nextId:s,...i}=n;if(s!==void 0){let o=this.childrenOf(i.containerId)?.findIndex(a=>a.id===s)??-1;if(o>=0)return{...i,index:o}}return{...i}}),this.activeSnippet=null,t.activeSnippetId!==null){let n=this.host.nodeIndex.get(t.activeSnippetId);n&&n.type==="snippet"&&(this.activeSnippet=n)}if(this.selectors=Ot(t.selectors),this.pendingChoice=null,t.pendingChoice!==null){let n=new Map,s=[];for(let i of t.pendingChoice.options){let o=this.host.nodeIndex.get(i.id);if(!o)continue;n.set(i.id,o);let{prompt:a,extensions:l,...c}=i,p=a?.kind==="line"&&a.speakerLabel===void 0?ce(this.host,a.character,a.qualifier):void 0;s.push({...c,...a?{prompt:{...a,padAfter:a.padAfter??this.promptPadOf(o),...p!==void 0?{speakerLabel:p}:{}}}:{},...M(o.extensions)})}s.length>0&&(this.pendingChoice={groupId:t.pendingChoice.groupId,options:s,byId:n})}if(this.pendingPrompt=null,this.pendingPromptOwnerId=t.pendingPromptOwnerId??null,this.pendingPromptOwnerId){let n=this.host.nodeIndex.get(this.pendingPromptOwnerId),s=n?this.authoredPromptOf(n):void 0,i=t.pendingPrompt,o=i?.kind==="line"&&i.speakerLabel===void 0?ce(this.host,i.character,i.qualifier):void 0;s?this.pendingPrompt={beat:s,...i?{shown:{...i,padAfter:i.padAfter??this.padOf(s.id),...o!==void 0?{speakerLabel:o}:{}}}:{}}:this.pendingPromptOwnerId=null}}enterSceneSetup(e){let t=this.host.bundle.scenes[e];if(!t)throw new Error(`unknown scene: ${e}`);this.currentSceneId=e,this.enter(e),this.seedScene(t),this.runEffects(t.onEntry,t.id)}enterChild(e){if(this.enter(e.id),e.type==="snippet"){this.beginSnippet(e);return}let t=e.selector??"run";if(t==="run"){this.stack.push({sceneId:this.currentSceneId,containerId:e.id,index:0});return}if(t==="choice"){this.setupChoice(e);return}let n=this.selectChild(e);n&&this.enterChild(n)}childrenOf(e){let t=this.host.blockById.get(e);if(t)return t.children;let n=this.host.nodeIndex.get(e);if(n&&n.type==="group")return n.children}beginSnippet(e){this.runEffects(e.onEnter,e.id),this.activeSnippet=e,this.beatIndex=0}setupChoice(e){let t=[],n=new Map,s=[];for(let o of e.children){if(o.fallback===!0){s.push(o);continue}if(o.sticky!==!0&&(this.visitCounts.get(o.id)??0)>=1)continue;let a=this.eligible(o),l=o.secretUntilEligible===!0;!a&&l||(t.push({id:o.id,prompt:this.promptFor(o),eligible:a,gameData:o.gameData,...M(o.extensions)}),n.set(o.id,o))}if(t.some(o=>o.eligible)){this.host.tracing&&this.emit({type:"choice",group:e.id,options:t.map(o=>({id:o.id,eligible:o.eligible}))}),this.pendingChoice={groupId:e.id,options:t,byId:n};return}let i=s.find(o=>this.eligible(o));if(i){this.enterChild(i);return}this.host.tracing&&this.emit({type:"dry",group:e.id}),this.host.onDryChoice?.(e.id)}resolveJump(e){e&&this.enterTarget(e.to,e.mode==="call"?"call":"jump")}enterTarget(e,t){if(this.host.tracing&&this.emit({type:"jump",to:e,mode:t}),e==="END"){this.flowEnded=!0,this.stack=[];return}let n,s,i=this.host.bundle.scenes[e];if(i){this.enterSceneSetup(e);let a=i.blocks[0];if(!a){t==="jump"&&(this.stack=[]);return}n=e,s=a.id}else{let a=this.host.blockIndex.get(e);if(!a)throw new Error(`jump target not found: ${e}`);a.sceneId!==this.currentSceneId&&this.enterSceneSetup(a.sceneId),n=a.sceneId,s=e}this.enter(s);let o={sceneId:n,containerId:s,index:0};t==="call"?this.stack.push(o):this.stack=[o]}selectChild(e){let t=e.children.map(l=>({id:l.id,eligible:this.eligible(l)})),n=e.children.filter((l,c)=>t[c].eligible),s=e.options?.order??"sequential",i=e.options?.exhaust??"once",o=l=>(this.host.tracing&&this.emit({type:"select",group:e.id,selector:e.selector??"default",...e.selector==="sequence"?{order:s,exhaust:i}:{},children:t,picked:l?.id??null}),l);if(n.length===0)return o(null);let a=this.selectorState(e);switch(e.selector){case"branch":return o(n[0]);case"sequence":return o(s==="shuffle"?this.pickShuffle(n,i,a):s==="specificity"?this.pickSpecificity(n,i,a):this.pickSequential(n,i,a));default:return null}}pickSequential(e,t,n){let s=e.length,i=n.seq??0;return n.seq=i+1,t==="repeat"?e[i%s]:i<s?e[i]:t==="stick"?e[s-1]:null}pickShuffle(e,t,n){let s=e.length,i=t==="stick",o=()=>(i?e.slice(0,s-1):e).map(f=>f.id),a=new Set(e.map(f=>f.id));if(n.bag===void 0&&(n.bag=o()),!n.bag.some(f=>a.has(f))){if(t==="once")return null;if(i){let f=e[s-1];return n.last=f.id,f}if(n.bag=o(),n.bag.length===0)return null}let l=n.bag.filter(f=>a.has(f)),c=n.last!==void 0&&l.length>1?l.indexOf(n.last):-1,p=Math.floor(this.rng()*(c>=0?l.length-1:l.length));c>=0&&p>=c&&p++;let d=l[p];return n.bag.splice(n.bag.indexOf(d),1),n.last=d,e.find(f=>f.id===d)}pickSpecificity(e,t,n){let s=e;if(t!=="repeat"){n.bag===void 0&&(n.bag=e.map(p=>p.id));let c=new Set(n.bag);if(s=e.filter(p=>c.has(p.id)),s.length===0)return t==="stick"&&n.last!==void 0?e.find(p=>p.id===n.last)??null:null}let i=-1,a=s.map(c=>{let p=this.specScore(c);return p>i&&(i=p),{c,s:p}}).filter(c=>c.s===i).map(c=>c.c),l;if(a.length===1)l=a[0];else{let c=n.last!==void 0?a.findIndex(d=>d.id===n.last):-1,p=Math.floor(this.rng()*(c>=0?a.length-1:a.length));c>=0&&p>=c&&p++,l=a[p]}return t!=="repeat"&&(n.bag=n.bag.filter(c=>c!==l.id)),n.last=l.id,l}specScore(e){return e.condition?this.matchedSpec(this.conditionAst(e.condition),!0,e):0}matchedSpec(e,t,n){return Ze(e,i=>{try{return Rt(ge(i,this.context(),Te))}catch(o){return this.reportError("best-match",n.id,n.condition,o),!1}},{want:t})}selectorState(e){let t=e.shared?this.host.sharedSelectors:this.selectors,n=this.host.journal,s;if(n&&(s=e.shared?n.selectors:n.flowSelectors.get(this),s||(s=new Set,n.flowSelectors.set(this,s))),n&&s&&!s.has(e.id)){s.add(e.id);let o=t.get(e.id),a=o?{...o,...o.bag?{bag:[...o.bag]}:{}}:void 0;n.undo.push(()=>{a?t.set(e.id,a):t.delete(e.id)})}let i=t.get(e.id);return i||(i={},t.set(e.id,i)),i}runEffects(e,t){for(let n of e??[]){let s;try{s=this.evalExpr(n.value);let i=this.host.tracing?this.getProperty(n.target):void 0;this.writeProperty(n.target,s,!1),this.host.tracing&&this.emit({type:"write",target:n.target,value:s,...i!==void 0?{prev:i}:{}})}catch(i){this.reportError("effect",t,n.value,i)}}}eligible(e){if(!e.condition)return!0;try{return Rt(this.evalExpr(e.condition))}catch(t){return this.reportError("condition",e.id,e.condition,t),!1}}reportError(e,t,n,s){let i=s instanceof Error?s.message:String(s),o=n?.src;this.host.onError({flow:this.id,kind:e,node:t,...o?{source:o}:{},message:i}),this.host.tracing&&this.emit({type:"diagnostic",kind:e,node:t,...o?{source:o}:{},message:i})}evalExpr(e){return ge(this.conditionAst(e),this.context(),Te)}conditionAst(e){let t=yt.get(e);return t||(t=V(e.ast),yt.set(e,t)),t}enter(e){let t=this.visitCounts,n=t.get(e);t.set(e,(n??0)+1);let s=this.host.sharedVisits,i=s.get(e);s.set(e,(i??0)+1),this.host.journal&&this.host.journal.undo.push(()=>{n===void 0?t.delete(e):t.set(e,n),i===void 0?s.delete(e):s.set(e,i)})}rng=()=>{if(this.host.customRng)return this.host.customRng();let e=Pe(this.rngState),t=e.next();return this.rngState=e.state(),t};beatResult(e){let t=H(this.host,e.id),n=t&&t.length?{tags:t}:{};switch(e.kind){case"gameEvent":return{type:"gameEvent",id:e.id,gameData:e.gameData,...M(e.extensions),...n};case"text":return{type:"text",id:e.id,text:this.interpolate(this.resolveString(e.id)),padAfter:this.padOf(e.id),...e.action?{action:!0}:{},gameData:e.gameData,...M(e.extensions),...n};case"line":{let s=this.resolveString(e.id),i=!this.host.captionsOn,a=i&&e.character===this.host.captionCharacter?"":this.captionLine(this.host.bundle.voiced?s:this.interpolate(s)),l=i&&a.length===0;return{type:"line",id:e.id,text:a,character:l?void 0:e.character,characterName:l?void 0:this.resolveCharacterName(e.character),direction:l?void 0:e.direction,qualifier:l?void 0:e.qualifier,qualifierName:l?void 0:this.resolveQualifierName(e.qualifier),speakerLabel:l?void 0:ce(this.host,e.character,e.qualifier),padAfter:this.padOf(e.id),gameData:e.gameData,...M(e.extensions),...n}}}}interpolate(e){return ct(e,t=>this.getProperty(t))}stripCaptions(e){return lt(e,this.host.captionOpen,this.host.captionClose)}captionLine(e){return this.host.captionsOn?e:this.stripCaptions(e)}promptFor(e){let t=this.promptBeatOf(e);if(!t)return;let n=this.interpolate(this.resolveString(t.id)),s=this.padOf(t.id);return t.kind==="line"?{kind:"line",text:this.captionLine(n),character:t.character,characterName:this.resolveCharacterName(t.character),direction:t.direction,qualifier:t.qualifier,qualifierName:this.resolveQualifierName(t.qualifier),speakerLabel:ce(this.host,t.character,t.qualifier),padAfter:s}:{kind:"text",text:n,padAfter:s}}authoredPromptOf(e){return e.type==="group"?e.prompt:void 0}promptResult(e,t){let n=H(this.host,e.id),s=n&&n.length?{tags:n}:{};return t.kind==="text"?{type:"text",id:e.id,text:t.text,padAfter:this.padOf(e.id),gameData:e.gameData,...M(e.extensions),...s}:{type:"line",id:e.id,text:t.text,character:t.character,characterName:t.characterName,direction:t.direction,qualifier:t.qualifier,qualifierName:t.qualifierName,speakerLabel:t.speakerLabel,padAfter:this.padOf(e.id),gameData:e.gameData,...M(e.extensions),...s}}promptBeatOf(e){return e.type==="group"&&e.prompt?e.prompt:((e.type==="snippet"?e:this.firstTextSnippetIn(e.children))?.beats??[]).find(n=>n.kind==="line"||n.kind==="text")}firstTextSnippetIn(e){let t;return q(e,n=>{!t&&n.type==="snippet"&&(n.beats??[]).some(s=>s.kind==="line"||s.kind==="text")&&(t=n)}),t}resolveString(e){if(this.host.emitIds)return e;let t=this.host.strings[e];if(t!==void 0)return t;let n=this.host.defaultStrings[e];return n!==void 0?`<Untranslated: ${e}> ${n}`:e}resolveCharacterName(e){if(e===void 0||this.host.emitIds)return;let t=Se(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.castDisplay.get(e)}promptPadOf(e){let t=this.promptBeatOf(e);return t?this.padOf(t.id):j}padOf(e){return this.host.padIndex.get(e)?.resolved??j}resolveQualifierName(e){if(e===void 0||this.host.emitIds)return;let t=xe(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.qualifierDisplay.get(e)}splitRef(e){return At(this.host,e)}newLocal(){return new $(this.host.patterLocalDecls,{pathPrefix:"@patter."})}mountLocal(){this.local=this.newLocal();let e=P.flowGlobals(this.id);this.host.registry.mountOwned(e,this.local,{owner:de}),this.registered.add(e),this.host.reportRefits()}releaseBags(e){for(let t of this.registered)this.host.registry.remove(t,{keep:e});this.registered.clear(),this.sceneBags.clear()}sceneBagFor(e,t){if(this.host.bundle.scenes[e])return this.ensureSceneBags(e),this.host.sceneSharedNames.get(e)?.has(t.toLowerCase())?this.host.stageBags.get(e):this.sceneBags.get(e)}ensureSceneBags(e){let t=this.host.sceneSharedNames.get(e)??new Set,n=this.host.bundle.scenes[e]?.sceneProps??[],s=this.host.journal,i=!this.sceneBags.has(e)||!this.host.stageBags.has(e);if(!this.sceneBags.has(e)){let o=new $(n.filter(c=>!t.has(c.name.toLowerCase())),{pathPrefix:"@scene."}),a=P.flowScene(this.id,e),l=Et(this.host.registry,a,o,s!==null);this.registered.add(a),this.sceneBags.set(e,o),s&&s.undo.push(()=>{this.sceneBags.get(e)===o&&(this.host.registry.remove(a,l?{keep:!0}:void 0),this.registered.delete(a),this.sceneBags.delete(e))})}if(!this.host.stageBags.has(e)){let o=new $(n.filter(l=>t.has(l.name.toLowerCase())),{pathPrefix:"@scene."}),a=Et(this.host.registry,P.stage(e),o,s!==null);this.host.stageBags.set(e,o),s&&s.undo.push(()=>{this.host.stageBags.get(e)===o&&(this.host.registry.remove(P.stage(e),a?{keep:!0}:void 0),this.host.stageBags.delete(e))})}i&&this.host.reportRefits()}seedScene(e){let t=this.host.sceneSharedNames.get(e.id)??new Set;this.ensureSceneBags(e.id);for(let n of e.sceneProps??[]){if(!n.temporary)continue;let s=n.name.toLowerCase(),i=t.has(s)?this.host.stageBags.get(e.id):this.sceneBags.get(e.id);if(!i)continue;let o=this.host.journal?i.get(s):void 0;o!==void 0&&this.host.journal.undo.push(()=>i.set(s,o)),i.set(s,K(n))}}};function wt(r,e){q(r,t=>{if(t.type==="group"){t.prompt?.kind==="line"&&t.prompt.character&&e.add(t.prompt.character);return}for(let n of t.beats??[])n.kind==="line"&&n.character&&e.add(n.character)})}function ce(r,e,t,n=!1){if(!e||r.emitIds)return;let s=l=>(n?void 0:r.strings[l])??r.defaultStrings[l],i=s(Se(e))??r.castDisplay.get(e)??e;if(t===void 0)return i;let o=r.speakerLabels.get(`${e}\0${t}`);if(o!==void 0)return s(dt(e,t))??o;let a=s(xe(t))??r.qualifierDisplay.get(t)??t;return ft(s(pt)??r.speakerPattern,i,a)}function kt(r){return r&&Object.keys(r).length?{gameData:r}:{}}function M(r){return r&&Object.keys(r).length?{extensions:r}:{}}function Ln(r){let e={kind:r.kind,text:r.text};return r.character!==void 0&&(e.character=r.character),r.characterName!==void 0&&(e.characterName=r.characterName),r.direction!==void 0&&(e.direction=r.direction),r.qualifier!==void 0&&(e.qualifier=r.qualifier),r.qualifierName!==void 0&&(e.qualifierName=r.qualifierName),r.speakerLabel!==void 0&&(e.speakerLabel=r.speakerLabel),typeof r.padAfter=="number"&&(e.padAfter=r.padAfter),e}function It(r){let e={};for(let[t,n]of r){let s={};n.seq!==void 0&&(s.seq=n.seq),n.bag&&(s.bag=[...n.bag]),n.last!==void 0&&(s.last=n.last),e[t]=s}return e}function Ot(r){let e=new Map;for(let[t,n]of Object.entries(r??{})){let s={};n.seq!==void 0&&(s.seq=n.seq),n.bag&&(s.bag=[...n.bag]),n.last!==void 0&&(s.last=n.last),e.set(t,s)}return e}function Et(r,e,t,n){let s=n?JSON.stringify(t.save()):"";return r.mountOwned(e,t,{owner:de}),n&&JSON.stringify(t.save())!==s}function Ct(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default}}function Dt(r){return{...r.world?{world:r.world}:{},...r.hostScopes}}function pe(r,e,t){let n=r.qualityLadders.get(e);if(!n){n=new Map;for(let s of t()??[]){let i=s.name.toLowerCase();s.type==="quality"&&s.stages&&!n.has(i)&&n.set(i,s.stages)}r.qualityLadders.set(e,n)}return n}function Bn(r,e,t){let n=t.toLowerCase();return e==="patter"?pe(r,"patter",()=>[...r.patterSharedDecls,...r.patterLocalDecls]).get(n):r.registry.toEvalContext().qualities?.(e,t)??pe(r,`host/${e}`,()=>r.bundle.scopeRegistry?.scopes.find(s=>s.token===e)?.declarations).get(n)}function Pt(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default,writable:r.writable}}function Mn(r,e){let t=Pt(r),n=r.writable??e;return n===void 0?t:{...t,writable:n}}function je(r,e){return ve(r.bundle.scenes,e,r.sceneGameIdToId)}function Ve(r,e,t){return r.blockGameIdToId.get(e)?.get(t)??(r.blockIndex.get(t)?.sceneId===e?t:void 0)}function At(r,e){r.refSplitRevision!==r.registry.revision&&(r.refSplitCache.clear(),r.refSplitRevision=r.registry.revision);let t=r.refSplitCache.get(e);return t||(t=at(e,n=>n==="scene"||r.registry.has(n)||(r.bundle.externalScopes?.includes(n)??!1)),r.refSplitCache.set(e,t)),t}function Tn(r){let e={};r.shared?.patter&&(e.patter=r.shared.patter);for(let[t,n]of Object.entries(r.stageBags??{}))e[P.stage(t)]=n;for(let[t,n]of Object.entries(r.flows??{}))Object.assign(e,Nt(t,n));return e}function Nt(r,e){let t={};e.scopes?.patter&&(t[P.flowGlobals(r)]=e.scopes.patter);for(let[n,s]of Object.entries(e.sceneBags??{}))t[P.flowScene(r,n)]=s;return t}function Fn(r,e){let t={scopes:{},sceneBags:{}},n=P.flow(r);for(let[s,i]of Object.entries(e)){if(!s.startsWith(n))continue;let o=s.slice(n.length);o==="patter"?t.scopes.patter=i:o.startsWith("scene/")&&(t.sceneBags[Nn(o.slice(6))]=i)}return t}function Rt(r){return typeof r=="boolean"?r:typeof r=="number"?r!==0:typeof r=="string"?r!=="":r.length>0}var $n=(r,e)=>r.shared??e;function Ge(r,e){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.default!==void 0?{default:r.default}:{},shared:$n(r,e)}}function jn(r){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.values?{values:[...r.values]}:{},...r.purpose?{purpose:r.purpose}:{}}}function Vn(r,e){e.blocks++;let t=[...r.children];for(;t.length;){let n=t.pop();if(n.type==="group"){e.groups++,n.prompt&&e.prompts++,t.push(...n.children);continue}e.snippets++;for(let s of n.beats??[])e.beats++,s.kind==="gameEvent"&&e.gameEvents++}}function Ee(r){let e={scenes:0,blocks:0,groups:0,snippets:0,beats:0,prompts:0,gameEvents:0,cast:r.cast?.length??0},t=[],n=[];for(let o of Object.values(r.scenes)){e.scenes++;let a=E(o);t.push({gameId:a,name:o.name,blocks:o.blocks.map(l=>({gameId:E(l),name:l.name}))});for(let l of o.blocks)Vn(l,e);o.sceneProps?.length&&n.push({gameId:a,properties:o.sceneProps.map(l=>Ge(l,!1))})}let s=(r.scopeRegistry?.scopes??[]).map(o=>({token:o.token,writable:o.writable??!0,opaque:o.declarations===void 0,properties:(o.declarations??[]).map(a=>Ge(a,!0))})),i=Object.entries(r.gameDataFields??{}).filter(([,o])=>(o?.length??0)>0).map(([o,a])=>({kind:o,fields:(a??[]).map(jn)}));return{identity:{schema:r.schema,project:r.content.project,...r.content.version!==void 0?{version:r.content.version}:{},...r.content.hash!==void 0?{hash:r.content.hash}:{},...r.content.structureHash!==void 0?{structureHash:r.content.structureHash}:{},voiced:r.voiced,defaultLocale:r.locales.default,locales:[...r.locales.included],localisation:r.localisation?.mode??"embedded",sourceDebug:r.localisation?.sourceDebug??!1},addresses:t,hostScopes:s,properties:{patter:(r.properties??[]).map(o=>Ge(o,!0)),scene:n},gameData:i,counts:e}}var Q=(r,e)=>Object.prototype.hasOwnProperty.call(r,e);function Lt(r,e){return r.gameDataFields?.[e]??[]}function qe(r,e,t){return e&&Q(e,t)?e[t]:r.find(n=>n.name===t)?.default}function Bt(r,e){let t={};for(let n of r){let s=qe(r,e,n.name);s!==void 0&&(t[n.name]=s)}for(let[n,s]of Object.entries(e??{}))Q(t,n)||(t[n]=s);return t}function Mt(r,e,t){let n=r.extensions!==void 0&&Q(r.extensions,e)?r.extensions[e]:void 0;return n!==void 0&&Q(n.fields,t)?n.fields[t]??[]:[]}function Tt(r,e){return{...(r.extensions!==void 0&&Q(r.extensions,e)?r.extensions[e]:void 0)?.settings??{}}}function Ft(r,e,t=""){let n=o=>({...o?.extensions??{}}),s=Object.values(r.scenes??{}),i=o=>(Q(r.scenes??{},o)?r.scenes[o]:void 0)??s.find(a=>E(a)===o);switch(e){case"project":{let o={};for(let[a,l]of Object.entries(r.extensions??{}))l.project!==void 0&&(o[a]=l.project);return o}case"scene":return n(i(t));case"block":{let o=t.indexOf("/");if(o<0)return{};let a=i(t.slice(0,o))?.blocks??[],l=t.slice(o+1);return n(a.find(c=>c.id===l)??a.find(c=>E(c)===l))}case"snippet":case"option":case"line":case"text":case"gameEvent":{let o,a=(l,c)=>{for(let p of l??[]){if(o!==void 0)return;if(p.type==="group"){if(c&&p.id===t&&e==="option"){o=p;return}if(c&&p.prompt?.id===t&&p.prompt.kind===e){o=p.prompt;return}a(p.children??[],p.selector==="choice");continue}if(p.id===t&&e==="snippet"){o=p;return}let d=(p.beats??[]).find(f=>f.id===t);if(d!==void 0){d.kind===e&&(o=d);return}}};for(let l of s)for(let c of l.blocks??[])o===void 0&&a(c.children??[],!1);return n(o)}default:return{}}}function He(r){return{schema:z,save:r.saveGame()}}function _e(r,e){if(!e||e.schema!==z||!e.save)throw new Error(`loadState: not a ${z} envelope`);r.loadGame(e.save)}function Ce(r){return JSON.stringify(He(r))}function De(r,e){_e(r,JSON.parse(e))}function $t(r,e){return r.getProperty(e)}function jt(r,e,t){r.setProperty(e,t)}function Vt(r,e){for(let[t,n]of Object.entries(e))r.setProperty(t,n)}function We(r){let e={};for(let t of Gt(r)){let n=t.pathPrefix??t.bag.pathPrefix;for(let[s,i]of Object.entries(t.bag.save()))e[`${n}${s}`]=i}return Object.assign(e,qt(r)),e}function Gt(r){return[...r.listBags(),...r.flows().flatMap(e=>e.listBags())]}function Gn(r){switch(r.type){case"line":return`line ${r.character??"?"}: ${JSON.stringify(r.text)}${Ue(r.gameData)}`;case"text":return`text: ${JSON.stringify(r.text)}${Ue(r.gameData)}`;case"gameEvent":return`game event ${r.id}${Ue(r.gameData)}`;case"choice":return`choice (${r.options.length} option${r.options.length===1?"":"s"})`;case"end":return"end"}}var Ue=r=>r?` gameData=${JSON.stringify(r)}`:"";function qt(r){let e={};for(let[t,n]of Object.entries(r.getVisitCounts()))e[`visit:${t}`]=n;for(let t of r.flows())for(let[n,s]of Object.entries(t.getVisitCounts()))e[`${t.id}/visit:${n}`]=s;return e}function Ht(r,e={}){let t=e.label?`[${e.label}] `:"",n=Be({mounts:()=>Gt(r),extra:()=>qt(r)},{sink:e.sink,label:t});return{snapshot:()=>We(r),capture:()=>n.capture(),dispose:()=>n.dispose(),logStep(s){(e.sink??(i=>console.log(i)))(`${t}${Gn(s)}`)}}}function _t(r){let e=r.url??"ws://127.0.0.1:4471",t=r.WebSocket??globalThis.WebSocket,n=new Set,s=[],i=null,o=!1,a=r.build,l=()=>{if(!(!i||i.readyState!==1)){for(let d of s)try{i.send(d)}catch{}s=[]}},c=d=>{o||!i||i.readyState>1||(s.push(JSON.stringify(d)),l())};if(!t)return{flowOpened(){},observe(){},flowClosed(){},setBuild(){},close(){o=!0},state:"closed",build:a,url:e};let p=()=>{let d=JSON.stringify({t:"hello",v:1,build:a,project:r.project,flows:[...n]});try{i?.send(d)}catch{}};try{i=new t(e),i.addEventListener("open",()=>{p(),l()}),i.addEventListener("message",d=>{if(!(!r.onBundle||typeof d.data!="string"))try{let f=JSON.parse(d.data);f.t==="bundle"&&typeof f.build=="string"&&typeof f.data=="string"&&r.onBundle({build:f.build,data:f.data})}catch{}}),i.addEventListener("error",()=>{}),i.addEventListener("close",()=>{i=null,s=[]})}catch{i=null}return{flowOpened(d){n.add(d),c({t:"flowOpen",flow:d})},flowClosed(d){n.delete(d),c({t:"flowClose",flow:d})},observe(d,f,g,y,u){n.has(d)||(n.add(d),c({t:"flowOpen",flow:d})),c({t:"frame",flow:d,sceneId:f,beatId:g,type:y,choiceId:u})},setBuild(d){o||d===a||(a=d,i&&i.readyState===1&&p())},close(){o=!0,s=[];try{i?.close()}catch{}i=null},get state(){return o||!i?"closed":i.readyState===1?"connected":"connecting"},get build(){return a},url:e}}function Ut(r,e,t){let n=JSON.parse(t);return e.content.structureHash!==void 0&&e.content.structureHash===n.content.structureHash?(r.replaceStrings(n),{engine:r,bundle:n,kind:"text"}):{engine:r.hotSwap(n),bundle:n,kind:"structure"}}function qn(r,e){r.textContent="";let t=/\u0002([^\u0003]*)\u0003/g,n=0,s;for(;(s=t.exec(e))!==null;){s.index>n&&r.append(e.slice(n,s.index));let i=document.createElement("strong");i.textContent=s[1]??"",r.append(i),n=s.index+s[0].length}n<e.length&&r.append(e.slice(n))}var ze=!1,Wt=!1,Yt,Hn=350,Je=6,Jt=7,X=null,Z=0,Re=null,_n=null;function Xt(){if(X)return X;let r=document.createElement("div");return r.className="tooltip",r.setAttribute("role","tooltip"),r.hidden=!0,document.body.appendChild(r),X=r,r}var Un=r=>r instanceof HTMLElement?r.getBoundingClientRect():r;function Wn(r){let e=Xt(),t=Un(r),n=e.getBoundingClientRect(),s=t.top-n.height-Jt;s<Je&&(s=t.top+t.height+Jt);let i=t.left+t.width/2-n.width/2;i=Math.max(Je,Math.min(i,window.innerWidth-n.width-Je)),e.style.left=`${Math.round(i)}px`,e.style.top=`${Math.round(s)}px`}function Jn(r){let e=r.dataset.tip;e&&Kn(r,e)}function Kn(r,e){if(Yt?.())return;let t=Xt(),n=(r instanceof HTMLElement?r.closest("dialog[open]"):null)??document.body;t.parentElement!==n&&n.appendChild(t),Re=r instanceof HTMLElement?r:null,qn(t,e),t.hidden=!1,t.classList.remove("show"),t.offsetWidth,Wn(r),t.classList.add("show")}function Y(){Z&&(window.clearTimeout(Z),Z=0),Re=null,_n=null,X&&(X.hidden=!0,X.classList.remove("show"))}function Kt(r){r!==Re&&(Z&&window.clearTimeout(Z),Z=window.setTimeout(()=>Jn(r),Hn))}function zn(){Yn()}function Qn(){Wt||(Wt=!0,setTimeout(()=>{ze||typeof document>"u"||document.querySelector("[data-tip]")&&console.warn("app-shell: something set `data-tip` but no tooltip host is mounted, so those rollovers will not draw. Call initTooltips() once per window.")},0))}var Ke=r=>r instanceof Element?r.closest("[data-tip]"):null;function Yn(r={}){r.suppressed!==void 0&&(Yt=r.suppressed),!ze&&(ze=!0,document.addEventListener("pointerover",e=>{let t=Ke(e.target);t&&Kt(t)}),document.addEventListener("pointerout",e=>{let t=Ke(e.target);if(!t)return;let n=e.relatedTarget;n instanceof Node&&t.contains(n)||Y()}),document.addEventListener("focusin",e=>{let t=Ke(e.target);t&&Kt(t)}),document.addEventListener("focusout",()=>Y()),document.addEventListener("pointerdown",()=>Y(),!0),document.addEventListener("scroll",()=>{Re&&Y()},!0),document.addEventListener("keydown",e=>{e.key==="Escape"&&Y()}),window.addEventListener("blur",()=>Y()))}var Xn={close:"\u2715",more:"\u22EF",collapsed:"\u25B8",expanded:"\u25BE",dropdown:"\u25BE",back:"\u2039",forward:"\u203A",up:"\u2191",down:"\u2193",tick:"\u2713",locked:"\u2298",readOnly:"\u25CB",checkedOut:"\u270E",modified:"\u25CF",untracked:"+",warning:"\u203C",dot:"\u25CF",play:"\u25B6",restart:"\u27F2",viewCards:"\u25A6",viewTable:"\u2630",viewNode:"\u25C8",grip:"\u283F",add:"+",note:"\u270E",comment:"\u275D"},Zn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.571" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">',er='<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">',v=r=>`${Zn}${r}</svg>`,Zt=r=>`${er}${r}</svg>`,zt=Zt('<circle cx="12" cy="12" r="6"/>'),tr=Zt('<circle cx="12" cy="12" r="9"/>'),en={close:v('<path d="M18 6 6 18"/><path d="m6 6 12 12"/>'),more:v('<circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/>'),collapsed:v('<path d="m9 18 6-6-6-6"/>'),expanded:v('<path d="m6 9 6 6 6-6"/>'),dropdown:v('<path d="m6 9 6 6 6-6"/>'),back:v('<path d="m15 18-6-6 6-6"/>'),forward:v('<path d="m9 18 6-6-6-6"/>'),up:v('<path d="m5 12 7-7 7 7"/><path d="M12 19V5"/>'),down:v('<path d="M12 5v14"/><path d="m19 12-7 7-7-7"/>'),arrowLeft:v('<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>'),arrowRight:v('<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>'),tick:v('<path d="M20 6 9 17l-5-5"/>'),locked:v('<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>'),readOnly:v('<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 9.9-1"/>'),checkedOut:v('<path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/><path d="m15 5 4 4"/>'),modified:zt,untracked:v('<path d="M5 12h14"/><path d="M12 5v14"/>'),warning:v('<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>'),dot:zt,play:v('<path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z"/>'),restart:v('<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/>'),viewCards:v('<rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/>'),viewTable:v('<rect width="18" height="18" x="3" y="3" rx="2"/><path d="M21 9H3"/><path d="M21 15H3"/>'),viewNode:v('<path d="m10.586 5.414-5.172 5.172"/><path d="m18.586 13.414-5.172 5.172"/><path d="M6 12h12"/><circle cx="12" cy="20" r="2"/><circle cx="12" cy="4" r="2"/><circle cx="20" cy="12" r="2"/><circle cx="4" cy="12" r="2"/>'),record:tr,speaker:v('<path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"/><path d="M16 9a5 5 0 0 1 0 6"/><path d="M19.364 18.364a9 9 0 0 0 0-12.728"/>'),grip:v('<circle cx="9" cy="12" r="1"/><circle cx="9" cy="5" r="1"/><circle cx="9" cy="19" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="15" cy="5" r="1"/><circle cx="15" cy="19" r="1"/>'),add:v('<path d="M5 12h14"/><path d="M12 5v14"/>'),copy:v('<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>'),connect:v('<path d="M12 22v-5"/><path d="M15 8V2"/><path d="M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z"/><path d="M9 8V2"/>'),search:v('<path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/>'),pin:v('<path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/>'),settings:v('<path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"/><circle cx="12" cy="12" r="3"/>'),note:v('<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/>'),comment:v('<path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/>')},bs={...en,noteFilled:'<svg viewBox="0 0 16 16" width="13" height="13" fill="currentColor" fill-rule="evenodd" aria-hidden="true"><path d="M3.4 1.4h5.3L12.6 5.3v8.1a1.2 1.2 0 0 1-1.2 1.2H3.4a1.2 1.2 0 0 1-1.2-1.2V2.6A1.2 1.2 0 0 1 3.4 1.4ZM4.9 6.8h6.2v1.1H4.9Zm0 2.1h6.2v1.1H4.9Zm0 2.1h3.7v1.1H4.9Z"/></svg>',noteOutline:'<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round" stroke-linecap="round" aria-hidden="true"><path d="M3.4 2h4.9l3.9 3.9v7.5a1 1 0 0 1-1 1H3.4a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1Z"/><path d="M8.3 2.2v3.8h3.8"/><path d="M4.9 8h6.2M4.9 10h6.2M4.9 12h3.7" stroke-width="0.95"/></svg>'},vs=Object.keys(en);var Qt=new Map;for(let[r,e]of Object.entries(Xn))Qt.has(e)||Qt.set(e,r);function tn(r,e,...t){let n=document.createElement(r),s=typeof e=="string"?{className:e}:e??{};s.className&&(n.className=s.className),s.text!==void 0&&s.text!==null&&(n.textContent=s.text),s.title!==void 0&&(n.title=s.title),s.tip!==void 0&&(n.dataset.tip=s.tip,n.setAttribute("aria-label",s.tip),zn()),s.onClick&&n.addEventListener("click",s.onClick);for(let i of t)i!=null&&n.append(i);return Qn(),n}function nn(r){let e=r.default;if(e!=null)return typeof e=="boolean"?e?"True":"False":Array.isArray(e)?e.length===0?"none":e.join(", "):e===""?"none":String(e);switch(r.type){case"boolean":return"False";case"number":return"0";case"enum":return r.values?.[0]??"none";case"quality":return r.stages?.[0]??"first stage";case"flags":return"none";default:return"empty"}}var rn=r=>`default (${nn(r)})`;function Qe(r){let e=r.doc===void 0?tn:(a,l)=>{let c=r.doc.createElement(a);return c.className=l.className,l.text!==void 0&&(c.textContent=l.text),l.tip!==void 0&&(c.title=l.tip,c.setAttribute("aria-label",l.tip)),l.onClick&&c.addEventListener("click",l.onClick),a==="button"&&(c.type="button"),c},t=e("span",{className:"seg shell-rungs"}),n=r.decl??{type:"quality",stages:r.stages},s=r.value===void 0,i=typeof n.default=="string"&&r.stages.includes(n.default)?n.default:r.stages[0],o=r.onPick===void 0;r.onClear&&t.append(e("button",{className:`seg-opt shell-rung shell-rung-default${s?" on":""}`,text:rn(n),tip:s?"Not set here: the declared default holds":"Clear the value, back to the default",onClick:()=>{s||r.onClear()}}));for(let a of r.stages){let l=r.value===a,c=s&&a===i,p=e(o?"span":"button",{className:`seg-opt shell-rung${l?" on":""}${c?" fallback":""}`,text:a,tip:l?"The current stage":c?"The stage it falls back to":o?a:r.pickTip?.(a)??`Set to "${a}"`,...o?{}:{onClick:()=>{l||r.onPick(a)}}});t.append(p)}return!s&&!r.stages.includes(r.value)&&t.append(e("span",{className:"seg-opt shell-rung stray on",text:r.value,tip:`"${r.value}" is not one of the stages: pick the one it belongs at now`})),t}var sn="pp-inspector-style",nr=`
|
|
1
|
+
"use strict";var Patterplay=(()=>{var Ie=Object.defineProperty;var dn=Object.getOwnPropertyDescriptor;var pn=Object.getOwnPropertyNames;var un=Object.prototype.hasOwnProperty;var fn=(r,e)=>{for(var t in e)Ie(r,t,{get:e[t],enumerable:!0})},gn=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of pn(e))!un.call(r,s)&&s!==t&&Ie(r,s,{get:()=>e[s],enumerable:!(n=dn(e,s))||n.enumerable});return r};var hn=r=>gn(Ie({},"__esModule",{value:!0}),r);var or={};fn(or,{Checkpoint:()=>pe,DEFAULT_PAD_AFTER:()=>j,Engine:()=>ke,Flow:()=>_,SAVE_SCHEMA:()=>z,applyLiveBundle:()=>_t,buildTagIndex:()=>xe,compareStages:()=>W,createAudioResolver:()=>ln,createBundleInspector:()=>an,createDebugLink:()=>Ht,createPropertyInspector:()=>sn,createStateLogger:()=>qt,describeBundle:()=>Ee,deserializeState:()=>De,diffState:()=>ne,effectiveGameData:()=>Bt,extensionDecls:()=>Mt,extensionsOf:()=>Tt,gameDataFields:()=>Lt,gameDataValue:()=>qe,getProperty:()=>Ft,loadState:()=>_e,nextStage:()=>J,resolveSceneRef:()=>ve,saveState:()=>He,sceneAddressIndex:()=>Fe,serializeState:()=>Ce,setProperties:()=>jt,setProperty:()=>$t,snapshotState:()=>We,stageIndex:()=>U});function ee(r,e){return r!==void 0&&Object.prototype.hasOwnProperty.call(r,e)?r[e]:void 0}function V(r){switch(r[0]){case"b":return{kind:"bool",value:r[1]};case"n":return{kind:"number",value:r[1]};case"s":return{kind:"string",value:r[1]};case"sv":return{kind:"scopedvar",scope:r[1],name:r[2]};case"u":return{kind:"unary",op:r[1],operand:V(r[2])};case"bin":return{kind:"binary",op:r[1],left:V(r[2]),right:V(r[3])};case"call":{let e=r.slice(2).map(V);return{kind:"call",name:r[1],args:e}}case"fd":return{kind:"flagdelta",sign:r[1],name:r[2]}}}var b=class extends Error{constructor(e){super(e),this.name="EvalError"}};function ge(r,e,t){let n=new Map(t.scopes.map(i=>[i.token,i.missing??"false"])),s=i=>{switch(i.kind){case"bool":return i.value;case"number":return i.value;case"string":return i.value;case"scopedvar":{let o=ee(e.scopes,i.scope);if(o===void 0)return!1;let a=typeof o.get=="function"?o.get(i.name):ee(o,i.name);if(a===void 0){if(n.get(i.scope)==="throw")throw new b(`@${i.scope}.${i.name} is not declared on the current ${i.scope}.`);return!1}return a}case"call":{if(i.name==="advance"&&!ee(t.functions,i.name)){let a=i.args[0];if(i.args.length!==1||a===void 0)throw new b(`advance() takes exactly 1 argument, got ${i.args.length}`);let l=Oe(a,e);if(l===void 0)throw new b("advance() needs a quality reference (@scope.name of a quality property)");let c=B(s(a),l,"advance");return l[Math.min(c+1,l.length-1)]}let o=ee(t.functions,i.name);if(!o)throw new b(`unknown function '${i.name}'`);return o.eval(i.args,{evaluate:s,ctx:e})}case"flagdelta":throw new b("flagdelta node is only valid as an argument to a flag-delta function");case"unary":{if(i.op==="not"){let a=s(i.operand);if(typeof a!="boolean")throw new b(`'not' requires a boolean operand, got ${typeof a}`);return!a}let o=s(i.operand);if(typeof o!="number")throw new b(`unary '-' requires a numeric operand, got ${typeof o}`);return-o}case"binary":{if(i.op==="and"){let d=s(i.left);if(typeof d!="boolean")throw new b(`'and' requires boolean operands, left is ${typeof d}`);if(!d)return!1;let f=s(i.right);if(typeof f!="boolean")throw new b(`'and' requires boolean operands, right is ${typeof f}`);return f}if(i.op==="or"){let d=s(i.left);if(typeof d!="boolean")throw new b(`'or' requires boolean operands, left is ${typeof d}`);if(d)return!0;let f=s(i.right);if(typeof f!="boolean")throw new b(`'or' requires boolean operands, right is ${typeof f}`);return f}let o=s(i.left),a=s(i.right),l=Oe(i.left,e),c=Oe(i.right,e),p=l??c;if(p!==void 0){if(l&&c&&!mn(l,c)&&(i.op===">"||i.op===">="||i.op==="<"||i.op==="<="))throw new b(`'${i.op}' compares two different qualities, whose stage orders are unrelated`);switch(i.op){case">":return B(o,p,">")>B(a,p,">");case">=":return B(o,p,">=")>=B(a,p,">=");case"<":return B(o,p,"<")<B(a,p,"<");case"<=":return B(o,p,"<=")<=B(a,p,"<=");case"+":case"-":case"*":case"/":throw new b(`'${i.op}' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`);default:break}}switch(i.op){case"==":return Xe(o,a);case"!=":return!Xe(o,a);case">":return G(o,a,">"),o>a;case">=":return G(o,a,">="),o>=a;case"<":return G(o,a,"<"),o<a;case"<=":return G(o,a,"<="),o<=a;case"+":if(typeof o=="number"&&typeof a=="number"||typeof o=="string"&&typeof a=="string")return o+a;throw new b(`'+' requires two numbers or two strings, got ${typeof o} and ${typeof a}`);case"-":return G(o,a,"-"),o-a;case"*":return G(o,a,"*"),o*a;case"/":if(G(o,a,"/"),a===0)throw new b("division by zero");return o/a}}}};return s(r)}function Xe(r,e){if(Array.isArray(r)||Array.isArray(e)){if(!Array.isArray(r)||!Array.isArray(e)||r.length!==e.length)return!1;let t=[...r].sort(),n=[...e].sort();for(let s=0;s<t.length;s++)if(t[s]!==n[s])return!1;return!0}return r===e}function G(r,e,t){if(typeof r!="number"||typeof e!="number")throw new b(`'${t}' requires numeric operands, got ${typeof r} and ${typeof e}`)}function Oe(r,e){if(!(r.kind!=="scopedvar"||e.qualities===void 0))return e.qualities(r.scope,r.name)}function B(r,e,t){if(typeof r!="string")throw new b(`'${t}' on a quality compares stages, got ${typeof r}`);let n=e.indexOf(r);if(n<0)throw new b(`"${r}" is not a stage of this quality (stages: ${e.join(", ")})`);return n}var mn=(r,e)=>r.length===e.length&&r.every((t,n)=>t===e[n]);function te(r){if(Number.isNaN(r)||!Number.isFinite(r))return 0;let e=Math.trunc(r)%4294967296;return e<0?e+4294967296:e}function Pe(r){let e=te(r);return{next(){e=e+1831565813>>>0;let t=Math.imul(e^e>>>15,1|e);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296},state(){return e}}}var Ne=r=>Array.isArray(r)?r:r.stages??[],yn=r=>Array.isArray(r)?"flags":r==null?"nothing":typeof r;function U(r,e){return typeof e=="string"?Ne(r).indexOf(e):-1}function Ae(r,e){if(typeof e!="string")throw new b(`a stage is a name, got ${yn(e)}`);let t=r.indexOf(e);if(t<0)throw new b(`"${e}" is not a stage of this quality (stages: ${r.join(", ")})`);return t}function W(r,e,t){let n=Ne(r),s=Ae(n,e)-Ae(n,t);return s<0?-1:s>0?1:0}function J(r,e){let t=Ne(r);return t[Math.min(Ae(t,e)+1,t.length-1)]}function Le(r,e,t){switch(r.type){case"boolean":return typeof e=="boolean";case"number":return typeof e=="number";case"string":case"text":case"multiline":return typeof e=="string";case"enum":return typeof e!="string"?!1:e===""&&t?.noneChosen?!0:!Array.isArray(r.values)||r.values.includes(e);case"flags":return Array.isArray(e)&&e.every(n=>typeof n=="string"&&(!Array.isArray(r.values)||r.values.includes(n)));case"quality":return typeof e=="string"&&(!Array.isArray(r.stages)||r.stages.includes(e));default:return!0}}var bn={name:"check_flags",count:r=>Math.max(1,r.args.length-1)},vn=[bn];function Ze(r,e,t){let n=t?.countingCalls??vn;return he(r,t?.want??!0,e,n)}function he(r,e,t,n){if(r.kind==="binary"&&(r.op==="and"||r.op==="or")){let s=he(r.left,e,t,n),i=he(r.right,e,t,n);return r.op==="and"===e?s>0&&i>0?s+i:0:Math.max(s,i)}if(r.kind==="unary"&&r.op==="not")return he(r.operand,!e,t,n);if(r.kind==="call"){let s=n.find(i=>i.name===r.name);if(s){let i=s.count(r),o=t(r);return e?o?i:0:o?0:1}}return t(r)===e?1:0}function ne(r,e){let t=[],n=new Set([...Object.keys(r),...Object.keys(e)]);for(let s of[...n].sort()){let i=r[s],o=e[s];JSON.stringify(i)!==JSON.stringify(o)&&t.push({path:s,from:i,to:o})}return t}var et=r=>r===void 0?"<unset>":JSON.stringify(r),tt=r=>r.pathPrefix??r.bag.pathPrefix;function Be(r,e={}){let t=e.sink??(d=>console.log(d)),n=e.label??"",s=d=>{t(`${n}${d.path}: ${et(d.from)} -> ${et(d.to)}`)},i=()=>{let d={};for(let f of r.mounts()){let g=tt(f);for(let[y,u]of Object.entries(f.bag.values))d[g+y]=u}return Object.assign(d,r.extra?.()??{}),structuredClone(d)},o=i(),a=[],l=[],c=(d,f)=>f.onAudit(g=>{let y=structuredClone({path:d+g.name,from:g.prev,to:g.next});s(y),a.push(y),o[y.path]=structuredClone(g.next)}),p=()=>{let d=r.mounts();if(!(l.length===d.length&&d.every((g,y)=>l[y].bag===g.bag))){for(let g of l)g.off();l=d.map(g=>({bag:g.bag,off:c(tt(g),g.bag)}))}};return p(),{snapshot:i,capture(){let d=i(),f=ne(o,d);for(let y of f)s(y);let g=[...a,...f];return a=[],o=d,p(),g},dispose(){for(let d of l)d.off();l=[],a=[]}}}var $=class r{values=Object.create(null);decls=new Map;subscribers=new Set;auditors=new Set;norm;pathPrefix;constructor(e=[],t){this.norm=t?.normalise??(n=>n.toLowerCase()),this.pathPrefix=t?.pathPrefix??"",this.seed(e)}seed(e){for(let t of e){let n=this.norm(t.name);this.decls.set(n,t),this.values[n]=structuredClone(t.default??K(t))}}get(e){return this.values[this.norm(e)]}normalise(e){return this.norm(e)}writable(e){return this.decls.get(this.norm(e))?.writable!==!1}set(e,t,n){let s=this.norm(e);if(!n?.host&&!this.writable(s))throw new Error(`'${e}' is read-only`);let i={name:s,prev:this.values[s],next:t,silent:n?.silent??!1,reason:n?.reason};this.values[s]=t;for(let o of[...this.auditors])o(i);if(!i.silent)for(let o of[...this.subscribers])o(i);return i}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}onAudit(e){return this.auditors.add(e),()=>this.auditors.delete(e)}rows(){return[...this.decls.entries()].map(([e,t])=>rt(t,this.get(e),void 0,e,this.pathPrefix))}declarations(){return[...this.decls.values()]}clone(){let e=new r([],{normalise:this.norm,pathPrefix:this.pathPrefix});return e.decls=new Map(this.decls),Object.assign(e.values,structuredClone(this.values)),e}reseed(e){for(let t of Object.keys(this.values))delete this.values[t];this.decls.clear(),this.seed(e)}save(){return structuredClone(this.values)}load(e,t){let n=new Map;for(let[i,o]of Object.entries(e)){let a=this.norm(i);this.values[a]=structuredClone(o),n.set(a,o)}let s=[];if(!t?.refit)return s;for(let[i,o]of this.decls){if(!n.has(i))continue;let a=n.get(i);Le(o,a)||(this.values[i]=structuredClone(K(o)),s.push({name:i,value:a}))}return s}};function rt(r,e,t,n,s=""){let i=n??r.name.toLowerCase();return{name:i,path:s+i,type:r.type,value:e,default:r.default??K(r),...r.values!==void 0?{values:r.values}:{},...r.stages!==void 0?{stages:r.stages}:{},writable:t??r.writable??!0}}var Sn=r=>r.toLowerCase(),Me=1,me=class{scopes=new Map;parked=new Map;parkedRefit=new Set;misfits=[];rev=0;get revision(){return this.rev}defineOwned(e,t,n){let s=typeof n=="string"?{pathPrefix:n}:n??{},i=new $(t,{pathPrefix:s.pathPrefix??`${e}.`,...s.normalise?{normalise:s.normalise}:{}});return this.mountOwned(e,i,s.owner!==void 0?{owner:s.owner}:void 0)}mountOwned(e,t,n){this.assertFree(e,n?.owner),this.scopes.set(e,{kind:"owned",bag:t,...n?.owner!==void 0?{owner:n.owner}:{}}),this.rev++;let s=this.parked.get(e);return s&&(this.note(e,t.load(s,{refit:this.parkedRefit.has(e)})),this.parked.delete(e),this.parkedRefit.delete(e)),this}remove(e,t){let n=this.scopes.get(e);if(!n)throw new Error(`unknown scope '@${e}'`);return t?.keep&&n.kind==="owned"&&(this.parked.set(e,n.bag.save()),this.parkedRefit.delete(e)),this.scopes.delete(e),this.rev++,this}discardParked(e){if(e===void 0)this.parked.clear(),this.parkedRefit.clear();else for(let t of[...this.parked.keys()])t.startsWith(e)&&(this.parked.delete(t),this.parkedRefit.delete(t));return this}takeMisfits(e){if(!e){let n=this.misfits;return this.misfits=[],n}let t=this.misfits.filter(n=>e(n.scope));return this.misfits=this.misfits.filter(n=>!e(n.scope)),t}note(e,t){for(let n of t)this.misfits.push({scope:e,name:n.name,value:n.value})}ownedBag(e){let t=this.scopes.get(e);if(!t||t.kind!=="owned")throw new Error(`'@${e}' is not an owned scope`);return t.bag}reseedOwned(e,t){return this.ownedBag(e).reseed(t),this}defineForeign(e,t,n=[],s=!0){let i=typeof s=="boolean"?{writable:s}:s;this.assertFree(e,i.owner);let o=i.normalise??Sn,a=new Map;for(let l of n)a.set(o(l.name),l);return this.scopes.set(e,{kind:"foreign",resolver:t,decls:a,scopeWritable:i.writable??!0,norm:o,...i.owner!==void 0?{owner:i.owner}:{}}),this.rev++,this}has(e){return this.scopes.has(e)}get(e,t){let n=this.scopes.get(e);if(n)return n.kind==="owned"?n.bag.get(t):n.resolver.get(n.norm(t))}set(e,t,n,s){let i=this.scopes.get(e);if(!i)throw new Error(`unknown scope '@${e}'`);if(i.kind==="owned"){if(!s?.host&&!i.bag.writable(t))throw new Error(`'@${e}.${t}' is read-only`);i.bag.set(t,n,s?.host?{host:!0}:void 0);return}let o=i.norm(t);if(!i.resolver.set)throw new Error(`'@${e}.${t}' is read-only`);if(!s?.host&&!this.foreignWritable(i,o))throw new Error(`'@${e}.${t}' is read-only`);i.resolver.set(o,n)}foreignWritable(e,t){return e.resolver.set?e.decls.get(t)?.writable??e.scopeWritable:!1}listProperties(){let e=[];for(let[t,n]of this.scopes){let s=n.owner!==void 0?{owner:n.owner}:{};if(n.kind==="owned")for(let i of n.bag.rows())e.push({scope:t,...s,...i});else for(let[i,o]of n.decls)e.push({scope:t,...s,...rt(o,n.resolver.get(i),this.foreignWritable(n,i),i,`${t}.`)})}return e}toEvalContext(e,t){let n=this.view(t?.aliases),s={};for(let[o,a]of n)s[o]=a.kind==="owned"?a.bag.values:a.resolver;let i=this.qualityLadders(n);return i.size===0?{scopes:s,host:e}:{scopes:s,host:e,qualities:(o,a)=>{let l=n.get(o);return l?i.get(o)?.get(wn(l)(a)):void 0}}}view(e){let t=new Map(this.scopes);for(let[n,s]of Object.entries(e??{})){let i=this.scopes.get(s);if(!i)throw new Error(`alias '@${n}' names '${s}', which is not registered`);t.set(n,i)}return t}qualityLadders(e){let t=new Map;for(let[n,s]of e)for(let[i,o]of nt(s)){if(o.type!=="quality"||o.stages===void 0)continue;let a=t.get(n);a||(a=new Map,t.set(n,a)),a.set(i,o.stages)}return t}toSchema(e){let t=new Map;for(let[n,s]of this.view(e?.aliases)){let i=nt(s);if(i.length===0)continue;let o=new Map;for(let[a,l]of i)o.set(a,{type:l.type,enumValues:l.values,...l.stages!==void 0?{stages:l.stages}:{}});t.set(n,o)}return{properties:t}}save(){let e={};for(let[t,n]of this.scopes)n.kind==="owned"&&(e[t]=n.bag.save());for(let[t,n]of this.parked)e[t]=structuredClone(n);return e}load(e,t){t?.keepParked||(this.parked.clear(),this.parkedRefit.clear());let n=t?.refit===!0;for(let[s,i]of Object.entries(e)){let o=this.scopes.get(s);o?.kind==="owned"?this.note(s,o.bag.load(i,{refit:n})):o||(this.parked.set(s,structuredClone(i)),n?this.parkedRefit.add(s):this.parkedRefit.delete(s))}}saveFragment(){return{version:Me,scopes:this.save()}}loadFragment(e){if(e.version!==Me)throw new Error(`unsupported owned-state fragment version ${e.version} (supported: ${Me})`);this.load(e.scopes)}assertFree(e,t){let n=this.scopes.get(e);if(!n)return;let s=n.owner!==void 0?` by ${n.owner}`:"",i=t!==void 0?` (wanted by ${t})`:"";throw new Error(`scope '@${e}' is already registered${s}${i}`)}};function nt(r){return r.kind==="foreign"?[...r.decls.entries()]:r.bag.declarations().map(e=>[r.bag.normalise(e.name),e])}function wn(r){return r.kind==="foreign"?r.norm:e=>r.bag.normalise(e)}function K(r){if(r.default!==void 0)return r.default;switch(r.type){case"boolean":return!1;case"number":return 0;case"string":case"text":case"multiline":return"";case"enum":return r.values?.[0]??"";case"flags":return[];case"quality":return r.stages?.[0]??"";default:return!1}}var st=[{token:"patter",engine:"Patterplay",means:"Patter's shared globals"},{token:"story",engine:"Storylet Engine",means:"the Storylet Engine's shared @story properties"}];function re(r){return r.ctx.host??{}}var Te={defaultScope:"patter",scopes:[{token:"patter"},{token:"scene"}],functions:{random:{minArgs:2,maxArgs:2,returnType:"number",eval(r,e){if(r.length!==2)throw new b("random(a, b) requires exactly 2 arguments");let t=re(e).nextRandom;if(!t)throw new b("random() called without a PRNG in context");let n=e.evaluate(r[0]),s=e.evaluate(r[1]);if(typeof n!="number"||typeof s!="number")throw new b("random(a, b) arguments must be numbers");if(!Number.isInteger(n)||!Number.isInteger(s))throw new b("random(a, b) arguments must be integers");let i=Math.min(n,s),o=Math.max(n,s);return Math.floor(t()*(o-i+1))+i}},check_flags:{minArgs:1,returnType:"boolean",flagDeltaArgs:!0,validate:ot("check_flags"),eval(r,e){let t=it(r[0],e,"check_flags");for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new b("check_flags() flag args must be +flagName or -flagName");if(s.sign==="+"?!t.includes(s.name):t.includes(s.name))return!1}return!0}},set_flags:{minArgs:1,returnType:"flags",flagDeltaArgs:!0,validate:ot("set_flags"),eval(r,e){let t=[...it(r[0],e,"set_flags")];for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new b("set_flags() flag args must be +flagName or -flagName");if(s.sign==="+")t.includes(s.name)||t.push(s.name);else{let i=t.indexOf(s.name);i>=0&&t.splice(i,1)}}return t}},visits:{minArgs:1,maxArgs:1,returnType:"number",validate:be("visits"),eval:(r,e)=>re(e).visits?.(ye(r,e,"visits"))??0},seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:be("seen"),eval:(r,e)=>(re(e).visits?.(ye(r,e,"seen"))??0)>0},patter_visits:{minArgs:1,maxArgs:1,returnType:"number",validate:be("patter_visits"),eval:(r,e)=>re(e).patterVisits?.(ye(r,e,"patter_visits"))??0},patter_seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:be("patter_seen"),eval:(r,e)=>(re(e).patterVisits?.(ye(r,e,"patter_seen"))??0)>0}}},Tr=st.map(r=>r.token).filter(r=>r!=="patter"&&r!=="scene");function at(r,e){let t=r.replace(/^@/,"").split(".");return t.length===2&&e(t[0])?{scope:t[0],name:t[1].toLowerCase()}:{scope:"patter",name:t.join(".").toLowerCase()}}function ye(r,e,t){let n=e.evaluate(r[0]);if(typeof n!="string")throw new b(`${t}(id) requires a string node id`);return n}function be(r){return(e,t)=>{let n=e[0];n&&n.kind!=="string"&&t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(id): the argument must be a string id literal (a scene / block / node id)`})}}function it(r,e,t){if(!r)throw new b(`${t}() requires at least one argument (the flags variable)`);let n=e.evaluate(r);if(Array.isArray(n))return n;if(n===!1||n===null||n===void 0)return[];throw new b(`${t}() first argument must be a flags property`)}function ot(r){return(e,t)=>{if(e.length===0)return;let n=e[0];if(n.kind!=="scopedvar"){t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(): first argument must be a flags property reference (@name or @scope.name)`});return}let s=t.schema.properties.get(n.scope)?.get(n.name);if(s&&s.type!=="flags"){let i=n.scope===t.defaultScope?n.name:`${n.scope}.${n.name}`;t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(): '@${i}' is not a flags property (got ${s.type})`});return}for(let i=1;i<e.length;i++){let o=e[i];o.kind!=="flagdelta"?t.report({path:[...t.path,"args",i],kind:"wrong-arg-type",severity:"error",message:`${r}(): argument ${i+1} must be +flagName or -flagName`}):s?.type==="flags"&&s.enumValues&&!s.enumValues.includes(o.name)&&t.report({path:[...t.path,"args",i],kind:"unknown-flag-name",severity:"error",message:`${r}(): unknown flag '${o.name}'`,reference:o.name})}}}var xn=/^@[A-Za-z0-9_.]+$/;function*kn(r){let e="",t=0;for(;t<r.length;){let n=r[t];if(n==="{"&&r[t+1]==="{"){e+="{",t+=2;continue}if(n==="}"&&r[t+1]==="}"){e+="}",t+=2;continue}if(n==="{"){let s=r.indexOf("}",t+1);if(s!==-1){let i=r.slice(t,s+1),o=r.slice(t+1,s).trim();if(o.startsWith("@")){e&&(yield{kind:"text",value:e},e=""),yield{kind:"slot",raw:i,inner:o,ref:xn.test(o)?o:void 0},t=s+1;continue}e+=i,t=s+1;continue}}e+=n,t+=1}e&&(yield{kind:"text",value:e})}function En(r){return Array.isArray(r)?r.join(", "):typeof r=="boolean"?r?"true":"false":String(r)}function Cn(r){return r===" "||r===" "||r===`
|
|
2
|
+
`||r==="\r"||r==="\f"||r==="\v"}function Dn(r){let e="",t=!1;for(let n of r){if(Cn(n)){t=!0;continue}t&&e.length>0&&(e+=" "),t=!1,e+=n}return e}function lt(r,e,t){if(e.length===0||r.indexOf(e)<0)return r;let n="",s=0,i=!1;for(;s<r.length;){if(r.startsWith(e,s)){let o=r.indexOf(t,s+e.length);if(o>=0){s=o+t.length,i=!0;continue}n+=r.slice(s);break}n+=r[s],s+=1}return i?Dn(n):r}function ct(r,e){if(r.indexOf("{")<0)return r;let t="";for(let n of kn(r)){if(n.kind==="text"){t+=n.value;continue}if(!n.ref){t+=n.raw;continue}let s=e(n.ref);t+=s===void 0?"":En(s)}return t}function q(r,e){for(let t of r){e(t);let n=t.children;n&&q(n,e)}}function Rn(r){return r.toLowerCase().replace(/['’]/g,"").replace(/[^a-z0-9-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function E(r){let e=r.gameId?.trim();return e||Rn(r.name)}function Fe(r){let e=new Map;for(let[t,n]of Object.entries(r))e.set(E(n),t);return e}function ve(r,e,t){return(t??Fe(r)).get(e)??(Object.hasOwn(r,e)?e:void 0)}var j=.6;function Se(r){return`cast:${r}`}function we(r){return`qualifier:${r}`}function dt(r,e){return`speaker:${r}:${e}`}var pt="speaker:pattern",ut="{name} ({qualifier})";function ft(r,e,t){return r.split("{name}").map(n=>n.split("{qualifier}").join(t)).join(e)}var $e={open:"[",close:"]"},gt="SFX",z="patter/save@0",se=3;function ie(r){let e=new Set,t=[];for(let n of r)e.has(n)||(e.add(n),t.push(n));return t}function xe(r){let e=new Map,t=(n,s)=>{let i=ie([...s,...n.tags??[]]);if(e.set(n.id,i),n.type==="group"&&n.prompt&&e.set(n.prompt.id,ie([...i,...n.prompt.tags??[]])),n.type==="group")for(let o of n.children)t(o,i);else for(let o of n.beats??[])e.set(o.id,ie([...i,...o.tags??[]]))};for(let n of Object.values(r.scenes)){let s=ie(n.tags??[]);e.set(n.id,s);for(let i of n.blocks){let o=ie([...s,...i.tags??[]]);e.set(i.id,o);for(let a of i.children)t(a,o)}}return e}var ht=r=>r.kind==="line"||r.kind==="text",oe=r=>typeof r=="number"&&Number.isFinite(r)?r:void 0;function mt(r){let e=new Map,t=(i,o,a)=>{let l=i.kind==="gameEvent"?void 0:oe(i.padAfter),c=l??o;a&&c<0&&(c=0),e.set(i.id,l!==void 0?{own:l,resolved:c}:{resolved:c})},n=(i,o)=>{let a=oe(i.padAfterDefault)??o;if(i.type==="group"){i.prompt&&t(i.prompt,a,!1);for(let p of i.children)n(p,a);return}let l=i.beats??[],c=-1;l.forEach((p,d)=>{ht(p)&&(c=d)}),l.forEach((p,d)=>{ht(p)&&t(p,a,d===c)})},s=oe(r.padAfterDefault)??j;for(let i of Object.values(r.scenes)){let o=oe(i.padAfterDefault)??s;for(let a of i.blocks){let l=oe(a.padAfterDefault)??o;for(let c of a.children)n(c,l)}}return e}var yt=new WeakMap,bt=new WeakMap;function In(r){let e=bt.get(r);return e||(e=xe(r),bt.set(r,e)),e}var vt=new WeakMap;function On(r){let e=vt.get(r);return e||(e=mt(r),vt.set(r,e)),e}var St=new WeakMap;function Pn(r){let e=St.get(r);if(e)return e;e=new Map;for(let t of Object.values(r.scenes))for(let n of t.blocks)q(n.children,s=>{if(s.type==="group"){s.prompt&&e.set(s.prompt.id,s.prompt);return}for(let i of s.beats??[])e.set(i.id,i)});return St.set(r,e),e}function H(r,e){return r.tagIndex.get(e)?.slice()}var ce="Patter",ae=r=>r.replace(/%/g,"%25").replace(/\//g,"%2F"),An=r=>r.replace(/%2F/g,"/").replace(/%25/g,"%"),wt=Symbol("ownsRegistry"),P={stage:r=>`patter/scene/${ae(r)}`,flow:r=>`patter/flow/${ae(r)}/`,flowGlobals:r=>`patter/flow/${ae(r)}/patter`,flowScene:(r,e)=>`patter/flow/${ae(r)}/scene/${ae(e)}`},pe=class{constructor(e){this.journal=e}journal},ke=class r{host;defaultSeed;flowsById=new Map;allStrings;currentLocale;sourceDebug;sceneGameIdToId=new Map;blockGameIdToId=new Map;creationOptions;engineLog=[];engineSeq=0;engineTraceHandlers=new Set;constructor(e,t={}){this.creationOptions=t;let n=t.locale??e.locales.default,s=e.strings;this.allStrings=s,this.currentLocale=n;let i=s[n]??{},o=s[e.locales.default]??{},a=e.localisation,l=a?.mode==="ids"&&!a.sourceDebug;this.sourceDebug=a?.mode==="ids"&&!!a.sourceDebug,this.sourceDebug&&typeof console<"u"&&console.warn("[Patterplay] source-only DEBUG build: strings are the source language for debugging, not a shippable localised build.");let c=new Map;for(let m of e.cast??[])m.displayName&&c.set(m.name,m.displayName);let p=new Map;for(let m of e.qualifiers??[])m?.gameId&&p.set(m.gameId,m.name);let d=new Map;for(let m of e.cast??[])for(let[S,O]of Object.entries(m.qualifierLabels??{}))typeof O=="string"&&d.set(`${m.name}\0${S}`,O);let f=e.speakerPattern??ut;this.defaultSeed=(t.seed??2654435769)>>>0;let g=new Map,y=new Map,u=new Map;for(let[m,S]of Object.entries(e.scenes)){this.sceneGameIdToId.set(E(S),m);let O=new Map;for(let D of S.blocks)y.set(D.id,{sceneId:m}),u.set(D.id,D),O.set(E(D),D.id),q(D.children,fe=>g.set(fe.id,fe));this.blockGameIdToId.set(m,O)}let x=e.properties??[],I=x.filter(m=>m.shared??!0).map(Ct),R=x.filter(m=>!(m.shared??!0)).map(Ct),N=new Set(I.map(m=>m.name.toLowerCase())),k=t.registry??new me,L=!t.registry||t[wt]===!0,T=new $(I,{pathPrefix:"@patter."}),F=[],h=[];try{k.mountOwned("patter",T,{owner:ce}),h.push("patter");let m=new Set;for(let[S,O]of Object.entries(Dt(t))){let D=e.scopeRegistry?.scopes.find(cn=>cn.token===S),fe=(D?.declarations??[]).map(Pt);k.defineForeign(S,O,fe,{writable:D?.writable??!0,owner:ce}),h.push(S),m.add(S)}for(let S of L?e.scopeRegistry?.scopes??[]:[]){if(m.has(S.token)||k.has(S.token))continue;let O=(S.declarations??[]).map(D=>Bn(D,S.writable));k.defineOwned(S.token,O,{owner:ce}),h.push(S.token),F.push(S.token)}}catch(m){for(let S of h)k.remove(S,{keep:!0});throw m}let C=new Map;for(let[m,S]of Object.entries(e.scenes)){let O=new Set((S.sceneProps??[]).filter(D=>D.shared??!1).map(D=>D.name.toLowerCase()));C.set(m,O)}this.host={logEnabled:t.log??!1,tracing:t.log??!1,emitEngine:(m,S,O)=>this.emitEngine(m,S,O),bundle:e,emitIds:l,strings:i,defaultStrings:o,castDisplay:c,qualifierDisplay:p,speakerLabels:d,speakerPattern:f,nodeIndex:g,blockIndex:y,blockById:u,sceneGameIdToId:this.sceneGameIdToId,blockGameIdToId:this.blockGameIdToId,tagIndex:In(e),padIndex:On(e),registry:k,ownsRegistry:L,patterBag:T,hostScopes:F,patterSharedDecls:I,patterLocalDecls:R,patterSharedNames:N,sceneSharedNames:C,sharedVisits:new Map,qualityLadders:new Map,sharedSelectors:new Map,stageBags:new Map,journal:null,customRng:t.rng,onDryChoice:t.onDryChoice,onError:t.onError??(m=>console.warn(`Patterplay: ${m.kind} on ${m.node} in flow '${m.flow}' failed, played through: ${m.message}`)),reportRefits:()=>{let m=k.takeMisfits(S=>S==="patter"||S.startsWith("patter/")||F.includes(S));if(m.length!==0)if(t.onRefit)t.onRefit(m);else for(let S of m)console.warn(`Patterplay: the save's ${S.scope}.${S.name} was ${JSON.stringify(S.value)}, which no longer fits its declaration; it is back at its default`)},replayPromptOnChoose:t.replayPromptOnChoose??!1,captionsOn:t.closedCaptions??!0,captionOpen:(e.closedCaptions??$e).open,captionClose:(e.closedCaptions??$e).close,captionCharacter:e.closedCaptions?.character||gt,refSplitCache:new Map,refSplitRevision:k.revision},this.host.reportRefits()}get locale(){return this.currentLocale}get isSourceDebug(){return this.sourceDebug}get buildId(){return this.host.bundle.content?.hash??""}setLocale(e){this.currentLocale=e,this.host.strings=this.allStrings[e]??{}}replaceStrings(e){this.allStrings=e.strings,this.host.strings=this.allStrings[this.currentLocale]??{},this.host.defaultStrings=this.allStrings[this.host.bundle.locales.default]??{}}hotSwap(e){this.refuseInCheckpoint("hotSwap");let t=this.saveGame(),n=l=>(l.setLocale(this.currentLocale),l.setClosedCaptions(this.host.captionsOn),l),s=()=>new r(e,{...this.creationOptions,registry:this.host.registry,[wt]:this.host.ownsRegistry}),i=new Set(["patter",...this.host.hostScopes]),o=this.host.ownsRegistry?void 0:Object.fromEntries(Object.entries(this.host.registry.save()).filter(([l])=>i.has(l)||l.startsWith("patter/")));this.release(!0),o&&this.host.registry.load(o,{keepParked:!0,refit:!0});let a=s();try{return a.loadGame(t),n(a)}catch{a.release(!0);let l=this.host.ownsRegistry?t.registry:o;l&&this.host.registry.load(l,{keepParked:!0,refit:!0});let c=s();for(let[p,d]of Object.entries(t.flows)){let f=d.cursor.currentSceneId;try{c.openFlow(p,f!==null?{scene:f}:{})}catch{}}return n(c)}}get closedCaptions(){return this.host.captionsOn}setClosedCaptions(e){this.host.captionsOn=e}openFlow(e,t={}){this.assertExternalScopes();let{sceneId:n,blockId:s}=this.resolveOpenAddress(t.scene,t.block),i=this.flowsById.get(e),o=this.host.journal;if(o&&i&&!i.isClosed)throw new Error(`openFlow would replace the open flow '${e}', which can't be undone while a checkpoint is open`);i?.close();let a=new _(e,this.host,t.seed??this.defaultSeed);return o&&(o.flows.add(a),o.opened.add(a),o.undo.push(()=>{a.close(),i?this.flowsById.set(e,i):this.flowsById.delete(e)})),this.flowsById.set(e,a),a.begin(n,s),a}runFlow(e,t,n){let s=this.flowsById.get(e);if(!s)return this.openFlow(e,{scene:t,block:n}).advanceToStop().played;if(!s.goto(t,n))throw new Error(`runFlow: address not found: ${t}${n===void 0?"":` / ${n}`}`);return s.advanceToStop().played}assertExternalScopes(){for(let e of this.host.bundle.externalScopes??[])if(!this.host.registry.has(e))throw new Error(`this content names @${e}, which no engine on this registry registered: give every engine the game's one registry`)}resolveOpenAddress(e,t){if(e!==void 0){let n=je(this.host,e);if(n===void 0)throw new Error(`unknown scene: ${e}`);if(t===void 0)return{sceneId:n};let s=Ve(this.host,n,t);if(s===void 0)throw new Error(`unknown block: ${t}`);return{sceneId:n,blockId:s}}if(t!==void 0){if(!this.host.blockIndex.has(t))throw new Error(`unknown block: ${t}`);return{blockId:t}}if(Object.keys(this.host.bundle.scenes).length===0)throw new Error("no scenes in bundle");return{}}resolveSceneRef(e){if(e!=null)return je(this.host,e)??e}resolveBlockRef(e,t){if(t!=null)return e==null?t:Ve(this.host,e,t)}sceneAddress(e){let t=this.host.bundle.scenes[e];return t?E(t):void 0}blockAddress(e){let t=this.host.blockById.get(e);return t?E(t):void 0}tagsForBeat(e){return H(this.host,e)??[]}tagsForScene(e){let t=this.resolveSceneRef(e);return(t!=null?H(this.host,t):void 0)??[]}tagsForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t);return(s!=null?H(this.host,s):void 0)??[]}gameDataForScene(e){let t=this.resolveSceneRef(e);return{...(t!=null?this.host.bundle.scenes[t]:void 0)?.gameData}}gameDataForBlock(e,t){let n=this.resolveBlockRef(this.resolveSceneRef(e),t);return{...(n!=null?this.host.blockById.get(n):void 0)?.gameData}}extensionsForScene(e){let t=this.resolveSceneRef(e);return{...(t!=null?this.host.bundle.scenes[t]:void 0)?.extensions}}extensionsForBlock(e,t){let n=this.resolveBlockRef(this.resolveSceneRef(e),t);return{...(n!=null?this.host.blockById.get(n):void 0)?.extensions}}extensionsForSnippet(e){let t=this.host.nodeIndex.get(e);return t?.type==="snippet"?{...t.extensions}:{}}getCast(){let e=[];for(let t of this.host.bundle.cast??[])t?.name&&e.push(t.name);return e}castForScene(e){let t=this.resolveSceneRef(e),n=t!=null?this.host.bundle.scenes[t]:void 0;if(!n)return[];let s=new Set;for(let i of n.blocks)xt(i.children,s);return[...s]}castForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t),i=s!=null?this.host.blockById.get(s):void 0;if(!i)return[];let o=new Set;return xt(i.children,o),[...o]}getOutline(){return Object.values(this.host.bundle.scenes).map(e=>({id:e.id,...E(e)?{gameId:E(e)}:{},name:e.name,...kt(e.gameData),...M(e.extensions),...this.tagsField(e.id),blocks:e.blocks.map(t=>({id:t.id,...E(t)?{gameId:E(t)}:{},name:t.name,...kt(t.gameData),...M(t.extensions),...this.tagsField(t.id),children:t.children.map(n=>this.outlineNode(n))}))}))}getBeatSequence(){let e=[];for(let t of Object.values(this.host.bundle.scenes))for(let n of t.blocks)q(n.children,s=>{if(s.type==="snippet")for(let i of s.beats??[])e.push({sceneId:t.id,blockId:n.id,snippetId:s.id,beat:this.beatInfo(i)})});return e}outlineNode(e){return e.type==="group"?{type:"group",id:e.id,...this.tagsField(e.id),...e.selector?{selector:e.selector}:{},...e.prompt?{prompt:this.beatInfo(e.prompt)}:{},children:e.children.map(t=>this.outlineNode(t))}:{type:"snippet",id:e.id,...this.tagsField(e.id),beats:(e.beats??[]).map(t=>this.beatInfo(t)),...e.jump?{jumpTo:e.jump.to,...e.jump.mode?{jumpMode:e.jump.mode}:{}}:{}}}beatInfo(e){let t=H(this.host,e.id),n={id:e.id,kind:e.kind};if(e.kind==="line"){if(e.character!==void 0){n.character=e.character;let i=this.host.defaultStrings[Se(e.character)]??this.host.castDisplay.get(e.character);i!==void 0&&(n.characterName=i)}if(e.direction!==void 0&&(n.direction=e.direction),e.qualifier!==void 0){n.qualifier=e.qualifier;let i=this.host.defaultStrings[we(e.qualifier)]??this.host.qualifierDisplay.get(e.qualifier);i!==void 0&&(n.qualifierName=i)}let s=le(this.host,e.character,e.qualifier,!0);s!==void 0&&(n.speakerLabel=s)}if(e.kind==="line"||e.kind==="text"){let s=this.host.padIndex.get(e.id);n.padAfter=s?.resolved??j,s?.own!==void 0&&(n.ownPadAfter=s.own);let i=this.host.defaultStrings[e.id];i!==void 0&&(n.text=i)}return e.gameData&&Object.keys(e.gameData).length&&(n.gameData=e.gameData),e.extensions&&Object.keys(e.extensions).length&&(n.extensions=e.extensions),t&&t.length&&(n.tags=t),n}tagsField(e){let t=H(this.host,e);return t&&t.length?{tags:t}:{}}getFlow(e){return this.flowsById.get(e)}flows(){return[...this.flowsById.values()]}listBags(){let e=[{bag:this.host.patterBag}];for(let[t,n]of this.host.stageBags)e.push({bag:n,pathPrefix:`@scene:${t}.`});return e}checkpoint(){if(this.host.journal)throw new Error("a checkpoint is already open: roll it back or commit it first");let e={undo:[],flows:new Set,opened:new Set,selectors:new Set,flowSelectors:new Map};return this.host.journal=e,new pe(e)}rollback(e){this.endCheckpoint(e);let t=e.journal.undo;for(let n=t.length-1;n>=0;n--)t[n]();r.forget(e.journal)}commit(e){this.endCheckpoint(e),r.forget(e.journal)}get inCheckpoint(){return this.host.journal!==null}endCheckpoint(e){if(this.host.journal!==e.journal)throw new Error("that checkpoint is not the open one");this.host.journal=null}static forget(e){e.undo=[],e.flows.clear(),e.opened.clear(),e.selectors.clear(),e.flowSelectors.clear()}refuseInCheckpoint(e){if(this.host.journal)throw new Error(`${e} can't be undone, so it isn't allowed while a checkpoint is open`)}captureFlow(e){let t=this.flowsById.get(e);if(!t)throw new Error(`no open flow '${e}' to capture`);return{version:se,...t.snapshot(),...Tn(e,this.host.registry.save())}}restoreFlow(e,t){this.refuseInCheckpoint("restoreFlow");let n=t.version;if(n!==2&&n!==se)throw new Error(`unsupported flow state version: ${String(n)}`);let s=t.cursor;if(typeof s!="object"||s===null)throw new Error("malformed flow state: no cursor");if(this.flowsById.has(e))throw new Error(`a flow '${e}' is already open; close it before restoring another under that id`);this.assertExternalScopes();let i=P.flow(e);this.host.registry.discardParked(i),this.host.registry.load(Nt(e,t),{keepParked:!0,refit:!0});let o=new _(e,this.host,this.defaultSeed);try{o.restore(t)}catch(a){throw o.close(),this.host.registry.discardParked(i),a}return this.flowsById.set(e,o),this.host.reportRefits(),o}closeFlow(e){this.refuseInCheckpoint("closeFlow"),this.flowsById.get(e)?.close(),this.flowsById.delete(e)}reset(){this.refuseInCheckpoint("reset");for(let e of this.flowsById.values())e.close();this.flowsById.clear(),this.host.patterBag.reseed(this.host.patterSharedDecls),this.host.sharedVisits.clear(),this.host.sharedSelectors.clear();for(let e of this.host.stageBags.keys())this.host.registry.remove(P.stage(e));this.host.stageBags.clear(),this.host.registry.discardParked("patter/")}release(e){for(let n of this.flowsById.values())n.releaseBags(e),n.close();this.flowsById.clear();let t=this.host.registry;for(let n of this.host.stageBags.keys())t.remove(P.stage(n),{keep:e});this.host.stageBags.clear();for(let n of["patter",...this.host.hostScopes])t.has(n)&&t.remove(n,{keep:e});for(let n of Object.keys(Dt(this.creationOptions)))t.has(n)&&t.remove(n)}getProperty(e){let{scope:t,name:n}=this.splitShared(e);return this.host.registry.get(t,n)}setProperty(e,t){let{scope:n,name:s}=this.splitShared(e),i=this.host.journal?this.host.registry.get(n,s):void 0;this.host.registry.set(n,s,t,{host:!0}),this.host.journal&&i!==void 0&&this.host.journal.undo.push(()=>this.host.registry.set(n,s,i,{host:!0}))}stageIndex(e,t){return U(this.ladderOf(e),t)}compareStages(e,t,n){return W(this.ladderOf(e),t,n)}nextStage(e,t){return J(this.ladderOf(e),t)}ladderOf(e){let{scope:t,name:n}=this.splitShared(e),s=Ln(this.host,t,n);if(!s)throw new Error(`'${e}' is not a quality`);return s}log(){return this.engineLog}clearLog(){this.engineLog.length=0}onTrace(e){return this.engineTraceHandlers.add(e),this.host.tracing=!0,()=>{this.engineTraceHandlers.delete(e),this.host.tracing=this.host.logEnabled||this.engineTraceHandlers.size>0}}emitEngine(e,t,n){for(let s of this.engineTraceHandlers)s(e,t);this.host.logEnabled&&this.engineLog.push({...t,flow:e,seq:this.engineSeq++,...n?{scene:n}:{}})}getVisitCounts(){return Object.fromEntries(this.host.sharedVisits)}listProperties(){return this.host.patterSharedDecls.map(e=>({name:e.name,path:`@patter.${e.name}`,type:e.type,values:e.values,stages:e.stages,value:this.getProperty(`@${e.name}`),default:K(e),writable:e.writable??!0}))}splitShared(e){let t=At(this.host,e);if(t.scope==="scene")throw new Error(`'${e}': @scene properties are scene-scoped - read/write them on a Flow, not the Engine`);return t}save(){return{patter:this.host.patterBag.save()}}load(e){e.patter&&this.host.patterBag.load(e.patter)}saveGame(){let e={};for(let[t,n]of this.flowsById)e[t]=n.snapshot();return{version:se,...this.host.ownsRegistry?{registry:this.host.registry.save()}:{},sharedVisits:Object.fromEntries(this.host.sharedVisits),sharedSelectors:It(this.host.sharedSelectors),flows:e}}loadGame(e){this.refuseInCheckpoint("loadGame");let t=e.version;if(t!==2&&t!==se)throw new Error(`unsupported save version: ${String(t)}`);let n=e.flows;if(typeof n!="object"||n===null||Array.isArray(n))throw new Error("malformed save: no flows");this.assertExternalScopes();let s=this.host.registry;for(let[o,a]of this.flowsById)a.releaseBags(o in e.flows),a.close();this.flowsById.clear();for(let o of this.host.stageBags.keys())s.remove(P.stage(o),{keep:!0});this.host.stageBags.clear();let i=e.version===2?Mn(e):e.registry;i&&(this.host.ownsRegistry?s.load(i,{refit:!0}):s.load(i,{keepParked:!0,refit:!0})),this.host.sharedVisits.clear();for(let[o,a]of Object.entries(e.sharedVisits??{}))this.host.sharedVisits.set(o,a);this.host.sharedSelectors.clear();for(let[o,a]of Ot(e.sharedSelectors))this.host.sharedSelectors.set(o,a);for(let[o,a]of Object.entries(e.flows)){let l=new _(o,this.host,this.defaultSeed);l.restore(a),this.flowsById.set(o,l)}this.host.reportRefits()}},_=class{id;host;local;registered=new Set;rngState;started=!1;flowEnded=!1;closed=!1;currentSceneId=null;stack=[];activeSnippet=null;beatIndex=0;pendingChoice=null;pendingPrompt=null;pendingPromptOwnerId=null;selectors=new Map;visitCounts=new Map;sceneBags=new Map;patterResolver={get:e=>this.host.patterSharedNames.has(e)?this.host.patterBag.get(e):this.local.get(e),set:(e,t)=>{this.host.patterSharedNames.has(e)?this.host.registry.set("patter",e,t):this.local.set(e,t)}};sceneResolver={get:e=>{let t=this.currentSceneId;if(t!==null)return this.sceneBagFor(t,e)?.get(e)},set:(e,t)=>{let n=this.currentSceneId;if(n===null)return;let s=this.sceneBagFor(n,e);s&&s.set(e,t)}};evalCtx;ctxRevision=-1;registryQualities;flowLog=[];flowSeq=0;constructor(e,t,n){this.id=e,this.host=t,this.rngState=te(n),this.local=this.newLocal(),this.evalCtx={scopes:{},host:{nextRandom:this.rng,visits:s=>this.visitCounts.get(s)??0,patterVisits:s=>this.host.sharedVisits.get(s)??0},qualities:(s,i)=>this.stagesFor(s,i)}}context(){let e=this.host.registry;if(e.revision!==this.ctxRevision){let t=e.toEvalContext(),n=this.evalCtx.scopes;for(let s of Object.keys(n))delete n[s];Object.assign(n,t.scopes),n.patter=this.patterResolver,n.scene=this.sceneResolver,this.registryQualities=t.qualities,this.ctxRevision=e.revision}return this.evalCtx}stagesFor(e,t){let n=t.toLowerCase();if(e==="patter")return de(this.host,"patter",()=>[...this.host.patterSharedDecls,...this.host.patterLocalDecls]).get(n);if(e==="scene"){let s=this.currentSceneId;return s==null?void 0:de(this.host,`scene/${s}`,()=>this.host.bundle.scenes[s]?.sceneProps).get(n)}return this.registryQualities?.(e,t)??de(this.host,`host/${e}`,()=>this.host.bundle.scopeRegistry?.scopes.find(s=>s.token===e)?.declarations).get(n)}begin(e,t){if(this.host.journal&&!this.host.journal.opened.has(this))throw new Error("a flow can't be started or reset while a checkpoint is open");if(this.releaseBags(!1),this.host.registry.discardParked(P.flow(this.id)),this.mountLocal(),this.selectors.clear(),this.visitCounts.clear(),this.stack=[],this.currentSceneId=null,this.flowEnded=!1,this.activeSnippet=null,this.beatIndex=0,this.clearPending(),this.started=!0,t){let n=this.host.blockIndex.get(t);if(!n)throw new Error(`unknown block: ${t}`);this.enterSceneSetup(n.sceneId),this.stack=[{sceneId:n.sceneId,containerId:t,index:0}],this.enter(t)}else{let n=e??Object.keys(this.host.bundle.scenes)[0],s=n?this.host.bundle.scenes[n]:void 0;if(!s)throw new Error(n?`unknown scene: ${n}`:"no scenes in bundle");this.enterSceneSetup(n);let i=s.blocks[0];i&&(this.stack=[{sceneId:n,containerId:i.id,index:0}],this.enter(i.id))}this.settle()}reset(e,t){this.begin(e,t)}start(e,t){this.reset(e,t)}goto(e,t){if(this.closed)return!1;if(this.touch(),e==="END")return this.started=!0,this.clearPending(),this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!0,this.stack=[],!0;let n=je(this.host,e);if(n===void 0)return!1;let s;return t!==void 0&&(s=Ve(this.host,n,t),s===void 0)?!1:this.started?(this.clearPending(),this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!1,this.enterTarget(s??n,"jump"),this.settle(),!0):(this.begin(n,s),!0)}close(){this.releaseBags(!1),this.closed=!0,this.flowEnded=!0,this.stack=[],this.activeSnippet=null,this.beatIndex=0,this.clearPending()}clearPending(){this.pendingChoice=null,this.pendingPrompt=null,this.pendingPromptOwnerId=null}touch(){let e=this.host.journal;if(!e||e.flows.has(this))return;e.flows.add(this);let{rngState:t,started:n,flowEnded:s,currentSceneId:i,activeSnippet:o,beatIndex:a,pendingChoice:l,pendingPrompt:c,pendingPromptOwnerId:p}=this,d=this.stack.map(f=>({...f}));e.undo.push(()=>{Object.assign(this,{rngState:t,started:n,flowEnded:s,currentSceneId:i,activeSnippet:o,beatIndex:a,pendingChoice:l,pendingPrompt:c,pendingPromptOwnerId:p,stack:d})})}get isClosed(){return this.closed}get currentScene(){return this.currentSceneId}advance(){if(this.closed)return{type:"end"};if(!this.started)throw new Error("flow has not been started");if(this.touch(),this.pendingPrompt){let e=this.pendingPrompt;return this.pendingPrompt=null,this.pendingPromptOwnerId=null,e.shown?this.promptResult(e.beat,e.shown):this.beatResult(e.beat)}return this.settle(),this.flowEnded?{type:"end"}:this.pendingChoice?{type:"choice",groupId:this.pendingChoice.groupId,options:this.pendingChoice.options}:this.activeSnippet?this.beatResult(this.activeSnippet.beats[this.beatIndex++]):(this.flowEnded=!0,{type:"end"})}advanceToStop(){let e=[];for(;;){let t=this.advance();if(t.type==="choice"||t.type==="end")return{played:e,stop:t};e.push(t)}}settle(){let e=0;for(;;){if(++e>1e4)throw new Error("flow did not settle after 10000 transitions - likely a jump cycle with no deliverable content");if(this.flowEnded||this.pendingChoice)return;if(this.activeSnippet){if(this.beatIndex<(this.activeSnippet.beats?.length??0))return;this.runEffects(this.activeSnippet.onExit,this.activeSnippet.id);let i=this.activeSnippet.jump;this.activeSnippet=null,this.beatIndex=0,this.resolveJump(i);continue}let t=this.stack[this.stack.length-1];if(!t){this.flowEnded=!0;return}t.sceneId!==this.currentSceneId&&(this.currentSceneId=t.sceneId);let n=this.childrenOf(t.containerId);if(!n){this.stack.pop();continue}let s=t.index;for(;t.index<n.length&&!this.eligible(n[t.index]);)t.index++;if(this.host.tracing&&t.index!==s&&this.emit({type:"select",group:t.containerId,selector:"run",children:n.slice(s,t.index+1).map((i,o)=>({id:i.id,eligible:s+o===t.index})),picked:n[t.index]?.id??null}),t.index>=n.length){this.stack.pop();continue}this.enterChild(n[t.index++])}}listBags(){let e=[{bag:this.local,pathPrefix:`${this.id}/@patter.`}];for(let[t,n]of this.sceneBags)e.push({bag:n,pathPrefix:`${this.id}/@scene:${t}.`});return e}log(){return this.flowLog}clearLog(){this.flowLog.length=0}emit(e){let t=this.currentSceneId??void 0;this.host.emitEngine(this.id,e,t),this.host.logEnabled&&this.flowLog.push({...e,seq:this.flowSeq++,...t?{scene:t}:{}})}getVisitCounts(){return Object.fromEntries(this.visitCounts)}stepFor(e){let t=Pn(this.host.bundle).get(e);return t?this.beatResult(t):void 0}getChoices(){return this.pendingChoice?.options??[]}choose(e){let t=this.pendingChoice;if(!t)throw new Error("no choice is pending");let n=t.options.find(o=>o.id===e);if(!n)throw new Error(`unknown choice option: ${e}`);if(!n.eligible)throw new Error(`choice option is not eligible: ${e}`);this.touch();let s=t.byId.get(e);this.host.tracing&&this.emit({type:"chose",group:t.groupId,option:e}),this.pendingChoice=null;let i=this.host.replayPromptOnChoose?this.authoredPromptOf(s):void 0;this.pendingPrompt=i&&n.prompt?{beat:i,shown:{...n.prompt}}:null,this.pendingPromptOwnerId=this.pendingPrompt?s.id:null,this.enterChild(s)}isEnded(){return this.flowEnded}getProperty(e){let{scope:t,name:n}=this.splitRef(e);return t==="patter"?this.patterResolver.get(n):t==="scene"?this.sceneResolver.get(n):this.host.registry.get(t,n)}setProperty(e,t){this.writeProperty(e,t,!0)}stageIndex(e,t){return U(this.ladderOf(e),t)}compareStages(e,t,n){return W(this.ladderOf(e),t,n)}nextStage(e,t){return J(this.ladderOf(e),t)}ladderOf(e){let{scope:t,name:n}=this.splitRef(e);this.context();let s=this.stagesFor(t,n);if(!s)throw new Error(`'${e}' is not a quality`);return s}writeProperty(e,t,n){let{scope:s,name:i}=this.splitRef(e),o=this.host.journal;if(s==="patter"){if(o){let a=this.host.patterSharedNames.has(i),l=a?this.host.patterBag.get(i):this.local.get(i),c=this.local;l!==void 0&&o.undo.push(a?()=>this.host.registry.set("patter",i,l):()=>c.set(i,l))}this.patterResolver.set(i,t)}else if(s==="scene"){if(this.currentSceneId===null)throw new Error(`'${e}': the flow has not entered a scene yet`);if(o){let a=this.sceneBagFor(this.currentSceneId,i),l=a?.get(i);a&&l!==void 0&&o.undo.push(()=>a.set(i,l))}this.sceneResolver.set(i,t)}else{let a=o?this.host.registry.get(s,i):void 0;this.host.registry.set(s,i,t,n?{host:!0}:void 0),o&&a!==void 0&&o.undo.push(()=>this.host.registry.set(s,i,a,{host:!0}))}}snapshot(){return{rngState:this.rngState,visits:Object.fromEntries(this.visitCounts),cursor:{flowEnded:this.flowEnded,currentSceneId:this.currentSceneId,stack:this.stack.map(e=>{let t=this.childrenOf(e.containerId)?.[e.index];return t?{...e,nextId:t.id}:{...e}}),activeSnippetId:this.activeSnippet?.id??null,beatIndex:this.beatIndex,pendingChoice:this.pendingChoice?{groupId:this.pendingChoice.groupId,options:this.pendingChoice.options.map(({extensions:e,...t})=>({...t}))}:null,pendingPromptOwnerId:this.pendingPromptOwnerId,...this.pendingPrompt?.shown?{pendingPrompt:Nn(this.pendingPrompt.shown)}:{},selectors:It(this.selectors)}}}restore(e){if(this.host.journal)throw new Error("a flow can't be restored while a checkpoint is open");this.restoreCursor(e),this.releaseBags(!0),this.mountLocal();for(let t of new Set([this.currentSceneId,...this.stack.map(n=>n.sceneId)]))t!==null&&this.host.bundle.scenes[t]&&this.ensureSceneBags(t)}restoreCursor(e){this.rngState=te(e.rngState),this.visitCounts=new Map(Object.entries(e.visits??{}));let t=e.cursor;if(this.started=!0,this.flowEnded=t.flowEnded,this.beatIndex=t.beatIndex,this.currentSceneId=t.currentSceneId,this.stack=t.stack.map(n=>{let{nextId:s,...i}=n;if(s!==void 0){let o=this.childrenOf(i.containerId)?.findIndex(a=>a.id===s)??-1;if(o>=0)return{...i,index:o}}return{...i}}),this.activeSnippet=null,t.activeSnippetId!==null){let n=this.host.nodeIndex.get(t.activeSnippetId);n&&n.type==="snippet"&&(this.activeSnippet=n)}if(this.selectors=Ot(t.selectors),this.pendingChoice=null,t.pendingChoice!==null){let n=new Map,s=[];for(let i of t.pendingChoice.options){let o=this.host.nodeIndex.get(i.id);if(!o)continue;n.set(i.id,o);let{prompt:a,extensions:l,...c}=i,p=a?.kind==="line"&&a.speakerLabel===void 0?le(this.host,a.character,a.qualifier):void 0;s.push({...c,...a?{prompt:{...a,padAfter:a.padAfter??this.promptPadOf(o),...p!==void 0?{speakerLabel:p}:{}}}:{},...M(o.extensions)})}s.length>0&&(this.pendingChoice={groupId:t.pendingChoice.groupId,options:s,byId:n})}if(this.pendingPrompt=null,this.pendingPromptOwnerId=t.pendingPromptOwnerId??null,this.pendingPromptOwnerId){let n=this.host.nodeIndex.get(this.pendingPromptOwnerId),s=n?this.authoredPromptOf(n):void 0,i=t.pendingPrompt,o=i?.kind==="line"&&i.speakerLabel===void 0?le(this.host,i.character,i.qualifier):void 0;s?this.pendingPrompt={beat:s,...i?{shown:{...i,padAfter:i.padAfter??this.padOf(s.id),...o!==void 0?{speakerLabel:o}:{}}}:{}}:this.pendingPromptOwnerId=null}}enterSceneSetup(e){let t=this.host.bundle.scenes[e];if(!t)throw new Error(`unknown scene: ${e}`);this.currentSceneId=e,this.enter(e),this.seedScene(t),this.runEffects(t.onEntry,t.id)}enterChild(e){if(this.enter(e.id),e.type==="snippet"){this.beginSnippet(e);return}let t=e.selector??"run";if(t==="run"){this.stack.push({sceneId:this.currentSceneId,containerId:e.id,index:0});return}if(t==="choice"){this.setupChoice(e);return}let n=this.selectChild(e);n&&this.enterChild(n)}childrenOf(e){let t=this.host.blockById.get(e);if(t)return t.children;let n=this.host.nodeIndex.get(e);if(n&&n.type==="group")return n.children}beginSnippet(e){this.runEffects(e.onEnter,e.id),this.activeSnippet=e,this.beatIndex=0}setupChoice(e){let t=[],n=new Map,s=[];for(let o of e.children){if(o.fallback===!0){s.push(o);continue}if(o.sticky!==!0&&(this.visitCounts.get(o.id)??0)>=1)continue;let a=this.eligible(o),l=o.secretUntilEligible===!0;!a&&l||(t.push({id:o.id,prompt:this.promptFor(o),eligible:a,gameData:o.gameData,...M(o.extensions)}),n.set(o.id,o))}if(t.some(o=>o.eligible)){this.host.tracing&&this.emit({type:"choice",group:e.id,options:t.map(o=>({id:o.id,eligible:o.eligible}))}),this.pendingChoice={groupId:e.id,options:t,byId:n};return}let i=s.find(o=>this.eligible(o));if(i){this.enterChild(i);return}this.host.tracing&&this.emit({type:"dry",group:e.id}),this.host.onDryChoice?.(e.id)}resolveJump(e){e&&this.enterTarget(e.to,e.mode==="call"?"call":"jump")}enterTarget(e,t){if(this.host.tracing&&this.emit({type:"jump",to:e,mode:t}),e==="END"){this.flowEnded=!0,this.stack=[];return}let n,s,i=this.host.bundle.scenes[e];if(i){this.enterSceneSetup(e);let a=i.blocks[0];if(!a){t==="jump"&&(this.stack=[]);return}n=e,s=a.id}else{let a=this.host.blockIndex.get(e);if(!a)throw new Error(`jump target not found: ${e}`);a.sceneId!==this.currentSceneId&&this.enterSceneSetup(a.sceneId),n=a.sceneId,s=e}this.enter(s);let o={sceneId:n,containerId:s,index:0};t==="call"?this.stack.push(o):this.stack=[o]}selectChild(e){let t=e.children.map(l=>({id:l.id,eligible:this.eligible(l)})),n=e.children.filter((l,c)=>t[c].eligible),s=e.options?.order??"sequential",i=e.options?.exhaust??"once",o=l=>(this.host.tracing&&this.emit({type:"select",group:e.id,selector:e.selector??"default",...e.selector==="sequence"?{order:s,exhaust:i}:{},children:t,picked:l?.id??null}),l);if(n.length===0)return o(null);let a=this.selectorState(e);switch(e.selector){case"branch":return o(n[0]);case"sequence":return o(s==="shuffle"?this.pickShuffle(n,i,a):s==="specificity"?this.pickSpecificity(n,i,a):this.pickSequential(n,i,a));default:return null}}pickSequential(e,t,n){let s=e.length,i=n.seq??0;return n.seq=i+1,t==="repeat"?e[i%s]:i<s?e[i]:t==="stick"?e[s-1]:null}pickShuffle(e,t,n){let s=e.length,i=t==="stick",o=()=>(i?e.slice(0,s-1):e).map(f=>f.id),a=new Set(e.map(f=>f.id));if(n.bag===void 0&&(n.bag=o()),!n.bag.some(f=>a.has(f))){if(t==="once")return null;if(i){let f=e[s-1];return n.last=f.id,f}if(n.bag=o(),n.bag.length===0)return null}let l=n.bag.filter(f=>a.has(f)),c=n.last!==void 0&&l.length>1?l.indexOf(n.last):-1,p=Math.floor(this.rng()*(c>=0?l.length-1:l.length));c>=0&&p>=c&&p++;let d=l[p];return n.bag.splice(n.bag.indexOf(d),1),n.last=d,e.find(f=>f.id===d)}pickSpecificity(e,t,n){let s=e;if(t!=="repeat"){n.bag===void 0&&(n.bag=e.map(p=>p.id));let c=new Set(n.bag);if(s=e.filter(p=>c.has(p.id)),s.length===0)return t==="stick"&&n.last!==void 0?e.find(p=>p.id===n.last)??null:null}let i=-1,a=s.map(c=>{let p=this.specScore(c);return p>i&&(i=p),{c,s:p}}).filter(c=>c.s===i).map(c=>c.c),l;if(a.length===1)l=a[0];else{let c=n.last!==void 0?a.findIndex(d=>d.id===n.last):-1,p=Math.floor(this.rng()*(c>=0?a.length-1:a.length));c>=0&&p>=c&&p++,l=a[p]}return t!=="repeat"&&(n.bag=n.bag.filter(c=>c!==l.id)),n.last=l.id,l}specScore(e){return e.condition?this.matchedSpec(this.conditionAst(e.condition),!0,e):0}matchedSpec(e,t,n){return Ze(e,i=>{try{return Rt(ge(i,this.context(),Te))}catch(o){return this.reportError("best-match",n.id,n.condition,o),!1}},{want:t})}selectorState(e){let t=e.shared?this.host.sharedSelectors:this.selectors,n=this.host.journal,s;if(n&&(s=e.shared?n.selectors:n.flowSelectors.get(this),s||(s=new Set,n.flowSelectors.set(this,s))),n&&s&&!s.has(e.id)){s.add(e.id);let o=t.get(e.id),a=o?{...o,...o.bag?{bag:[...o.bag]}:{}}:void 0;n.undo.push(()=>{a?t.set(e.id,a):t.delete(e.id)})}let i=t.get(e.id);return i||(i={},t.set(e.id,i)),i}runEffects(e,t){for(let n of e??[]){let s;try{s=this.evalExpr(n.value);let i=this.host.tracing?this.getProperty(n.target):void 0;this.writeProperty(n.target,s,!1),this.host.tracing&&this.emit({type:"write",target:n.target,value:s,...i!==void 0?{prev:i}:{}})}catch(i){this.reportError("effect",t,n.value,i)}}}eligible(e){if(!e.condition)return!0;try{return Rt(this.evalExpr(e.condition))}catch(t){return this.reportError("condition",e.id,e.condition,t),!1}}reportError(e,t,n,s){let i=s instanceof Error?s.message:String(s),o=n?.src;this.host.onError({flow:this.id,kind:e,node:t,...o?{source:o}:{},message:i}),this.host.tracing&&this.emit({type:"diagnostic",kind:e,node:t,...o?{source:o}:{},message:i})}evalExpr(e){return ge(this.conditionAst(e),this.context(),Te)}conditionAst(e){let t=yt.get(e);return t||(t=V(e.ast),yt.set(e,t)),t}enter(e){let t=this.visitCounts,n=t.get(e);t.set(e,(n??0)+1);let s=this.host.sharedVisits,i=s.get(e);s.set(e,(i??0)+1),this.host.journal&&this.host.journal.undo.push(()=>{n===void 0?t.delete(e):t.set(e,n),i===void 0?s.delete(e):s.set(e,i)})}rng=()=>{if(this.host.customRng)return this.host.customRng();let e=Pe(this.rngState),t=e.next();return this.rngState=e.state(),t};beatResult(e){let t=H(this.host,e.id),n=t&&t.length?{tags:t}:{};switch(e.kind){case"gameEvent":return{type:"gameEvent",id:e.id,gameData:e.gameData,...M(e.extensions),...n};case"text":return{type:"text",id:e.id,text:this.interpolate(this.resolveString(e.id)),padAfter:this.padOf(e.id),...e.action?{action:!0}:{},gameData:e.gameData,...M(e.extensions),...n};case"line":{let s=this.resolveString(e.id),i=!this.host.captionsOn,a=i&&e.character===this.host.captionCharacter?"":this.captionLine(this.host.bundle.voiced?s:this.interpolate(s)),l=i&&a.length===0;return{type:"line",id:e.id,text:a,character:l?void 0:e.character,characterName:l?void 0:this.resolveCharacterName(e.character),direction:l?void 0:e.direction,qualifier:l?void 0:e.qualifier,qualifierName:l?void 0:this.resolveQualifierName(e.qualifier),speakerLabel:l?void 0:le(this.host,e.character,e.qualifier),padAfter:this.padOf(e.id),gameData:e.gameData,...M(e.extensions),...n}}}}interpolate(e){return ct(e,t=>this.getProperty(t))}stripCaptions(e){return lt(e,this.host.captionOpen,this.host.captionClose)}captionLine(e){return this.host.captionsOn?e:this.stripCaptions(e)}promptFor(e){let t=this.promptBeatOf(e);if(!t)return;let n=this.interpolate(this.resolveString(t.id)),s=this.padOf(t.id);return t.kind==="line"?{kind:"line",text:this.captionLine(n),character:t.character,characterName:this.resolveCharacterName(t.character),direction:t.direction,qualifier:t.qualifier,qualifierName:this.resolveQualifierName(t.qualifier),speakerLabel:le(this.host,t.character,t.qualifier),padAfter:s}:{kind:"text",text:n,padAfter:s}}authoredPromptOf(e){return e.type==="group"?e.prompt:void 0}promptResult(e,t){let n=H(this.host,e.id),s=n&&n.length?{tags:n}:{};return t.kind==="text"?{type:"text",id:e.id,text:t.text,padAfter:this.padOf(e.id),gameData:e.gameData,...M(e.extensions),...s}:{type:"line",id:e.id,text:t.text,character:t.character,characterName:t.characterName,direction:t.direction,qualifier:t.qualifier,qualifierName:t.qualifierName,speakerLabel:t.speakerLabel,padAfter:this.padOf(e.id),gameData:e.gameData,...M(e.extensions),...s}}promptBeatOf(e){return e.type==="group"&&e.prompt?e.prompt:((e.type==="snippet"?e:this.firstTextSnippetIn(e.children))?.beats??[]).find(n=>n.kind==="line"||n.kind==="text")}firstTextSnippetIn(e){let t;return q(e,n=>{!t&&n.type==="snippet"&&(n.beats??[]).some(s=>s.kind==="line"||s.kind==="text")&&(t=n)}),t}resolveString(e){if(this.host.emitIds)return e;let t=this.host.strings[e];if(t!==void 0)return t;let n=this.host.defaultStrings[e];return n!==void 0?`<Untranslated: ${e}> ${n}`:e}resolveCharacterName(e){if(e===void 0||this.host.emitIds)return;let t=Se(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.castDisplay.get(e)}promptPadOf(e){let t=this.promptBeatOf(e);return t?this.padOf(t.id):j}padOf(e){return this.host.padIndex.get(e)?.resolved??j}resolveQualifierName(e){if(e===void 0||this.host.emitIds)return;let t=we(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.qualifierDisplay.get(e)}splitRef(e){return At(this.host,e)}newLocal(){return new $(this.host.patterLocalDecls,{pathPrefix:"@patter."})}mountLocal(){this.local=this.newLocal();let e=P.flowGlobals(this.id);this.host.registry.mountOwned(e,this.local,{owner:ce}),this.registered.add(e),this.host.reportRefits()}releaseBags(e){for(let t of this.registered)this.host.registry.remove(t,{keep:e});this.registered.clear(),this.sceneBags.clear()}sceneBagFor(e,t){if(this.host.bundle.scenes[e])return this.ensureSceneBags(e),this.host.sceneSharedNames.get(e)?.has(t.toLowerCase())?this.host.stageBags.get(e):this.sceneBags.get(e)}ensureSceneBags(e){let t=this.host.sceneSharedNames.get(e)??new Set,n=this.host.bundle.scenes[e]?.sceneProps??[],s=this.host.journal,i=!this.sceneBags.has(e)||!this.host.stageBags.has(e);if(!this.sceneBags.has(e)){let o=new $(n.filter(c=>!t.has(c.name.toLowerCase())),{pathPrefix:"@scene."}),a=P.flowScene(this.id,e),l=Et(this.host.registry,a,o,s!==null);this.registered.add(a),this.sceneBags.set(e,o),s&&s.undo.push(()=>{this.sceneBags.get(e)===o&&(this.host.registry.remove(a,l?{keep:!0}:void 0),this.registered.delete(a),this.sceneBags.delete(e))})}if(!this.host.stageBags.has(e)){let o=new $(n.filter(l=>t.has(l.name.toLowerCase())),{pathPrefix:"@scene."}),a=Et(this.host.registry,P.stage(e),o,s!==null);this.host.stageBags.set(e,o),s&&s.undo.push(()=>{this.host.stageBags.get(e)===o&&(this.host.registry.remove(P.stage(e),a?{keep:!0}:void 0),this.host.stageBags.delete(e))})}i&&this.host.reportRefits()}seedScene(e){let t=this.host.sceneSharedNames.get(e.id)??new Set;this.ensureSceneBags(e.id);for(let n of e.sceneProps??[]){if(!n.temporary)continue;let s=n.name.toLowerCase(),i=t.has(s)?this.host.stageBags.get(e.id):this.sceneBags.get(e.id);if(!i)continue;let o=this.host.journal?i.get(s):void 0;o!==void 0&&this.host.journal.undo.push(()=>i.set(s,o)),i.set(s,K(n))}}};function xt(r,e){q(r,t=>{if(t.type==="group"){t.prompt?.kind==="line"&&t.prompt.character&&e.add(t.prompt.character);return}for(let n of t.beats??[])n.kind==="line"&&n.character&&e.add(n.character)})}function le(r,e,t,n=!1){if(!e||r.emitIds)return;let s=l=>(n?void 0:r.strings[l])??r.defaultStrings[l],i=s(Se(e))??r.castDisplay.get(e)??e;if(t===void 0)return i;let o=r.speakerLabels.get(`${e}\0${t}`);if(o!==void 0)return s(dt(e,t))??o;let a=s(we(t))??r.qualifierDisplay.get(t)??t;return ft(s(pt)??r.speakerPattern,i,a)}function kt(r){return r&&Object.keys(r).length?{gameData:r}:{}}function M(r){return r&&Object.keys(r).length?{extensions:r}:{}}function Nn(r){let e={kind:r.kind,text:r.text};return r.character!==void 0&&(e.character=r.character),r.characterName!==void 0&&(e.characterName=r.characterName),r.direction!==void 0&&(e.direction=r.direction),r.qualifier!==void 0&&(e.qualifier=r.qualifier),r.qualifierName!==void 0&&(e.qualifierName=r.qualifierName),r.speakerLabel!==void 0&&(e.speakerLabel=r.speakerLabel),typeof r.padAfter=="number"&&(e.padAfter=r.padAfter),e}function It(r){let e={};for(let[t,n]of r){let s={};n.seq!==void 0&&(s.seq=n.seq),n.bag&&(s.bag=[...n.bag]),n.last!==void 0&&(s.last=n.last),e[t]=s}return e}function Ot(r){let e=new Map;for(let[t,n]of Object.entries(r??{})){let s={};n.seq!==void 0&&(s.seq=n.seq),n.bag&&(s.bag=[...n.bag]),n.last!==void 0&&(s.last=n.last),e.set(t,s)}return e}function Et(r,e,t,n){let s=n?JSON.stringify(t.save()):"";return r.mountOwned(e,t,{owner:ce}),n&&JSON.stringify(t.save())!==s}function Ct(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default}}function Dt(r){return{...r.world?{world:r.world}:{},...r.hostScopes}}function de(r,e,t){let n=r.qualityLadders.get(e);if(!n){n=new Map;for(let s of t()??[]){let i=s.name.toLowerCase();s.type==="quality"&&s.stages&&!n.has(i)&&n.set(i,s.stages)}r.qualityLadders.set(e,n)}return n}function Ln(r,e,t){let n=t.toLowerCase();return e==="patter"?de(r,"patter",()=>[...r.patterSharedDecls,...r.patterLocalDecls]).get(n):r.registry.toEvalContext().qualities?.(e,t)??de(r,`host/${e}`,()=>r.bundle.scopeRegistry?.scopes.find(s=>s.token===e)?.declarations).get(n)}function Pt(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default,writable:r.writable}}function Bn(r,e){let t=Pt(r),n=r.writable??e;return n===void 0?t:{...t,writable:n}}function je(r,e){return ve(r.bundle.scenes,e,r.sceneGameIdToId)}function Ve(r,e,t){return r.blockGameIdToId.get(e)?.get(t)??(r.blockIndex.get(t)?.sceneId===e?t:void 0)}function At(r,e){r.refSplitRevision!==r.registry.revision&&(r.refSplitCache.clear(),r.refSplitRevision=r.registry.revision);let t=r.refSplitCache.get(e);return t||(t=at(e,n=>n==="scene"||r.registry.has(n)||(r.bundle.externalScopes?.includes(n)??!1)),r.refSplitCache.set(e,t)),t}function Mn(r){let e={};r.shared?.patter&&(e.patter=r.shared.patter);for(let[t,n]of Object.entries(r.stageBags??{}))e[P.stage(t)]=n;for(let[t,n]of Object.entries(r.flows??{}))Object.assign(e,Nt(t,n));return e}function Nt(r,e){let t={};e.scopes?.patter&&(t[P.flowGlobals(r)]=e.scopes.patter);for(let[n,s]of Object.entries(e.sceneBags??{}))t[P.flowScene(r,n)]=s;return t}function Tn(r,e){let t={scopes:{},sceneBags:{}},n=P.flow(r);for(let[s,i]of Object.entries(e)){if(!s.startsWith(n))continue;let o=s.slice(n.length);o==="patter"?t.scopes.patter=i:o.startsWith("scene/")&&(t.sceneBags[An(o.slice(6))]=i)}return t}function Rt(r){return typeof r=="boolean"?r:typeof r=="number"?r!==0:typeof r=="string"?r!=="":r.length>0}var Fn=(r,e)=>r.shared??e;function Ge(r,e){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.default!==void 0?{default:r.default}:{},shared:Fn(r,e)}}function $n(r){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.values?{values:[...r.values]}:{},...r.purpose?{purpose:r.purpose}:{}}}function jn(r,e){e.blocks++;let t=[...r.children];for(;t.length;){let n=t.pop();if(n.type==="group"){e.groups++,n.prompt&&e.prompts++,t.push(...n.children);continue}e.snippets++;for(let s of n.beats??[])e.beats++,s.kind==="gameEvent"&&e.gameEvents++}}function Ee(r){let e={scenes:0,blocks:0,groups:0,snippets:0,beats:0,prompts:0,gameEvents:0,cast:r.cast?.length??0},t=[],n=[];for(let o of Object.values(r.scenes)){e.scenes++;let a=E(o);t.push({gameId:a,name:o.name,blocks:o.blocks.map(l=>({gameId:E(l),name:l.name}))});for(let l of o.blocks)jn(l,e);o.sceneProps?.length&&n.push({gameId:a,properties:o.sceneProps.map(l=>Ge(l,!1))})}let s=(r.scopeRegistry?.scopes??[]).map(o=>({token:o.token,writable:o.writable??!0,opaque:o.declarations===void 0,properties:(o.declarations??[]).map(a=>Ge(a,!0))})),i=Object.entries(r.gameDataFields??{}).filter(([,o])=>(o?.length??0)>0).map(([o,a])=>({kind:o,fields:(a??[]).map($n)}));return{identity:{schema:r.schema,project:r.content.project,...r.content.version!==void 0?{version:r.content.version}:{},...r.content.hash!==void 0?{hash:r.content.hash}:{},...r.content.structureHash!==void 0?{structureHash:r.content.structureHash}:{},voiced:r.voiced,defaultLocale:r.locales.default,locales:[...r.locales.included],localisation:r.localisation?.mode??"embedded",sourceDebug:r.localisation?.sourceDebug??!1},addresses:t,hostScopes:s,properties:{patter:(r.properties??[]).map(o=>Ge(o,!0)),scene:n},gameData:i,counts:e}}var ue=(r,e)=>Object.prototype.hasOwnProperty.call(r,e);function Lt(r,e){return r.gameDataFields?.[e]??[]}function qe(r,e,t){return e&&ue(e,t)?e[t]:r.find(n=>n.name===t)?.default}function Bt(r,e){let t={};for(let n of r){let s=qe(r,e,n.name);s!==void 0&&(t[n.name]=s)}for(let[n,s]of Object.entries(e??{}))ue(t,n)||(t[n]=s);return t}function Mt(r,e,t){let n=r.extensions!==void 0&&ue(r.extensions,e)?r.extensions[e]:void 0;return n!==void 0&&ue(n.fields,t)?n.fields[t]??[]:[]}function Tt(r,e,t=""){let n=o=>({...o?.extensions??{}}),s=Object.values(r.scenes??{}),i=o=>(ue(r.scenes??{},o)?r.scenes[o]:void 0)??s.find(a=>E(a)===o);switch(e){case"project":{let o={};for(let[a,l]of Object.entries(r.extensions??{}))l.project!==void 0&&(o[a]=l.project);return o}case"scene":return n(i(t));case"block":{let o=t.indexOf("/");if(o<0)return{};let a=i(t.slice(0,o))?.blocks??[],l=t.slice(o+1);return n(a.find(c=>c.id===l)??a.find(c=>E(c)===l))}case"snippet":case"option":case"line":case"text":case"gameEvent":{let o,a=(l,c)=>{for(let p of l??[]){if(o!==void 0)return;if(p.type==="group"){if(c&&p.id===t&&e==="option"){o=p;return}if(c&&p.prompt?.id===t&&p.prompt.kind===e){o=p.prompt;return}a(p.children??[],p.selector==="choice");continue}if(p.id===t&&e==="snippet"){o=p;return}let d=(p.beats??[]).find(f=>f.id===t);if(d!==void 0){d.kind===e&&(o=d);return}}};for(let l of s)for(let c of l.blocks??[])o===void 0&&a(c.children??[],!1);return n(o)}default:return{}}}function He(r){return{schema:z,save:r.saveGame()}}function _e(r,e){if(!e||e.schema!==z||!e.save)throw new Error(`loadState: not a ${z} envelope`);r.loadGame(e.save)}function Ce(r){return JSON.stringify(He(r))}function De(r,e){_e(r,JSON.parse(e))}function Ft(r,e){return r.getProperty(e)}function $t(r,e,t){r.setProperty(e,t)}function jt(r,e){for(let[t,n]of Object.entries(e))r.setProperty(t,n)}function We(r){let e={};for(let t of Vt(r)){let n=t.pathPrefix??t.bag.pathPrefix;for(let[s,i]of Object.entries(t.bag.save()))e[`${n}${s}`]=i}return Object.assign(e,Gt(r)),e}function Vt(r){return[...r.listBags(),...r.flows().flatMap(e=>e.listBags())]}function Vn(r){switch(r.type){case"line":return`line ${r.character??"?"}: ${JSON.stringify(r.text)}${Ue(r.gameData)}`;case"text":return`text: ${JSON.stringify(r.text)}${Ue(r.gameData)}`;case"gameEvent":return`game event ${r.id}${Ue(r.gameData)}`;case"choice":return`choice (${r.options.length} option${r.options.length===1?"":"s"})`;case"end":return"end"}}var Ue=r=>r?` gameData=${JSON.stringify(r)}`:"";function Gt(r){let e={};for(let[t,n]of Object.entries(r.getVisitCounts()))e[`visit:${t}`]=n;for(let t of r.flows())for(let[n,s]of Object.entries(t.getVisitCounts()))e[`${t.id}/visit:${n}`]=s;return e}function qt(r,e={}){let t=e.label?`[${e.label}] `:"",n=Be({mounts:()=>Vt(r),extra:()=>Gt(r)},{sink:e.sink,label:t});return{snapshot:()=>We(r),capture:()=>n.capture(),dispose:()=>n.dispose(),logStep(s){(e.sink??(i=>console.log(i)))(`${t}${Vn(s)}`)}}}function Ht(r){let e=r.url??"ws://127.0.0.1:4471",t=r.WebSocket??globalThis.WebSocket,n=new Set,s=[],i=null,o=!1,a=r.build,l=()=>{if(!(!i||i.readyState!==1)){for(let d of s)try{i.send(d)}catch{}s=[]}},c=d=>{o||!i||i.readyState>1||(s.push(JSON.stringify(d)),l())};if(!t)return{flowOpened(){},observe(){},flowClosed(){},setBuild(){},close(){o=!0},state:"closed",build:a,url:e};let p=()=>{let d=JSON.stringify({t:"hello",v:1,build:a,project:r.project,flows:[...n]});try{i?.send(d)}catch{}};try{i=new t(e),i.addEventListener("open",()=>{p(),l()}),i.addEventListener("message",d=>{if(!(!r.onBundle||typeof d.data!="string"))try{let f=JSON.parse(d.data);f.t==="bundle"&&typeof f.build=="string"&&typeof f.data=="string"&&r.onBundle({build:f.build,data:f.data})}catch{}}),i.addEventListener("error",()=>{}),i.addEventListener("close",()=>{i=null,s=[]})}catch{i=null}return{flowOpened(d){n.add(d),c({t:"flowOpen",flow:d})},flowClosed(d){n.delete(d),c({t:"flowClose",flow:d})},observe(d,f,g,y,u){n.has(d)||(n.add(d),c({t:"flowOpen",flow:d})),c({t:"frame",flow:d,sceneId:f,beatId:g,type:y,choiceId:u})},setBuild(d){o||d===a||(a=d,i&&i.readyState===1&&p())},close(){o=!0,s=[];try{i?.close()}catch{}i=null},get state(){return o||!i?"closed":i.readyState===1?"connected":"connecting"},get build(){return a},url:e}}function _t(r,e,t){let n=JSON.parse(t);return e.content.structureHash!==void 0&&e.content.structureHash===n.content.structureHash?(r.replaceStrings(n),{engine:r,bundle:n,kind:"text"}):{engine:r.hotSwap(n),bundle:n,kind:"structure"}}function Gn(r,e){r.textContent="";let t=/\u0002([^\u0003]*)\u0003/g,n=0,s;for(;(s=t.exec(e))!==null;){s.index>n&&r.append(e.slice(n,s.index));let i=document.createElement("strong");i.textContent=s[1]??"",r.append(i),n=s.index+s[0].length}n<e.length&&r.append(e.slice(n))}var ze=!1,Ut=!1,Qt,qn=350,Je=6,Wt=7,Y=null,X=0,Re=null,Hn=null;function Yt(){if(Y)return Y;let r=document.createElement("div");return r.className="tooltip",r.setAttribute("role","tooltip"),r.hidden=!0,document.body.appendChild(r),Y=r,r}var _n=r=>r instanceof HTMLElement?r.getBoundingClientRect():r;function Un(r){let e=Yt(),t=_n(r),n=e.getBoundingClientRect(),s=t.top-n.height-Wt;s<Je&&(s=t.top+t.height+Wt);let i=t.left+t.width/2-n.width/2;i=Math.max(Je,Math.min(i,window.innerWidth-n.width-Je)),e.style.left=`${Math.round(i)}px`,e.style.top=`${Math.round(s)}px`}function Wn(r){let e=r.dataset.tip;e&&Jn(r,e)}function Jn(r,e){if(Qt?.())return;let t=Yt(),n=(r instanceof HTMLElement?r.closest("dialog[open]"):null)??document.body;t.parentElement!==n&&n.appendChild(t),Re=r instanceof HTMLElement?r:null,Gn(t,e),t.hidden=!1,t.classList.remove("show"),t.offsetWidth,Un(r),t.classList.add("show")}function Q(){X&&(window.clearTimeout(X),X=0),Re=null,Hn=null,Y&&(Y.hidden=!0,Y.classList.remove("show"))}function Jt(r){r!==Re&&(X&&window.clearTimeout(X),X=window.setTimeout(()=>Wn(r),qn))}function Kn(){Qn()}function zn(){Ut||(Ut=!0,setTimeout(()=>{ze||typeof document>"u"||document.querySelector("[data-tip]")&&console.warn("app-shell: something set `data-tip` but no tooltip host is mounted, so those rollovers will not draw. Call initTooltips() once per window.")},0))}var Ke=r=>r instanceof Element?r.closest("[data-tip]"):null;function Qn(r={}){r.suppressed!==void 0&&(Qt=r.suppressed),!ze&&(ze=!0,document.addEventListener("pointerover",e=>{let t=Ke(e.target);t&&Jt(t)}),document.addEventListener("pointerout",e=>{let t=Ke(e.target);if(!t)return;let n=e.relatedTarget;n instanceof Node&&t.contains(n)||Q()}),document.addEventListener("focusin",e=>{let t=Ke(e.target);t&&Jt(t)}),document.addEventListener("focusout",()=>Q()),document.addEventListener("pointerdown",()=>Q(),!0),document.addEventListener("scroll",()=>{Re&&Q()},!0),document.addEventListener("keydown",e=>{e.key==="Escape"&&Q()}),window.addEventListener("blur",()=>Q()))}var Yn={close:"\u2715",more:"\u22EF",collapsed:"\u25B8",expanded:"\u25BE",dropdown:"\u25BE",back:"\u2039",forward:"\u203A",up:"\u2191",down:"\u2193",tick:"\u2713",locked:"\u2298",readOnly:"\u25CB",checkedOut:"\u270E",modified:"\u25CF",untracked:"+",warning:"\u203C",dot:"\u25CF",play:"\u25B6",restart:"\u27F2",viewCards:"\u25A6",viewTable:"\u2630",viewNode:"\u25C8",grip:"\u283F",add:"+",note:"\u270E",comment:"\u275D"},Xn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.571" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">',Zn='<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">',v=r=>`${Xn}${r}</svg>`,Xt=r=>`${Zn}${r}</svg>`,Kt=Xt('<circle cx="12" cy="12" r="6"/>'),er=Xt('<circle cx="12" cy="12" r="9"/>'),Zt={close:v('<path d="M18 6 6 18"/><path d="m6 6 12 12"/>'),more:v('<circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/>'),collapsed:v('<path d="m9 18 6-6-6-6"/>'),expanded:v('<path d="m6 9 6 6 6-6"/>'),dropdown:v('<path d="m6 9 6 6 6-6"/>'),back:v('<path d="m15 18-6-6 6-6"/>'),forward:v('<path d="m9 18 6-6-6-6"/>'),up:v('<path d="m5 12 7-7 7 7"/><path d="M12 19V5"/>'),down:v('<path d="M12 5v14"/><path d="m19 12-7 7-7-7"/>'),arrowLeft:v('<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>'),arrowRight:v('<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>'),tick:v('<path d="M20 6 9 17l-5-5"/>'),locked:v('<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>'),readOnly:v('<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 9.9-1"/>'),checkedOut:v('<path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/><path d="m15 5 4 4"/>'),modified:Kt,untracked:v('<path d="M5 12h14"/><path d="M12 5v14"/>'),warning:v('<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>'),dot:Kt,play:v('<path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z"/>'),restart:v('<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/>'),viewCards:v('<rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/>'),viewTable:v('<rect width="18" height="18" x="3" y="3" rx="2"/><path d="M21 9H3"/><path d="M21 15H3"/>'),viewNode:v('<path d="m10.586 5.414-5.172 5.172"/><path d="m18.586 13.414-5.172 5.172"/><path d="M6 12h12"/><circle cx="12" cy="20" r="2"/><circle cx="12" cy="4" r="2"/><circle cx="20" cy="12" r="2"/><circle cx="4" cy="12" r="2"/>'),record:er,speaker:v('<path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"/><path d="M16 9a5 5 0 0 1 0 6"/><path d="M19.364 18.364a9 9 0 0 0 0-12.728"/>'),grip:v('<circle cx="9" cy="12" r="1"/><circle cx="9" cy="5" r="1"/><circle cx="9" cy="19" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="15" cy="5" r="1"/><circle cx="15" cy="19" r="1"/>'),add:v('<path d="M5 12h14"/><path d="M12 5v14"/>'),copy:v('<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>'),connect:v('<path d="M12 22v-5"/><path d="M15 8V2"/><path d="M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z"/><path d="M9 8V2"/>'),search:v('<path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/>'),pin:v('<path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/>'),settings:v('<path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"/><circle cx="12" cy="12" r="3"/>'),note:v('<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/>'),comment:v('<path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/>')},ys={...Zt,noteFilled:'<svg viewBox="0 0 16 16" width="13" height="13" fill="currentColor" fill-rule="evenodd" aria-hidden="true"><path d="M3.4 1.4h5.3L12.6 5.3v8.1a1.2 1.2 0 0 1-1.2 1.2H3.4a1.2 1.2 0 0 1-1.2-1.2V2.6A1.2 1.2 0 0 1 3.4 1.4ZM4.9 6.8h6.2v1.1H4.9Zm0 2.1h6.2v1.1H4.9Zm0 2.1h3.7v1.1H4.9Z"/></svg>',noteOutline:'<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round" stroke-linecap="round" aria-hidden="true"><path d="M3.4 2h4.9l3.9 3.9v7.5a1 1 0 0 1-1 1H3.4a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1Z"/><path d="M8.3 2.2v3.8h3.8"/><path d="M4.9 8h6.2M4.9 10h6.2M4.9 12h3.7" stroke-width="0.95"/></svg>'},bs=Object.keys(Zt);var zt=new Map;for(let[r,e]of Object.entries(Yn))zt.has(e)||zt.set(e,r);function en(r,e,...t){let n=document.createElement(r),s=typeof e=="string"?{className:e}:e??{};s.className&&(n.className=s.className),s.text!==void 0&&s.text!==null&&(n.textContent=s.text),s.title!==void 0&&(n.title=s.title),s.tip!==void 0&&(n.dataset.tip=s.tip,n.setAttribute("aria-label",s.tip),Kn()),s.onClick&&n.addEventListener("click",s.onClick);for(let i of t)i!=null&&n.append(i);return zn(),n}function tn(r){let e=r.default;if(e!=null)return typeof e=="boolean"?e?"True":"False":Array.isArray(e)?e.length===0?"none":e.join(", "):e===""?"none":String(e);switch(r.type){case"boolean":return"False";case"number":return"0";case"enum":return r.values?.[0]??"none";case"quality":return r.stages?.[0]??"first stage";case"flags":return"none";default:return"empty"}}var nn=r=>`default (${tn(r)})`;function Qe(r){let e=r.doc===void 0?en:(a,l)=>{let c=r.doc.createElement(a);return c.className=l.className,l.text!==void 0&&(c.textContent=l.text),l.tip!==void 0&&(c.title=l.tip,c.setAttribute("aria-label",l.tip)),l.onClick&&c.addEventListener("click",l.onClick),a==="button"&&(c.type="button"),c},t=e("span",{className:"seg shell-rungs"}),n=r.decl??{type:"quality",stages:r.stages},s=r.value===void 0,i=typeof n.default=="string"&&r.stages.includes(n.default)?n.default:r.stages[0],o=r.onPick===void 0;r.onClear&&t.append(e("button",{className:`seg-opt shell-rung shell-rung-default${s?" on":""}`,text:nn(n),tip:s?"Not set here: the declared default holds":"Clear the value, back to the default",onClick:()=>{s||r.onClear()}}));for(let a of r.stages){let l=r.value===a,c=s&&a===i,p=e(o?"span":"button",{className:`seg-opt shell-rung${l?" on":""}${c?" fallback":""}`,text:a,tip:l?"The current stage":c?"The stage it falls back to":o?a:r.pickTip?.(a)??`Set to "${a}"`,...o?{}:{onClick:()=>{l||r.onPick(a)}}});t.append(p)}return!s&&!r.stages.includes(r.value)&&t.append(e("span",{className:"seg-opt shell-rung stray on",text:r.value,tip:`"${r.value}" is not one of the stages: pick the one it belongs at now`})),t}var rn="pp-inspector-style",tr=`
|
|
3
3
|
.pp-insp{font:13px/1.4 ui-sans-serif,system-ui,sans-serif;color:#15201e;background:#f4efe6;border:1px solid #cfc7b8;border-radius:10px;padding:.6rem .7rem;max-width:22rem;box-shadow:0 6px 20px rgba(21,32,30,.12)}
|
|
4
4
|
.pp-insp h4{margin:0 0 .4rem;font:600 .72rem/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#5c6b62}
|
|
5
5
|
.pp-insp-empty{color:#8a9691;font-style:italic}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
.pp-insp-ctl .seg-opt+.seg-opt{border-left:1px solid #cfc7b8}
|
|
17
17
|
.pp-insp-ctl .seg-opt.on{color:#214f4b;background:#dbe8e4;font-weight:600;cursor:default}
|
|
18
18
|
.pp-insp-ctl .shell-rung.stray{color:#9a3b2e;text-decoration:line-through}
|
|
19
|
-
`;function
|
|
19
|
+
`;function nr(r){if(r.getElementById(rn))return;let e=r.createElement("style");e.id=rn,e.textContent=tr,(r.head??r.documentElement).appendChild(e)}function rr(r,e){return Array.isArray(r)&&Array.isArray(e)?r.length===e.length&&r.every((t,n)=>t===e[n]):r===e}function sn(r,e={}){let t=e.container?.ownerDocument??document;nr(t);let n=t.createElement("div");n.className="pp-insp";let s=t.createElement("h4");s.textContent=e.title??"Runtime state";let i=t.createElement("div"),o=t.createElement("div");o.className="pp-insp-io";let a=t.createElement("button");a.type="button",a.textContent="Save state\u2026",a.addEventListener("click",()=>{let u=new Blob([Ce(r)],{type:"application/json"}),x=t.createElement("a");x.href=URL.createObjectURL(u),x.download="save.patterstate",x.click(),URL.revokeObjectURL(x.href)});let l=t.createElement("button");l.type="button",l.textContent="Load state\u2026",l.addEventListener("click",()=>{let u=t.createElement("input");u.type="file",u.accept=".patterstate,application/json",u.addEventListener("change",()=>{let x=u.files?.[0];x&&x.text().then(I=>{try{De(r,I),f()}catch(R){console.error("Load state failed:",R instanceof Error?R.message:R)}})}),u.click()}),o.append(a,l),n.append(s,o,i);let c=[],p=u=>{let x=t.createElement("div");x.className="pp-insp-row";let I=t.createElement("span");I.className="pp-insp-ref",I.textContent=u.path,I.title=u.path;let R=t.createElement("div");R.className="pp-insp-ctl";let N=t.createElement("button");N.className="pp-insp-reset",N.type="button",N.textContent="\u21BA",N.title="Reset to default",x.append(I,R,N),i.appendChild(x);let k,L=h=>{r.setProperty(u.path,h),F()},T=h=>t.activeElement===h;function F(){N.disabled=rr(r.getProperty(u.path),u.default)}if(N.addEventListener("click",()=>{r.setProperty(u.path,u.default),k(),F()}),u.type==="boolean"){let h=t.createElement("input");h.type="checkbox",h.addEventListener("change",()=>L(h.checked)),R.appendChild(h),k=()=>{T(h)||(h.checked=r.getProperty(u.path)===!0)}}else if(u.type==="number"){let h=t.createElement("input");h.type="number",h.addEventListener("change",()=>L(Number(h.value))),R.appendChild(h),k=()=>{T(h)||(h.value=String(r.getProperty(u.path)??""))}}else if(u.type==="quality"){let h=()=>{let C=r.getProperty(u.path);R.replaceChildren(Qe({stages:u.stages??[],value:typeof C=="string"?C:void 0,decl:u,onPick:m=>{L(m),h()},doc:t}))};k=h}else if(u.type==="enum"){let h=t.createElement("select");for(let C of u.values??[]){let m=t.createElement("option");m.value=C,m.textContent=C,h.appendChild(m)}h.addEventListener("change",()=>L(h.value)),R.appendChild(h),k=()=>{T(h)||(h.value=String(r.getProperty(u.path)??""))}}else if(u.type==="flags"){let h=t.createElement("input");h.type="text",h.placeholder="comma, separated, flags",h.addEventListener("change",()=>L(h.value.split(",").map(C=>C.trim()).filter(C=>C.length>0))),R.appendChild(h),k=()=>{if(!T(h)){let C=r.getProperty(u.path);h.value=Array.isArray(C)?C.join(", "):""}}}else{let h=t.createElement("input");h.type="text",h.addEventListener("change",()=>L(h.value)),R.appendChild(h),k=()=>{T(h)||(h.value=String(r.getProperty(u.path)??""))}}k(),F(),c.push(()=>{k(),F()})},d=r.listProperties();if(d.length===0){let u=t.createElement("div");u.className="pp-insp-empty",u.textContent="No @patter properties.",i.appendChild(u)}else for(let u of d)p(u);let f=()=>{for(let u of c)u()};e.container?.appendChild(n);let g=e.pollMs??250,y;return g>0&&(y=setInterval(f,g)),{el:n,refresh:f,destroy(){y!==void 0&&clearInterval(y),n.remove()}}}var on="pp-bundle-style",sr=`
|
|
20
20
|
.pp-bundle{font:13px/1.4 ui-sans-serif,system-ui,sans-serif;color:#15201e;background:#f4efe6;border:1px solid #cfc7b8;border-radius:10px;padding:.6rem .7rem;max-width:26rem;box-shadow:0 6px 20px rgba(21,32,30,.12)}
|
|
21
21
|
.pp-bundle h4{margin:0 0 .4rem;font:600 .72rem/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#5c6b62}
|
|
22
22
|
.pp-bundle details{border-top:1px solid #e3dccf;padding:.3rem 0}
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
.pp-bundle-empty{color:#8a9691;font-style:italic;margin-left:1rem}
|
|
34
34
|
.pp-bundle-warn{color:#8a3a2f;font-weight:600}
|
|
35
35
|
.pp-bundle-tag{font-size:.7rem;color:#5c6b62;border:1px solid #cfc7b8;border-radius:5px;padding:0 .25rem;margin-left:.3rem}
|
|
36
|
-
`;function
|
|
36
|
+
`;function ir(r){if(r.getElementById(on))return;let e=r.createElement("style");e.id=on,e.textContent=sr,(r.head??r.documentElement).appendChild(e)}var w=(r,e,t,n)=>{let s=r.createElement(e);return t&&(s.className=t),n!==void 0&&(s.textContent=n),s};function A(r,e,t,n="pp-bundle-val"){let s=w(r,"div","pp-bundle-row");return s.append(w(r,"span","pp-bundle-key",e),w(r,"span",n,t)),s}function Ye(r,e){let t=w(r,"div","pp-bundle-row");t.append(w(r,"span","pp-bundle-key pp-bundle-addr",e.name));let n=w(r,"span","pp-bundle-val",e.type);return e.hasDefault||n.append(w(r,"span","pp-bundle-tag","no default")),t.append(n),t}function Z(r,e,t,n,s){let i=r.createElement("details");i.dataset.section=e,i.open=s;let o=r.createElement("summary");return o.textContent=t,n!==null&&o.append(w(r,"span","pp-bundle-count",` ${n}`)),i.append(o),i}function an(r,e={}){let t=e.container?.ownerDocument??document;ir(t);let n=Ee(r),s=new Set(e.open??["identity","addresses"]),i=w(t,"div","pp-bundle");i.append(w(t,"h4",void 0,e.title??"Bundle"));let o=Z(t,"identity",n.identity.project||"(unnamed project)",null,s.has("identity"));n.identity.version&&o.append(A(t,"version",n.identity.version)),o.append(A(t,"schema",n.identity.schema)),o.append(A(t,"locales",`${n.identity.defaultLocale}${n.identity.locales.length>1?` (+${n.identity.locales.length-1})`:""}`)),o.append(A(t,"strings",n.identity.localisation)),n.identity.voiced&&o.append(A(t,"voiced","yes")),n.identity.hash&&o.append(A(t,"hash",n.identity.hash)),n.identity.structureHash&&o.append(A(t,"structure",n.identity.structureHash)),n.identity.sourceDebug&&o.append(A(t,"build","SOURCE DEBUG - not shippable","pp-bundle-val pp-bundle-warn")),i.append(o);let a=Z(t,"addresses","Addresses",n.addresses.length,s.has("addresses"));n.addresses.length||a.append(w(t,"div","pp-bundle-empty","no scenes"));for(let g of n.addresses){let y=w(t,"div","pp-bundle-row");y.append(w(t,"span","pp-bundle-key pp-bundle-addr",g.gameId),w(t,"span","pp-bundle-val",g.name)),a.append(y);for(let u of g.blocks){let x=w(t,"div","pp-bundle-row pp-bundle-sub");x.append(w(t,"span","pp-bundle-key pp-bundle-addr",u.gameId),w(t,"span","pp-bundle-val",u.name)),a.append(x)}}i.append(a);let l=n.hostScopes.reduce((g,y)=>g+y.properties.length,0),c=Z(t,"hostScopes","Host properties",l,s.has("hostScopes"));n.hostScopes.length||c.append(w(t,"div","pp-bundle-empty","the game supplies nothing"));for(let g of n.hostScopes){let y=w(t,"div","pp-bundle-row");y.append(w(t,"span","pp-bundle-key pp-bundle-addr",`@${g.token}`));let u=w(t,"span","pp-bundle-val",g.opaque?"any name, unchecked":`${g.properties.length} declared`);g.writable||u.append(w(t,"span","pp-bundle-tag","read-only")),y.append(u),c.append(y);for(let x of g.properties){let I=Ye(t,x);I.classList.add("pp-bundle-sub"),c.append(I)}}i.append(c);let p=n.properties.patter.length+n.properties.scene.reduce((g,y)=>g+y.properties.length,0),d=Z(t,"properties","Story properties",p,s.has("properties"));p||d.append(w(t,"div","pp-bundle-empty","none declared"));for(let g of n.properties.patter)d.append(Ye(t,g));for(let g of n.properties.scene){d.append(A(t,"@scene",g.gameId,"pp-bundle-val pp-bundle-addr"));for(let y of g.properties){let u=Ye(t,y);u.classList.add("pp-bundle-sub"),d.append(u)}}if(i.append(d),n.gameData.length){let g=Z(t,"gameData","Game data",n.gameData.reduce((y,u)=>y+u.fields.length,0),s.has("gameData"));for(let y of n.gameData){g.append(A(t,"on",y.kind));for(let u of y.fields){let x=w(t,"div","pp-bundle-row pp-bundle-sub");x.append(w(t,"span","pp-bundle-key pp-bundle-addr",u.name),w(t,"span","pp-bundle-val",u.type)),g.append(x)}}i.append(g)}let f=Z(t,"counts","Counts",null,s.has("counts"));for(let[g,y]of Object.entries(n.counts))f.append(A(t,g,String(y)));return i.append(f),e.container?.append(i),{el:i,description:n,destroy(){i.remove()}}}function ln(r,e){let n=JSON.parse(r).clips??{},s=e===""||/[/\\]$/.test(e)?"":"/";return{resolve(i){let o=n[i];return!o||!o.file?null:`${e}${s}${o.file}`}}}return hn(or);})();
|
|
37
37
|
//# sourceMappingURL=patterplay.min.js.map
|