@patterkit/play-helpers 0.12.1 → 0.12.3
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 $e=Object.defineProperty;var Rn=Object.getOwnPropertyDescriptor;var Bn=Object.getOwnPropertyNames;var Ln=Object.prototype.hasOwnProperty;var On=(r,e)=>{for(var t in e)$e(r,t,{get:e[t],enumerable:!0})},Nn=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Bn(e))!Ln.call(r,s)&&s!==t&&$e(r,s,{get:()=>e[s],enumerable:!(n=Rn(e,s))||n.enumerable});return r};var Pn=r=>Nn($e({},"__esModule",{value:!0}),r);var Pr={};On(Pr,{Checkpoint:()=>me,DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND:()=>de,DEFAULT_PAD_AFTER:()=>U,Engine:()=>Be,Flow:()=>K,Runner:()=>Te,SAVE_SCHEMA:()=>Z,applyLiveBundle:()=>gn,buildTagIndex:()=>Ie,compareStages:()=>z,countSyllables:()=>We,createAudioResolver:()=>Dn,createBundleInspector:()=>An,createDebugLink:()=>fn,createPropertyInspector:()=>kn,createStateLogger:()=>un,describeBundle:()=>Le,deserializeState:()=>Ne,diffState:()=>ae,effectiveGameData:()=>rn,estimateLineDuration:()=>Rt,extensionDecls:()=>sn,extensionsOf:()=>on,gameDataFields:()=>nn,gameDataValue:()=>Ze,getProperty:()=>an,loadState:()=>tt,nextStage:()=>Y,resolveSceneRef:()=>Ae,saveState:()=>et,sceneAddressIndex:()=>Ke,serializeState:()=>Oe,setProperties:()=>cn,setProperty:()=>ln,snapshotState:()=>rt,speechUnits:()=>X,stageIndex:()=>J});function se(r,e){return r!==void 0&&Object.prototype.hasOwnProperty.call(r,e)?r[e]:void 0}function H(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:H(r[2])};case"bin":return{kind:"binary",op:r[1],left:H(r[2]),right:H(r[3])};case"call":{let e=r.slice(2).map(H);return{kind:"call",name:r[1],args:e}}case"fd":return{kind:"flagdelta",sign:r[1],name:r[2]}}}var C=class extends Error{constructor(e){super(e),this.name="EvalError"}};function Se(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=se(e.scopes,i.scope);if(o===void 0)return!1;let a=typeof o.get=="function"?o.get(i.name):se(o,i.name);if(a===void 0){if(n.get(i.scope)==="throw")throw new C(`@${i.scope}.${i.name} is not declared on the current ${i.scope}.`);return!1}return a}case"call":{if(i.name==="advance"&&!se(t.functions,i.name)){let a=i.args[0];if(i.args.length!==1||a===void 0)throw new C(`advance() takes exactly 1 argument, got ${i.args.length}`);let l=Me(a,e);if(l===void 0)throw new C("advance() needs a quality reference (@scope.name of a quality property)");let c=T(s(a),l,"advance");return l[Math.min(c+1,l.length-1)]}let o=se(t.functions,i.name);if(!o)throw new C(`unknown function '${i.name}'`);return o.eval(i.args,{evaluate:s,ctx:e})}case"flagdelta":throw new C("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 C(`'not' requires a boolean operand, got ${typeof a}`);return!a}let o=s(i.operand);if(typeof o!="number")throw new C(`unary '-' requires a numeric operand, got ${typeof o}`);return-o}case"binary":{if(i.op==="and"){let u=s(i.left);if(typeof u!="boolean")throw new C(`'and' requires boolean operands, left is ${typeof u}`);if(!u)return!1;let h=s(i.right);if(typeof h!="boolean")throw new C(`'and' requires boolean operands, right is ${typeof h}`);return h}if(i.op==="or"){let u=s(i.left);if(typeof u!="boolean")throw new C(`'or' requires boolean operands, left is ${typeof u}`);if(u)return!0;let h=s(i.right);if(typeof h!="boolean")throw new C(`'or' requires boolean operands, right is ${typeof h}`);return h}let o=s(i.left),a=s(i.right),l=Me(i.left,e),c=Me(i.right,e),f=l??c;if(f!==void 0){if(l&&c&&!Tn(l,c)&&(i.op===">"||i.op===">="||i.op==="<"||i.op==="<="))throw new C(`'${i.op}' compares two different qualities, whose stage orders are unrelated`);switch(i.op){case">":return T(o,f,">")>T(a,f,">");case">=":return T(o,f,">=")>=T(a,f,">=");case"<":return T(o,f,"<")<T(a,f,"<");case"<=":return T(o,f,"<=")<=T(a,f,"<=");case"+":case"-":case"*":case"/":throw new C(`'${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 ct(o,a);case"!=":return!ct(o,a);case">":return q(o,a,">"),o>a;case">=":return q(o,a,">="),o>=a;case"<":return q(o,a,"<"),o<a;case"<=":return q(o,a,"<="),o<=a;case"+":if(typeof o=="number"&&typeof a=="number"||typeof o=="string"&&typeof a=="string")return o+a;throw new C(`'+' requires two numbers or two strings, got ${typeof o} and ${typeof a}`);case"-":return q(o,a,"-"),o-a;case"*":return q(o,a,"*"),o*a;case"/":if(q(o,a,"/"),a===0)throw new C("division by zero");return o/a}}}};return s(r)}function ct(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 q(r,e,t){if(typeof r!="number"||typeof e!="number")throw new C(`'${t}' requires numeric operands, got ${typeof r} and ${typeof e}`)}function Me(r,e){if(!(r.kind!=="scopedvar"||e.qualities===void 0))return e.qualities(r.scope,r.name)}function T(r,e,t){if(typeof r!="string")throw new C(`'${t}' on a quality compares stages, got ${typeof r}`);let n=e.indexOf(r);if(n<0)throw new C(`"${r}" is not a stage of this quality (stages: ${e.join(", ")})`);return n}var Tn=(r,e)=>r.length===e.length&&r.every((t,n)=>t===e[n]);function ie(r){if(Number.isNaN(r)||!Number.isFinite(r))return 0;let e=Math.trunc(r)%4294967296;return e<0?e+4294967296:e}function je(r){let e=ie(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 Ge=r=>Array.isArray(r)?r:r.stages??[],$n=r=>Array.isArray(r)?"flags":r==null?"nothing":typeof r;function J(r,e){return typeof e=="string"?Ge(r).indexOf(e):-1}function _e(r,e){if(typeof e!="string")throw new C(`a stage is a name, got ${$n(e)}`);let t=r.indexOf(e);if(t<0)throw new C(`"${e}" is not a stage of this quality (stages: ${r.join(", ")})`);return t}function z(r,e,t){let n=Ge(r),s=_e(n,e)-_e(n,t);return s<0?-1:s>0?1:0}function Y(r,e){let t=Ge(r);return t[Math.min(_e(t,e)+1,t.length-1)]}function oe(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 Mn={name:"check_flags",count:r=>Math.max(1,r.args.length-1)},jn=[Mn];function dt(r,e,t){let n=t?.countingCalls??jn;return ve(r,t?.want??!0,e,n)}function ve(r,e,t,n){if(r.kind==="binary"&&(r.op==="and"||r.op==="or")){let s=ve(r.left,e,t,n),i=ve(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 ve(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 ae(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 pt=r=>r===void 0?"<unset>":JSON.stringify(r),ut=r=>r.pathPrefix??r.bag.pathPrefix;function Ve(r,e={}){let t=e.sink??(u=>console.log(u)),n=e.label??"",s=u=>{t(`${n}${u.path}: ${pt(u.from)} -> ${pt(u.to)}`)},i=()=>{let u={};for(let h of r.mounts()){let x=ut(h);for(let[p,d]of Object.entries(h.bag.values))u[x+p]=d}return Object.assign(u,r.extra?.()??{}),structuredClone(u)},o=i(),a=[],l=[],c=(u,h)=>h.onAudit(x=>{let p=structuredClone({path:u+x.name,from:x.prev,to:x.next});s(p),a.push(p),o[p.path]=structuredClone(x.next)}),f=()=>{let u=r.mounts();if(!(l.length===u.length&&u.every((x,p)=>l[p].bag===x.bag))){for(let x of l)x.off();l=u.map(x=>({bag:x.bag,off:c(ut(x),x.bag)}))}};return f(),{snapshot:i,capture(){let u=i(),h=ae(o,u);for(let p of h)s(p);let x=[...a,...h];return a=[],o=u,f(),x},dispose(){for(let u of l)u.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??Q(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])=>gt(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);oe(o,a,{noneChosen:o.type==="enum"&&o.default===""})||(this.values[i]=structuredClone(Q(o)),s.push({name:i,value:a}))}return s}};function gt(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??Q(r),...r.values!==void 0?{values:r.values}:{},...r.stages!==void 0?{stages:r.stages}:{},writable:t??r.writable??!0}}var _n=r=>r.toLowerCase(),He=1,Ee=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??_n,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,...gt(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(Gn(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 ft(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=ft(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:He,scopes:this.save()}}loadFragment(e){if(e.version!==He)throw new Error(`unsupported owned-state fragment version ${e.version} (supported: ${He})`);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 ft(r){return r.kind==="foreign"?[...r.decls.entries()]:r.bag.declarations().map(e=>[r.bag.normalise(e.name),e])}function Gn(r){return r.kind==="foreign"?r.norm:e=>r.bag.normalise(e)}function Q(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 ht=[{token:"patter",engine:"Patterplay",means:"Patter's shared globals"},{token:"story",engine:"Storylet Engine",means:"the Storylet Engine's shared @story properties"}];function le(r){return r.ctx.host??{}}var qe={defaultScope:"patter",scopes:[{token:"patter"},{token:"scene"}],functions:{random:{minArgs:2,maxArgs:2,returnType:"number",eval(r,e){if(r.length!==2)throw new C("random(a, b) requires exactly 2 arguments");let t=le(e).nextRandom;if(!t)throw new C("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 C("random(a, b) arguments must be numbers");if(!Number.isInteger(n)||!Number.isInteger(s))throw new C("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:mt("check_flags"),eval(r,e){let t=xt(r[0],e,"check_flags");for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new C("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:mt("set_flags"),eval(r,e){let t=[...xt(r[0],e,"set_flags")];for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new C("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:ke("visits"),eval:(r,e)=>le(e).visits?.(we(r,e,"visits"))??0},seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:ke("seen"),eval:(r,e)=>(le(e).visits?.(we(r,e,"seen"))??0)>0},patter_visits:{minArgs:1,maxArgs:1,returnType:"number",validate:ke("patter_visits"),eval:(r,e)=>le(e).patterVisits?.(we(r,e,"patter_visits"))??0},patter_seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:ke("patter_seen"),eval:(r,e)=>(le(e).patterVisits?.(we(r,e,"patter_seen"))??0)>0}}},ps=ht.map(r=>r.token).filter(r=>r!=="patter"&&r!=="scene");function yt(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 we(r,e,t){let n=e.evaluate(r[0]);if(typeof n!="string")throw new C(`${t}(id) requires a string node id`);return n}function ke(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 xt(r,e,t){if(!r)throw new C(`${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 C(`${t}() first argument must be a flags property`)}function mt(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 Vn=/^@[A-Za-z0-9_.]+$/;function*Hn(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:Vn.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 qn(r){return Array.isArray(r)?r.join(", "):typeof r=="boolean"?r?"true":"false":String(r)}function Un(r){return r===" "||r===" "||r===`
|
|
2
|
-
`||r==="\r"||r==="\f"||r==="\v"}function Wn(r){let e="",t=!1;for(let n of r){if(Un(n)){t=!0;continue}t&&e.length>0&&(e+=" "),t=!1,e+=n}return e}function bt(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?Wn(n):r}function St(r,e){if(r.indexOf("{")<0)return r;let t="";for(let n of Hn(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?"":qn(s)}return t}function vt(r){return r.toLowerCase().replace(/['’]/g,"").replace(/[^a-z0-9-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}var y={NONE:0,LATIN_VOWEL:1,LATIN_LETTER:2,CYRILLIC_VOWEL:3,CYRILLIC_LETTER:4,HAN:5,KANA:6,KANA_SMALL:7,KANA_SOKUON:8,KANA_LONG:9,HANGUL:10,ARABIC_LETTER:11,ARABIC_VOWEL:12,THAI_CONSONANT:13,THAI_LEAD:14,THAI_VOWEL:15,MARK:16,OTHER_LETTER:17,DIGIT:18,PAUSE_SHORT:19,PAUSE_LONG:20,JOINER:21,SPACE:22},ce=[9,13,22,32,32,22,33,33,20,39,39,21,44,44,19,46,46,20,48,57,18,58,59,19,63,63,20,65,65,1,66,68,2,69,69,1,70,72,2,73,73,1,74,78,2,79,79,1,80,84,2,85,85,1,86,88,2,89,89,1,90,90,2,97,97,1,98,100,2,101,101,1,102,104,2,105,105,1,106,110,2,111,111,1,112,116,2,117,117,1,118,120,2,121,121,1,122,122,2,133,133,22,160,160,22,170,170,2,173,173,21,181,181,17,186,186,2,192,198,1,199,199,2,200,207,1,208,209,2,210,214,1,216,221,1,222,223,2,224,230,1,231,231,2,232,239,1,240,241,2,242,246,1,248,253,1,254,254,2,255,261,1,262,273,2,274,283,1,284,295,2,296,305,1,306,331,2,332,339,1,340,359,2,360,371,1,372,373,2,374,376,1,377,415,2,416,417,1,418,430,2,431,432,1,433,460,2,461,476,1,477,477,2,478,483,1,484,489,2,490,493,1,494,505,2,506,527,1,528,531,2,532,535,1,536,549,2,550,563,1,564,696,2,697,699,17,700,700,21,701,705,17,710,721,17,736,740,2,748,748,17,750,750,17,768,879,16,880,884,17,886,893,17,895,895,17,902,902,17,904,1013,17,1015,1023,17,1024,1025,3,1026,1027,4,1028,1028,3,1029,1029,4,1030,1031,3,1032,1036,4,1037,1038,3,1039,1039,4,1040,1040,3,1041,1044,4,1045,1045,3,1046,1047,4,1048,1048,3,1049,1053,4,1054,1054,3,1055,1058,4,1059,1059,3,1060,1066,4,1067,1067,3,1068,1068,4,1069,1072,3,1073,1076,4,1077,1077,3,1078,1079,4,1080,1080,3,1081,1085,4,1086,1086,3,1087,1090,4,1091,1091,3,1092,1098,4,1099,1099,3,1100,1100,4,1101,1105,3,1106,1107,4,1108,1108,3,1109,1109,4,1110,1111,3,1112,1116,4,1117,1118,3,1119,1153,4,1155,1161,16,1162,1231,4,1232,1235,3,1236,1237,4,1238,1239,3,1240,1249,4,1250,1255,3,1256,1259,4,1260,1267,3,1268,1271,4,1272,1273,3,1274,1327,4,1329,1369,17,1376,1416,17,1425,1469,17,1471,1471,17,1473,1474,17,1476,1477,17,1479,1522,17,1548,1548,19,1552,1562,16,1563,1563,19,1567,1567,20,1568,1599,11,1600,1600,16,1601,1610,11,1611,1616,12,1617,1631,16,1632,1641,18,1646,1647,11,1648,1648,12,1649,1747,11,1748,1748,20,1749,1749,11,1750,1756,16,1759,1764,16,1765,1766,11,1767,1768,16,1770,1773,16,1774,1775,11,1776,1785,18,1786,1788,11,1791,1791,11,1808,1871,17,1872,1919,11,1920,2037,17,2042,2045,17,2048,2093,17,2112,2139,17,2144,2154,17,2160,2183,11,2185,2191,11,2199,2207,16,2208,2249,11,2250,2273,16,2275,2303,16,2304,2384,17,2385,2388,16,2389,2403,17,2404,2405,20,2406,2415,17,2417,2545,17,2556,2556,17,2558,2677,17,2689,2799,17,2809,2927,17,2929,2929,17,2946,3055,17,3072,3183,17,3200,3203,17,3205,3406,17,3412,3415,17,3423,3439,17,3450,3571,17,3585,3630,13,3631,3631,16,3632,3641,15,3642,3642,16,3648,3652,14,3653,3654,16,3655,3655,15,3656,3660,16,3661,3661,15,3662,3662,16,3664,3673,18,3713,3840,17,3864,3865,17,3872,3881,17,3893,3893,17,3895,3895,17,3897,3897,17,3902,3972,17,3974,4028,17,4038,4038,17,4096,4169,17,4176,4253,17,4256,4346,17,4348,4959,17,4992,5007,17,5024,5117,17,5121,5740,17,5743,5759,17,5760,5760,22,5761,5786,17,5792,5866,17,5873,5940,17,5952,6099,17,6103,6103,17,6108,6121,17,6155,6157,17,6159,6459,17,6470,6617,17,6656,6683,17,6688,6809,17,6823,6823,17,6832,6891,16,6912,6988,17,6992,7001,17,7019,7027,17,7040,7155,17,7168,7223,17,7232,7293,17,7296,7306,4,7312,7359,17,7376,7378,16,7380,7392,16,7393,7393,17,7394,7400,16,7401,7404,17,7405,7405,16,7406,7411,17,7412,7412,16,7413,7415,17,7416,7417,16,7418,7418,17,7424,7461,2,7462,7466,17,7467,7467,4,7468,7516,2,7517,7521,17,7522,7525,2,7526,7530,17,7531,7543,2,7544,7544,4,7545,7614,2,7615,7615,17,7616,7679,16,7680,7681,1,7682,7699,2,7700,7709,1,7710,7723,2,7724,7727,1,7728,7755,2,7756,7763,1,7764,7793,2,7794,7803,1,7804,7821,2,7822,7823,1,7824,7832,2,7833,7833,1,7834,7839,2,7840,7929,1,7930,7935,2,7936,8124,17,8126,8126,17,8130,8140,17,8144,8155,17,8160,8172,17,8178,8188,17,8192,8202,22,8204,8205,21,8211,8212,19,8217,8217,21,8230,8230,20,8232,8233,22,8239,8239,22,8253,8253,20,8263,8265,20,8287,8287,22,8305,8305,2,8319,8319,2,8336,8348,2,8400,8432,16,8450,8450,17,8455,8455,17,8458,8467,17,8469,8469,17,8473,8477,17,8484,8484,17,8486,8486,17,8488,8488,17,8490,8490,2,8491,8491,1,8492,8493,17,8495,8497,17,8498,8498,2,8499,8505,17,8508,8511,17,8517,8521,17,8526,8526,2,8579,8580,2,11264,11359,17,11360,11391,2,11392,11492,17,11499,11507,17,11520,11631,17,11647,11742,17,11744,11775,16,11823,11823,17,12288,12288,22,12289,12289,19,12290,12290,20,12293,12293,5,12294,12294,17,12330,12335,16,12337,12341,17,12347,12347,5,12348,12348,17,12353,12353,7,12354,12354,6,12355,12355,7,12356,12356,6,12357,12357,7,12358,12358,6,12359,12359,7,12360,12360,6,12361,12361,7,12362,12386,6,12387,12387,8,12388,12418,6,12419,12419,7,12420,12420,6,12421,12421,7,12422,12422,6,12423,12423,7,12424,12429,6,12430,12430,7,12431,12436,6,12437,12438,7,12441,12444,16,12445,12447,6,12449,12449,7,12450,12450,6,12451,12451,7,12452,12452,6,12453,12453,7,12454,12454,6,12455,12455,7,12456,12456,6,12457,12457,7,12458,12482,6,12483,12483,8,12484,12514,6,12515,12515,7,12516,12516,6,12517,12517,7,12518,12518,6,12519,12519,7,12520,12525,6,12526,12526,7,12527,12538,6,12540,12540,9,12541,12543,6,12549,12686,17,12704,12735,17,12784,12799,7,13312,19903,5,19968,40959,5,40960,42124,17,42192,42237,17,42240,42508,17,42512,42539,17,42560,42606,4,42607,42610,16,42612,42621,16,42623,42653,4,42654,42655,16,42656,42725,17,42736,42737,17,42775,42783,17,42786,42887,2,42888,42888,17,42891,43007,2,43008,43047,17,43052,43052,17,43072,43123,17,43136,43205,17,43216,43255,17,43259,43259,17,43261,43309,17,43312,43347,17,43360,43456,17,43471,43481,17,43488,43609,17,43616,43638,17,43642,43741,17,43744,43759,17,43762,43822,17,43824,43866,2,43868,43876,2,43877,43877,17,43878,43881,2,43888,44010,17,44012,44025,17,44032,55203,10,55216,55291,17,63744,64217,5,64256,64262,2,64275,64296,17,64298,64335,17,64336,64433,11,64467,64829,11,64848,64911,11,64914,64967,11,65008,65019,11,65024,65039,16,65056,65071,16,65104,65105,19,65136,65276,11,65281,65281,20,65292,65292,19,65294,65294,20,65296,65305,18,65306,65307,19,65311,65311,20,65313,65338,2,65345,65370,2,65377,65377,20,65380,65380,19,65382,65382,6,65383,65390,7,65391,65391,8,65392,65392,9,65393,65437,6,65438,65439,16,65440,65500,17,65536,65786,17,66045,66045,16,66176,66256,17,66272,66272,16,66304,66335,17,66349,66368,17,66370,66377,17,66384,66461,17,66464,66511,17,66560,66915,17,66928,67431,17,67456,67514,2,67584,67669,17,67680,67702,17,67712,67742,17,67808,67829,17,67840,67861,17,67872,67897,17,67904,68023,17,68030,68031,17,68096,68159,17,68192,68220,17,68224,68252,17,68288,68295,17,68297,68326,17,68352,68405,17,68416,68437,17,68448,68466,17,68480,68497,17,68608,68850,17,68864,68973,17,68975,68997,17,69248,69292,17,69296,69297,17,69314,69319,11,69370,69375,16,69376,69404,17,69415,69456,17,69488,69509,17,69552,69572,17,69600,69702,17,69734,69818,17,69826,69826,17,69840,69951,17,69956,70003,17,70006,70084,17,70089,70092,17,70094,70106,17,70108,70108,17,70144,70199,17,70206,70312,17,70320,70457,17,70459,70459,16,70460,70611,17,70625,70730,17,70736,70745,17,70750,70853,17,70855,71104,17,71128,71232,17,71236,71257,17,71296,71352,17,71360,71481,17,71488,71738,17,71840,71913,17,71935,72003,17,72016,72161,17,72163,72254,17,72263,72345,17,72349,72349,17,72368,72440,17,72544,72672,17,72688,72768,17,72784,72793,17,72818,73462,17,73472,73538,17,73552,73648,17,73728,74649,17,74880,77808,17,77824,78895,17,78912,92777,17,92784,92916,17,92928,92982,17,92992,92995,17,93008,93017,17,93027,93548,17,93552,93823,17,93856,94177,17,94179,94179,5,94180,94180,17,94192,94193,16,94194,94195,5,94208,101874,17,110576,110951,6,110960,113817,17,113821,113822,17,118e3,118009,17,118528,118598,16,119141,119142,17,119143,119145,16,119149,119154,17,119163,119170,16,119173,119179,16,119210,119213,16,119362,119364,17,119808,120512,17,120514,120538,17,120540,120570,17,120572,120596,17,120598,120628,17,120630,120654,17,120656,120686,17,120688,120712,17,120714,120744,17,120746,120770,17,120772,120831,17,121344,121398,17,121403,121452,17,121461,121461,17,121476,121476,17,121499,121519,17,122624,122666,2,122880,122922,17,122928,122989,4,123023,123023,16,123136,123214,17,123536,123641,17,124112,124410,17,124608,125124,17,125136,125273,17,126464,126651,11,130032,130041,17,131072,210041,5,917760,917999,16];var Dt=1.5,Ft=2,Ue=1,It=2,E=(r,e)=>r[e]??-1;function Kn(r){let e=0,t=ce.length/3-1;for(;e<=t;){let n=e+t>>1;if(r<E(ce,n*3))t=n-1;else if(r>E(ce,n*3+1))e=n+1;else return E(ce,n*3+2)}return y.NONE}function Jn(r){return((r??"").split(/[-_]/)[0]??"").toLowerCase()}var Et=r=>r>=65&&r<=90||r>=97&&r<=122,zn=r=>r>=48&&r<=57;function Yn(r,e){let t=n=>E(r,n);if(t(e)===60){let n=e+1;t(n)===47&&n++;let s=n;for(;Et(t(n));)n++;return n>s&&t(n)===62?n+1:e}if(t(e)===38){let n=e+1,s=t(n)===35;s&&n++;let i=n;for(;s?zn(t(n)):Et(t(n));)n++;return n>i&&t(n)===59?n+1:e}return e}var wt=new Set([y.LATIN_VOWEL,y.LATIN_LETTER]),kt=new Set([y.CYRILLIC_VOWEL,y.CYRILLIC_LETTER]),Ct=new Set([y.ARABIC_LETTER,y.ARABIC_VOWEL]),Ce=new Set([y.THAI_CONSONANT,y.THAI_LEAD,y.THAI_VOWEL]),At=new Set([y.OTHER_LETTER]),Qn=new Set([y.KANA,y.KANA_SMALL,y.KANA_SOKUON,y.KANA_LONG]);function X(r,e){let t=Array.from(r??"",d=>d.codePointAt(0)),n=t.map(Kn),s=t.length,i=Jn(e),o=i==="ja"||n.some(d=>Qn.has(d)),a=[],l=(d,w,g=1)=>{a.push({kind:"syllable",weight:g,start:d,end:w})},c=d=>d>=0&&d<s?E(n,d):y.NONE,f=d=>{for(;d<s&&E(n,d)===y.MARK;)d++;return d},u=(d,w)=>{let g=d+1;for(;g<s&&(w.has(E(n,g))||E(n,g)===y.MARK||E(n,g)===y.JOINER&&w.has(c(g+1)));)g++;return g},h=(d,w,g)=>{let b=[...new Set(g.map(v=>Math.min(f(v+1),w)-1))].sort((v,k)=>v-k);b.forEach((v,k)=>l(k===0?d:E(b,k-1)+1,k===b.length-1?w:v+1))},x=(d,w,g)=>Array.from({length:w},(b,v)=>E(d,Math.min(g*v+g-1,d.length-1))),p=0;for(;p<s;){let d=E(n,p),w=Yn(t,p);if(w>p){p=w;continue}if(wt.has(d)){let g=u(p,wt),b=[],v=[],k=!1;for(let I=p;I<g;I++)E(n,I)===y.LATIN_VOWEL?(k?(b[b.length-1]=I,v[v.length-1]=E(v,v.length-1)+1):(b.push(I),v.push(1)),k=!0):E(n,I)!==y.MARK&&(k=!1);b.length>=2&&E(v,v.length-1)===1&&Zn(t,n,p,g,E(b,b.length-1),i)&&b.pop(),h(p,g,b.length?b:[g-1]),p=g}else if(kt.has(d)){let g=u(p,kt),b=[];for(let v=p;v<g;v++)E(n,v)===y.CYRILLIC_VOWEL&&b.push(v);h(p,g,b.length?b:[g-1]),p=g}else if(Ct.has(d)){let g=u(p,Ct),b=[],v=[];for(let k=p;k<g;k++)E(n,k)===y.ARABIC_VOWEL?b.push(k):E(n,k)===y.ARABIC_LETTER&&v.push(k);h(p,g,b.length?b:x(v,Math.max(1,Math.ceil(v.length/2)),2)),p=g}else if(Ce.has(d)){let g=u(p,Ce);h(p,g,er(n,p,g)),p=g}else if(At.has(d)){let g=u(p,At),b=[];for(let v=p;v<g;v++)E(n,v)===y.OTHER_LETTER&&b.push(v);h(p,g,x(b,Math.max(1,Math.ceil(b.length/3)),3)),p=g}else if(d===y.HAN){let g=f(p+1);l(p,g,o?Ft:1),p=g}else if(d===y.KANA||d===y.HANGUL){let g=f(p+1);l(p,g),p=g}else if(d===y.KANA_SMALL||d===y.KANA_LONG){let g=f(p+1),b=a[a.length-1];b&&b.kind==="syllable"&&b.end===p?(b.end=g,d===y.KANA_LONG&&(b.weight+=1)):d===y.KANA_SMALL&&l(p,g),p=g}else if(d===y.KANA_SOKUON){let g=f(p+1);a.push({kind:"closed",weight:1,start:p,end:g}),p=g}else if(d===y.DIGIT){let g=f(p+1);l(p,g,Dt),p=g}else if(d===y.PAUSE_SHORT||d===y.PAUSE_LONG)(E(t,p)===46||E(t,p)===44)&&c(p-1)===y.DIGIT&&c(p+1)===y.DIGIT||a.push({kind:"pause",weight:d===y.PAUSE_LONG?It:Ue,start:p,end:p+1}),p++;else if(d===y.SPACE){let g=p+1;for(;g<s&&E(n,g)===y.SPACE;)g++;Xn(n,p-1)&&Ce.has(c(g))&&a.push({kind:"pause",weight:Ue,start:p,end:g}),p=g}else p++}return tr(a)}function Xn(r,e){for(;e>=0&&E(r,e)===y.MARK;)e--;return e>=0&&Ce.has(E(r,e))}function Zn(r,e,t,n,s,i){if(i!=="en"&&i!=="fr"||E(r,s)!==101&&E(r,s)!==69)return!1;let o=s+1;return!(o<n&&E(e,o)===y.MARK||(i==="fr"&&o<n&&(E(r,o)===115||E(r,o)===83)&&o++,o!==n)||i==="en"&&s-2>=t&&(E(r,s-1)===108||E(r,s-1)===76)&&E(e,s-2)===y.LATIN_LETTER)}function er(r,e,t){let n=[],s=[],i=!1,o=()=>{for(let a=0;a<Math.floor((s.length-1)/2);a++)n.push(E(s,2*a+1))};for(let a=e;a<t;a++){let l=E(r,a);if(l===y.THAI_CONSONANT)s.push(a);else if(l===y.THAI_LEAD)o(),n.push(a+1<t&&E(r,a+1)===y.THAI_CONSONANT?a+1:a),s=[],i=!0;else if(l===y.THAI_VOWEL){if(s.length===0)continue;if(i&&s.length<=2){i=!1,s=[];continue}o(),n.push(a),s=[],i=!1}}if(n.length===0){let a=Math.max(1,Math.ceil(s.length/2));for(let l=0;l<a;l++)n.push(s.length?E(s,Math.min(2*l+1,s.length-1)):t-1)}else o();return n}function tr(r){let e=[];for(let t of r){let n=e[e.length-1];t.kind==="pause"&&n?.kind==="pause"?(n.weight=Math.max(n.weight,t.weight),n.end=t.end):e.push({...t})}for(;e[0]?.kind==="pause";)e.shift();for(;e[e.length-1]?.kind==="pause";)e.pop();return e}function We(r,e){let t=0;for(let n of X(r,e))n.kind!=="pause"&&(t+=n.weight);return t}function G(r,e){for(let t of r){e(t);let n=t.children;n&&G(n,e)}}function R(r){let e=r.gameId?.trim();return e||vt(r.name)}function Ke(r){let e=new Map;for(let[t,n]of Object.entries(r))e.set(R(n),t);return e}function Ae(r,e,t){return(t??Ke(r)).get(e)??(Object.hasOwn(r,e)?e:void 0)}var U=.6;var de=4;var nr=1.5,rr=18;function Rt(r,e,t){let n=typeof t=="number"&&Number.isFinite(t)&&t>0?t:de,s=0;for(let i of X(r??"",e))s+=i.weight;return Math.min(Math.max(s/n,nr),rr)}function De(r){return`cast:${r}`}function Fe(r){return`qualifier:${r}`}function Bt(r,e){return`speaker:${r}:${e}`}var Lt="speaker:pattern",Ot="{name} ({qualifier})";function Nt(r,e,t){return r.split("{name}").map(n=>n.split("{qualifier}").join(t)).join(e)}var Je={open:"[",close:"]"},Pt="SFX",Z="patter/save@0",pe=4;function ue(r){let e=new Set,t=[];for(let n of r)e.has(n)||(e.add(n),t.push(n));return t}function Ie(r){let e=new Map,t=(n,s)=>{let i=ue([...s,...n.tags??[]]);if(e.set(n.id,i),n.type==="group"&&n.prompt&&e.set(n.prompt.id,ue([...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,ue([...i,...o.tags??[]]))};for(let n of Object.values(r.scenes)){let s=ue(n.tags??[]);e.set(n.id,s);for(let i of n.blocks){let o=ue([...s,...i.tags??[]]);e.set(i.id,o);for(let a of i.children)t(a,o)}}return e}var Tt=r=>r.kind==="line"||r.kind==="text",fe=r=>typeof r=="number"&&Number.isFinite(r)?r:void 0;function $t(r){let e=new Map,t=(i,o,a)=>{let l=i.kind==="gameEvent"?void 0:fe(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=fe(i.padAfterDefault)??o;if(i.type==="group"){i.prompt&&t(i.prompt,a,!1);for(let f of i.children)n(f,a);return}let l=i.beats??[],c=-1;l.forEach((f,u)=>{Tt(f)&&(c=u)}),l.forEach((f,u)=>{Tt(f)&&t(f,a,u===c)})},s=fe(r.padAfterDefault)??U;for(let i of Object.values(r.scenes)){let o=fe(i.padAfterDefault)??s;for(let a of i.blocks){let l=fe(a.padAfterDefault)??o;for(let c of a.children)n(c,l)}}return e}var Mt=new WeakMap,jt=new WeakMap;function sr(r){let e=jt.get(r);return e||(e=Ie(r),jt.set(r,e)),e}var _t=new WeakMap;function ir(r){let e=_t.get(r);return e||(e=$t(r),_t.set(r,e)),e}var Gt=new WeakMap;function or(r){let e=Gt.get(r);if(e)return e;e=new Map;for(let t of Object.values(r.scenes))for(let n of t.blocks)G(n.children,s=>{if(s.type==="group"&&s.selector==="choice")for(let i of s.children)e.set(i.id,s.id)});return Gt.set(r,e),e}var Vt=new WeakMap;function ar(r){let e=Vt.get(r);if(e)return e;e=new Map;for(let t of Object.values(r.scenes))for(let n of t.blocks)G(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 Vt.set(r,e),e}function N(r){if(r===void 0)return;let e={};for(let[t,n]of Object.entries(r))e[t]=Array.isArray(n)?[...n]:n;return e}function W(r,e){return r.tagIndex.get(e)?.slice()}var he="Patter",ge=r=>r.replace(/%/g,"%25").replace(/\//g,"%2F"),lr=r=>r.replace(/%2F/g,"/").replace(/%25/g,"%"),Ht=Symbol("ownsRegistry"),qt=Symbol("setupReported"),O={stage:r=>`patter/scene/${ge(r)}`,flow:r=>`patter/flow/${ge(r)}/`,flowGlobals:r=>`patter/flow/${ge(r)}/patter`,flowScene:(r,e)=>`patter/flow/${ge(r)}/scene/${ge(e)}`},me=class{constructor(e){this.journal=e}journal},Be=class r{host;defaultSeed;flowsById=new Map;allStrings;currentLocale;requestedLocale;sourceDebug;sceneGameIdToId=new Map;blockGameIdToId=new Map;creationOptions;engineLog=[];engineSeq=0;engineTraceHandlers=new Set;constructor(e,t={}){this.creationOptions=t;let n=[];for(let m of Object.keys(t))dr.has(m)||n.push({node:m,message:m==="world"?'the engine option "world" has gone: bind the scope as hostScopes: { world }':`"${m}" isn't an engine option, so it's ignored`});let s=e.strings;this.allStrings=s,this.requestedLocale=t.locale,this.currentLocale=ze(e,t.locale),this.currentLocale.problem&&n.push({node:t.locale,message:this.currentLocale.problem});let i=zt(s,this.currentLocale),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 f=new Map;for(let m of e.qualifiers??[])m?.gameId&&f.set(m.gameId,m.name);let u=new Map;for(let m of e.cast??[])for(let[F,A]of Object.entries(m.qualifierLabels??{}))typeof A=="string"&&u.set(`${m.name}\0${F}`,A);let h=e.speakerPattern??Ot;this.defaultSeed=(t.seed??2654435769)>>>0;let x=new Map,p=new Map,d=new Map;for(let[m,F]of Object.entries(e.scenes)){this.sceneGameIdToId.set(R(F),m);let A=new Map;for(let L of F.blocks)p.set(L.id,{sceneId:m}),d.set(L.id,L),A.set(R(L),L.id),G(L.children,j=>x.set(j.id,j));this.blockGameIdToId.set(m,A)}let w=e.properties??[],g=w.filter(m=>m.shared??!0).map(Jt),b=w.filter(m=>!(m.shared??!0)).map(Jt),v=new Set(g.map(m=>m.name.toLowerCase())),k=t.registry??new Ee,I=!t.registry||t[Ht]===!0,$=new _(g,{pathPrefix:"@patter."}),M=[],S=[];try{k.mountOwned("patter",$,{owner:he}),S.push("patter");let m=new Set,F=e.scopeRegistry?.scopes??[];for(let[A,L]of Object.entries(t.hostScopes??{})){let j=F.find(be=>be.token===A);if(!j&&!(e.externalScopes??[]).includes(A)){let be=F.find(In=>In.token.toLowerCase()===A.toLowerCase());n.push({node:A,message:be?`hostScopes binds "${A}", which this bundle doesn't declare: it declares "${be.token}", and a scope's token is case-sensitive`:`hostScopes binds "${A}", which this bundle doesn't declare`})}let Fn=(j?.declarations??[]).map(en);k.defineForeign(A,L,Fn,{writable:j?.writable??!0,owner:he}),S.push(A),m.add(A)}for(let A of I?e.scopeRegistry?.scopes??[]:[]){if(m.has(A.token)||k.has(A.token))continue;let L=(A.declarations??[]).map(j=>fr(j,A.writable));k.defineOwned(A.token,L,{owner:he}),S.push(A.token),M.push(A.token)}}catch(m){for(let F of S)k.remove(F,{keep:!0});throw m}let B=new Map;for(let[m,F]of Object.entries(e.scenes)){let A=new Set((F.sceneProps??[]).filter(L=>L.shared??!1).map(L=>L.name.toLowerCase()));B.set(m,A)}if(this.host={logEnabled:t.log??!1,tracing:t.log??!1,emitEngine:(m,F,A)=>this.emitEngine(m,F,A),bundle:e,emitIds:l,strings:i,defaultStrings:o,castDisplay:c,qualifierDisplay:f,speakerLabels:u,speakerPattern:h,nodeIndex:x,blockIndex:p,blockById:d,sceneGameIdToId:this.sceneGameIdToId,blockGameIdToId:this.blockGameIdToId,tagIndex:sr(e),padIndex:ir(e),registry:k,ownsRegistry:I,patterBag:$,hostScopes:M,patterSharedDecls:g,patterLocalDecls:b,patterSharedNames:v,sceneSharedNames:B,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(m.kind==="setup"?`Patterplay: ${m.message}`:m.kind==="save"?`Patterplay: flow '${m.flow}': ${m.message}`:`Patterplay: ${m.kind} on ${m.node} in flow '${m.flow}' failed, played through: ${m.message}`)),reportRefits:()=>{let m=k.takeMisfits(F=>F==="patter"||F.startsWith("patter/")||M.includes(F));if(m.length!==0)if(t.onRefit)t.onRefit(m);else for(let F of m)console.warn(`Patterplay: the save's ${F.scope}.${F.name} was ${JSON.stringify(F.value)}, which no longer fits its declaration; it is back at its default`)},replayPromptOnChoose:t.replayPromptOnChoose??!1,captionsOn:t.closedCaptions??!0,captionOpen:(e.closedCaptions??Je).open,captionClose:(e.closedCaptions??Je).close,captionCharacter:e.closedCaptions?.character||Pt,refSplitCache:new Map,refSplitRevision:k.revision},this.host.reportRefits(),t[qt]!==!0)for(let m of n)this.reportSetup(m.node,m.message)}reportSetup(e,t){this.host.onError({flow:"",kind:"setup",node:e,message:t}),this.host.tracing&&this.emitEngine("",{type:"diagnostic",kind:"setup",node:e,message:t})}get locale(){return this.currentLocale.locale}get locales(){let{default:e,included:t}=this.host.bundle.locales;return{default:e,included:[...t]}}get isSourceDebug(){return this.sourceDebug}get buildId(){return this.host.bundle.content?.hash??""}setLocale(e){this.requestedLocale=e,this.useLocale(ze(this.host.bundle,e)),this.currentLocale.problem&&this.reportSetup(e,this.currentLocale.problem)}useLocale(e){this.currentLocale=e,this.host.strings=zt(this.allStrings,e)}replaceStrings(e){this.allStrings=e.strings;let t=this.currentLocale.problem;this.useLocale(ze(e,this.requestedLocale)),this.host.defaultStrings=this.allStrings[this.host.bundle.locales.default]??{};let n=this.currentLocale.problem;n&&n!==t&&this.reportSetup(this.requestedLocale,n)}hotSwap(e){this.refuseInCheckpoint("hotSwap");let t=this.saveGame(),n=c=>(c.setClosedCaptions(this.host.captionsOn),c),s=this.requestedLocale,i=(c=!1)=>new r(e,{...this.creationOptions,...s!==void 0?{locale:s}:{},registry:this.host.registry,[Ht]:this.host.ownsRegistry,[qt]:c}),o=new Set(["patter",...this.host.hostScopes]),a=this.host.ownsRegistry?void 0:Object.fromEntries(Object.entries(this.host.registry.save()).filter(([c])=>o.has(c)||c.startsWith("patter/")));this.release(!0),a&&this.host.registry.load(a,{keepParked:!0,refit:!0});let l=i();try{return l.loadGame(t),n(l)}catch{l.release(!0);let c=this.host.ownsRegistry?t.registry:a;c&&this.host.registry.load(c,{keepParked:!0,refit:!0});let f=i(!0);for(let[u,h]of Object.entries(t.flows)){let x=h.cursor.currentSceneId;try{f.openFlow(u,x!==null?{scene:x}:{})}catch{}}return n(f)}}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 K(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=Ye(this.host,e);if(n===void 0)throw new Error(`unknown scene: ${e}`);if(t===void 0)return{sceneId:n};let s=Qe(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 Ye(this.host,e)??e}resolveBlockRef(e,t){if(t!=null)return e==null?t:Qe(this.host,e,t)}sceneAddress(e){let t=this.host.bundle.scenes[e];return t?R(t):void 0}blockAddress(e){let t=this.host.blockById.get(e);return t?R(t):void 0}tagsForBeat(e){return W(this.host,e)??[]}tagsForScene(e){let t=this.resolveSceneRef(e);return(t!=null?W(this.host,t):void 0)??[]}tagsForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t);return(s!=null?W(this.host,s):void 0)??[]}gameDataForScene(e){let t=this.resolveSceneRef(e),n=t!=null?this.host.bundle.scenes[t]:void 0;return N(n?.gameData)??{}}gameDataForBlock(e,t){let n=this.resolveBlockRef(this.resolveSceneRef(e),t),s=n!=null?this.host.blockById.get(n):void 0;return N(s?.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)Ut(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 Ut(i.children,o),[...o]}getOutline(){return Object.values(this.host.bundle.scenes).map(e=>({id:e.id,...R(e)?{gameId:R(e)}:{},name:e.name,...Wt(e.gameData),...V(e.extensions),...this.tagsField(e.id),blocks:e.blocks.map(t=>({id:t.id,...R(t)?{gameId:R(t)}:{},name:t.name,...Wt(t.gameData),...V(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)G(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=W(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[De(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[Fe(e.qualifier)]??this.host.qualifierDisplay.get(e.qualifier);i!==void 0&&(n.qualifierName=i)}let s=Re(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??U,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=N(e.gameData)),e.extensions&&Object.keys(e.extensions).length&&(n.extensions=e.extensions),t&&t.length&&(n.tags=t),n}tagsField(e){let t=W(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 me(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:pe,...t.snapshot(),...hr(e,this.host.registry.save())}}restoreFlow(e,t){this.refuseInCheckpoint("restoreFlow");let n=t.version;if(n!==3&&n!==pe)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=O.flow(e);this.host.registry.discardParked(i),this.host.registry.load(gr(e,t),{keepParked:!0,refit:!0});let o=new K(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(O.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(O.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(this.creationOptions.hostScopes??{}))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);Zt(this.host,n,s,t,null);let 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 J(this.ladderOf(e),t)}compareStages(e,t,n){return z(this.ladderOf(e),t,n)}nextStage(e,t){return Y(this.ladderOf(e),t)}ladderOf(e){let{scope:t,name:n}=this.splitShared(e),s=ur(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:Q(e),writable:e.writable??!0}))}splitShared(e){let t=tn(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}saveGame(){let e={};for(let[t,n]of this.flowsById)e[t]=n.snapshot();return{version:pe,...this.host.ownsRegistry?{registry:this.host.registry.save()}:{},sharedVisits:Object.fromEntries(this.host.sharedVisits),sharedSelectors:Qt(this.host.sharedSelectors),flows:e}}loadGame(e){this.refuseInCheckpoint("loadGame");let t=e.version;if(t!==3&&t!==pe)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(O.stage(o),{keep:!0});this.host.stageBags.clear();let i=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 Xt(e.sharedSelectors))this.host.sharedSelectors.set(o,a);for(let[o,a]of Object.entries(e.flows)){let l=new K(o,this.host,this.defaultSeed);l.restore(a),this.flowsById.set(o,l)}this.host.reportRefits()}},K=class{id;host;local;registered=new Set;rngState;started=!1;flowEnded=!1;dryChoice=null;ranDry=null;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=ie(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 xe(this.host,"patter",()=>[...this.host.patterSharedDecls,...this.host.patterLocalDecls]).get(n);if(e==="scene"){let s=this.currentSceneId;return s==null?void 0:xe(this.host,`scene/${s}`,()=>this.host.bundle.scenes[s]?.sceneProps).get(n)}return this.registryQualities?.(e,t)??xe(this.host,`host/${e}`,()=>this.host.bundle.scopeRegistry?.scopes.find(s=>s.token===e)?.declarations).get(n)}begin(e,t){let n=this.host.bundle.start;if(e===void 0&&t===void 0&&n&&this.host.bundle.scenes[n.scene]&&(e=n.scene,n.block!==void 0&&this.host.blockIndex.get(n.block)?.sceneId===n.scene&&(t=n.block)),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(O.flow(this.id)),this.mountLocal(),this.selectors.clear(),this.visitCounts.clear(),this.stack=[],this.currentSceneId=null,this.flowEnded=!1,this.dryChoice=null,this.ranDry=null,this.activeSnippet=null,this.beatIndex=0,this.clearPending(),this.started=!0,t){let s=this.host.blockIndex.get(t);if(!s)throw new Error(`unknown block: ${t}`);this.enterSceneSetup(s.sceneId),this.stack=[{sceneId:s.sceneId,containerId:t,index:0}],this.enter(t)}else{let s=e??Object.keys(this.host.bundle.scenes)[0],i=s?this.host.bundle.scenes[s]:void 0;if(!i)throw new Error(s?`unknown scene: ${s}`:"no scenes in bundle");this.enterSceneSetup(s);let o=i.blocks[0];o&&(this.stack=[{sceneId:s,containerId:o.id,index:0}],this.enter(o.id))}this.settle()}reset(e,t){this.begin(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=[],this.dryChoice=null,this.ranDry=null,!0;let n=Ye(this.host,e);if(n===void 0)return!1;let s;return t!==void 0&&(s=Qe(this.host,n,t),s===void 0)?!1:this.started?(this.clearPending(),this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!1,this.dryChoice=null,this.ranDry=null,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,dryChoice:i,ranDry:o,currentSceneId:a,activeSnippet:l,beatIndex:c,pendingChoice:f,pendingPrompt:u,pendingPromptOwnerId:h}=this,x=this.stack.map(p=>({...p}));e.undo.push(()=>{Object.assign(this,{rngState:t,started:n,flowEnded:s,dryChoice:i,ranDry:o,currentSceneId:a,activeSnippet:l,beatIndex:c,pendingChoice:f,pendingPrompt:u,pendingPromptOwnerId:h,stack:x})})}get isClosed(){return this.closed}get currentScene(){return this.currentSceneId}advance(){if(this.closed)return{type:"end",reason:"ended"};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&&!this.activeSnippet&&!this.pendingChoice&&(this.flowEnded=!0),this.flowEnded?this.endResult():(this.dryChoice=null,this.pendingChoice?{type:"choice",groupId:this.pendingChoice.groupId,options:this.offer(this.pendingChoice)}:this.beatResult(this.activeSnippet.beats[this.beatIndex++]))}endResult(){if(this.dryChoice!==null){let e=this.dryChoice;this.dryChoice=null,this.ranDry=e,this.report({flow:this.id,kind:"dry-choice",node:e,message:`choice '${e}' ran dry (no option left to take, and no fallback) with nothing after it, so the flow ended there`})}return{type:"end",reason:this.ranDry!==null?"ran-dry":"ended"}}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=ar(this.host.bundle).get(e);return t?this.beatResult(t):void 0}getChoices(){return this.pendingChoice?this.offer(this.pendingChoice):[]}offer(e){return e.options.map(t=>{let n=e.byId.get(t.id),s=this.promptFor(n);return e.shown.set(t.id,s),{id:t.id,prompt:s,eligible:t.eligible,gameData:N(t.gameData),...V(n.extensions)}})}choose(e){let t=this.pendingChoice;if(!t)throw new Error("no choice is pending");let n=t.options.find(a=>a.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,o=i?t.shown.has(e)?t.shown.get(e):this.promptFor(s):void 0;this.pendingPrompt=i&&o?{beat:i,shown:{...o}}: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 J(this.ladderOf(e),t)}compareStages(e,t,n){return z(this.ladderOf(e),t,n)}nextStage(e,t){return Y(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);if(n){if(s==="scene"&&this.currentSceneId===null)throw new Error(`'${e}': the flow has not entered a scene yet`);Zt(this.host,s,i,t,this.currentSceneId)}let 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(){let e=or(this.host.bundle),t=this.activeSnippet?.beats?.[this.beatIndex]?.id;return{rngState:this.rngState,visits:Object.fromEntries(this.visitCounts),cursor:{flowEnded:this.flowEnded,...this.ranDry!==null?{ranDry:this.ranDry}:{},currentSceneId:this.currentSceneId,stack:this.stack.map(n=>{let s=this.childrenOf(n.containerId)?.[n.index],i=e.get(n.containerId);return{...n,...s?{nextId:s.id}:{},...i!==void 0?{choiceId:i}:{}}}),activeSnippetId:this.activeSnippet?.id??null,...t!==void 0?{beatId:t}:{},pendingChoice:this.pendingChoice?{groupId:this.pendingChoice.groupId,options:this.pendingChoice.options.map(n=>({id:n.id,eligible:n.eligible,...n.gameData!==void 0?{gameData:N(n.gameData)}:{}}))}:null,pendingPromptOwnerId:this.pendingPromptOwnerId,...this.pendingPrompt?.shown?{pendingPrompt:cr(this.pendingPrompt.shown)}:{},selectors:Qt(this.selectors)}}}restore(e){if(this.host.journal)throw new Error("a flow can't be restored while a checkpoint is open");let t=this.restoreCursor(e);this.releaseBags(!0),this.mountLocal();for(let n of new Set([this.currentSceneId,...this.stack.map(s=>s.sceneId)]))n!==null&&this.host.bundle.scenes[n]&&this.ensureSceneBags(n);t&&(this.report({flow:this.id,kind:"save",node:t.node,message:`the save's place has gone from this build: ${t.instead}`}),t.reoffer&&this.setupChoice(t.reoffer))}restoreCursor(e){this.rngState=ie(e.rngState),this.visitCounts=new Map(Object.entries(e.visits??{}));let t=e.cursor;this.started=!0,this.flowEnded=t.flowEnded,this.dryChoice=null,this.ranDry=t.flowEnded&&typeof t.ranDry=="string"?t.ranDry:null,this.currentSceneId=t.currentSceneId;let n=null;this.stack=[];for(let s of t.stack){let{nextId:i,choiceId:o,...a}=s,l=this.childrenOf(a.containerId),c=!l&&o!==void 0?this.host.nodeIndex.get(o):void 0;if(c?.type==="group"&&c.selector==="choice"){n={node:t.activeSnippetId??t.pendingChoice?.groupId??a.containerId,instead:`option ${a.containerId} has gone, so choice ${c.id} is offered again`,reoffer:c};break}let f=i!==void 0?l?.findIndex(u=>u.id===i)??-1:-1;this.stack.push(f>=0?{...a,index:f}:{...a})}if(this.activeSnippet=null,this.beatIndex=0,!n?.reoffer&&t.activeSnippetId!==null){let s=this.host.nodeIndex.get(t.activeSnippetId);if(s&&s.type==="snippet"){let i=s.beats??[];if(this.activeSnippet=s,t.beatId!==void 0){let o=i.findIndex(a=>a.id===t.beatId);this.beatIndex=o>=0?o:i.length,o<0&&(n={node:t.activeSnippetId,instead:`beat ${t.beatId} has gone from snippet ${t.activeSnippetId}, so the snippet ends there`})}else this.beatIndex=t.beatIndex??i.length}else n={node:t.activeSnippetId,instead:`snippet ${t.activeSnippetId} has gone, so play carries on after it`}}if(this.selectors=Xt(t.selectors),this.pendingChoice=null,!n?.reoffer&&t.pendingChoice!==null){let s=new Map,i=[];for(let o of t.pendingChoice.options){let a=this.host.nodeIndex.get(o.id);a&&(s.set(o.id,a),i.push({id:o.id,eligible:o.eligible,...o.gameData!==void 0?{gameData:o.gameData}:{}}))}if(i.length>0)this.pendingChoice={groupId:t.pendingChoice.groupId,options:i,byId:s,shown:new Map};else{let o=this.host.nodeIndex.get(t.pendingChoice.groupId);n=o?.type==="group"&&o.selector==="choice"?{node:t.pendingChoice.groupId,instead:`none of choice ${o.id}'s options is left, so it's offered again`,reoffer:o}:{node:t.pendingChoice.groupId,instead:`choice ${t.pendingChoice.groupId} has gone, so play carries on after it`}}}if(this.pendingPrompt=null,this.pendingPromptOwnerId=n?.reoffer?null:t.pendingPromptOwnerId??null,this.pendingPromptOwnerId){let s=this.host.nodeIndex.get(this.pendingPromptOwnerId),i=s?this.authoredPromptOf(s):void 0,o=t.pendingPrompt,a=o?.kind==="line"&&o.speakerLabel===void 0?Re(this.host,o.character,o.qualifier):void 0;i?this.pendingPrompt={beat:i,...o?{shown:{...o,padAfter:o.padAfter??this.padOf(i.id),...a!==void 0?{speakerLabel:a}:{}}}:{}}:this.pendingPromptOwnerId=null}return n}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,eligible:a,...o.gameData!==void 0?{gameData:o.gameData}:{}}),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,shown:new Map};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),this.dryChoice=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(h=>h.id),a=new Set(e.map(h=>h.id));if(n.bag===void 0&&(n.bag=o()),!n.bag.some(h=>a.has(h))){if(t==="once")return null;if(i){let h=e[s-1];return n.last=h.id,h}if(n.bag=o(),n.bag.length===0)return null}let l=n.bag.filter(h=>a.has(h)),c=n.last!==void 0&&l.length>1?l.indexOf(n.last):-1,f=Math.floor(this.rng()*(c>=0?l.length-1:l.length));c>=0&&f>=c&&f++;let u=l[f];return n.bag.splice(n.bag.indexOf(u),1),n.last=u,e.find(h=>h.id===u)}pickSpecificity(e,t,n){let s=e;if(t!=="repeat"){n.bag===void 0&&(n.bag=e.map(f=>f.id));let c=new Set(n.bag);if(s=e.filter(f=>c.has(f.id)),s.length===0)return t==="stick"&&n.last!==void 0?e.find(f=>f.id===n.last)??null:null}let i=-1,a=s.map(c=>{let f=this.specScore(c);return f>i&&(i=f),{c,s:f}}).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(u=>u.id===n.last):-1,f=Math.floor(this.rng()*(c>=0?a.length-1:a.length));c>=0&&f>=c&&f++,l=a[f]}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 dt(e,i=>{try{return Yt(Se(i,this.context(),qe))}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 Yt(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.report({flow:this.id,kind:e,node:t,...o?{source:o}:{},message:i})}report(e){this.host.onError(e),this.host.tracing&&this.emit({type:"diagnostic",kind:e.kind,node:e.node,...e.source?{source:e.source}:{},message:e.message})}evalExpr(e){return Se(this.conditionAst(e),this.context(),qe)}conditionAst(e){let t=Mt.get(e);return t||(t=H(e.ast),Mt.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=je(this.rngState),t=e.next();return this.rngState=e.state(),t};beatResult(e){let t=W(this.host,e.id),n=t&&t.length?{tags:t}:{};switch(e.kind){case"gameEvent":return{type:"gameEvent",id:e.id,gameData:N(e.gameData),...V(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}:{},...this.spokenOf(e),gameData:N(e.gameData),...V(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:Re(this.host,e.character,e.qualifier),padAfter:this.padOf(e.id),...this.spokenOf(e),gameData:N(e.gameData),...V(e.extensions),...n}}}}interpolate(e){return St(e,t=>this.getProperty(t))}stripCaptions(e){return bt(e,this.host.captionOpen,this.host.captionClose)}captionLine(e){return this.host.captionsOn?e:this.stripCaptions(e)}spokenOf(e){let t=this.host.bundle.estimateSyllablesPerSecond??de,n=this.host.emitIds?void 0:this.host.defaultStrings[e.id];if(n===void 0)return{estimateRate:t};let s;return e.kind==="text"?s=this.interpolate(n):e.character===this.host.captionCharacter?s="":s=this.stripCaptions(this.host.bundle.voiced?n:this.interpolate(n)),{spokenText:s,spokenLocale:this.host.bundle.locales.default,estimateRate:t}}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:Re(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=W(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),...this.spokenOf(e),gameData:N(e.gameData),...V(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),...this.spokenOf(e),gameData:N(e.gameData),...V(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 G(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=De(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.castDisplay.get(e)}padOf(e){return this.host.padIndex.get(e)?.resolved??U}resolveQualifierName(e){if(e===void 0||this.host.emitIds)return;let t=Fe(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.qualifierDisplay.get(e)}splitRef(e){return tn(this.host,e)}newLocal(){return new _(this.host.patterLocalDecls,{pathPrefix:"@patter."})}mountLocal(){this.local=this.newLocal();let e=O.flowGlobals(this.id);this.host.registry.mountOwned(e,this.local,{owner:he}),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=O.flowScene(this.id,e),l=Kt(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=Kt(this.host.registry,O.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(O.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,Q(n))}}};function Ut(r,e){G(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 Re(r,e,t,n=!1){if(!e||r.emitIds)return;let s=l=>(n?void 0:r.strings[l])??r.defaultStrings[l],i=s(De(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(Bt(e,t))??o;let a=s(Fe(t))??r.qualifierDisplay.get(t)??t;return Nt(s(Lt)??r.speakerPattern,i,a)}function Wt(r){return r&&Object.keys(r).length?{gameData:N(r)}:{}}function V(r){return r&&Object.keys(r).length?{extensions:r}:{}}function cr(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 Qt(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 Xt(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 Kt(r,e,t,n){let s=n?JSON.stringify(t.save()):"";return r.mountOwned(e,t,{owner:he}),n&&JSON.stringify(t.save())!==s}function Jt(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default}}var dr=new Set(["rng","seed","locale","hostScopes","registry","replayPromptOnChoose","closedCaptions","onDryChoice","onError","onRefit","log"]);function ze(r,e){let t=r.locales.default;if(e===void 0)return{locale:t,table:t};if(r.localisation?.mode==="ids")return{locale:e,table:e};let n=[...new Set([t,...r.locales.included,...Object.keys(r.strings)])];if(n.includes(e))return{locale:e,table:e};let s=l=>l.toLowerCase().replace(/_/g,"-"),i=n.find(l=>s(l)===s(e));if(i!==void 0)return{locale:i,table:i,problem:`the locale "${e}" is spelled "${i}" in this bundle, so it's using "${i}"`};let o=s(e).split("-")[0],a=n.find(l=>s(l)===o);return a!==void 0?{locale:a,table:a,problem:`this bundle has no locale "${e}", so it's using its language, "${a}"`}:{locale:t,problem:`this bundle has no locale "${e}", so it's using the default, "${t}", with every string marked untranslated`}}function zt(r,e){return e.table!==void 0?r[e.table]??{}:{}}function Zt(r,e,t,n,s){let i=l=>l?.find(c=>c.name.toLowerCase()===t),o;if(e==="patter")o=i(r.bundle.properties);else if(e==="scene")o=i(s!==null?r.bundle.scenes[s]?.sceneProps:void 0);else{let l=r.bundle.scopeRegistry?.scopes.find(c=>c.token===e);if(!l||l.declarations===void 0)return;o=i(l.declarations)}let a=`@${e}.${t}`;if(o===void 0)throw new Error(`no property at "${a}": the content declares no ${a}`);if(!oe(o,n,{noneChosen:o.type==="enum"&&o.default===""}))throw new Error(`"${a}" takes ${pr(o)}; ${JSON.stringify(n)} doesn't fit`)}function pr(r){let e=t=>(t??[]).map(n=>JSON.stringify(n)).join(", ");switch(r.type){case"number":return"a number";case"boolean":return"true or false";case"enum":return`one of ${e(r.values)}`;case"flags":return r.values!==void 0&&r.values.length>0?`a list of flags from ${e(r.values)}`:"a list of flags";case"quality":return`one of its stages ${e(r.stages)}`;default:return"text"}}function xe(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 ur(r,e,t){let n=t.toLowerCase();return e==="patter"?xe(r,"patter",()=>[...r.patterSharedDecls,...r.patterLocalDecls]).get(n):r.registry.toEvalContext().qualities?.(e,t)??xe(r,`host/${e}`,()=>r.bundle.scopeRegistry?.scopes.find(s=>s.token===e)?.declarations).get(n)}function en(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default,writable:r.writable}}function fr(r,e){let t=en(r),n=r.writable??e;return n===void 0?t:{...t,writable:n}}function Ye(r,e){return Ae(r.bundle.scenes,e,r.sceneGameIdToId)}function Qe(r,e,t){return r.blockGameIdToId.get(e)?.get(t)??(r.blockIndex.get(t)?.sceneId===e?t:void 0)}function tn(r,e){r.refSplitRevision!==r.registry.revision&&(r.refSplitCache.clear(),r.refSplitRevision=r.registry.revision);let t=r.refSplitCache.get(e);return t||(t=yt(e,n=>n==="scene"||r.registry.has(n)||(r.bundle.externalScopes?.includes(n)??!1)),r.refSplitCache.set(e,t)),t}function gr(r,e){let t={};e.scopes?.patter&&(t[O.flowGlobals(r)]=e.scopes.patter);for(let[n,s]of Object.entries(e.sceneBags??{}))t[O.flowScene(r,n)]=s;return t}function hr(r,e){let t={scopes:{},sceneBags:{}},n=O.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[lr(o.slice(6))]=i)}return t}function Yt(r){return typeof r=="boolean"?r:typeof r=="number"?r!==0:typeof r=="string"?r!=="":r.length>0}var xr=(r,e)=>r.shared??e;function Xe(r,e){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.default!==void 0?{default:r.default}:{},shared:xr(r,e)}}function mr(r){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.values?{values:[...r.values]}:{},...r.purpose?{purpose:r.purpose}:{}}}function yr(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 Le(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=R(o);t.push({gameId:a,name:o.name,blocks:o.blocks.map(l=>({gameId:R(l),name:l.name}))});for(let l of o.blocks)yr(l,e);o.sceneProps?.length&&n.push({gameId:a,properties:o.sceneProps.map(l=>Xe(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=>Xe(a,!0))})),i=Object.entries(r.gameDataFields??{}).filter(([,o])=>(o?.length??0)>0).map(([o,a])=>({kind:o,fields:(a??[]).map(mr)}));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=>Xe(o,!0)),scene:n},gameData:i,counts:e}}var ye=(r,e)=>Object.prototype.hasOwnProperty.call(r,e);function nn(r,e){return r.gameDataFields?.[e]??[]}function Ze(r,e,t){return e&&ye(e,t)?e[t]:r.find(n=>n.name===t)?.default}function rn(r,e){let t={};for(let n of r){let s=Ze(r,e,n.name);s!==void 0&&(t[n.name]=s)}for(let[n,s]of Object.entries(e??{}))ye(t,n)||(t[n]=s);return t}function sn(r,e,t){let n=r.extensions!==void 0&&ye(r.extensions,e)?r.extensions[e]:void 0;return n!==void 0&&ye(n.fields,t)?n.fields[t]??[]:[]}function on(r,e,t=""){let n=o=>({...o?.extensions??{}}),s=Object.values(r.scenes??{}),i=o=>(ye(r.scenes??{},o)?r.scenes[o]:void 0)??s.find(a=>R(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=>R(c)===l))}case"snippet":case"option":case"line":case"text":case"gameEvent":{let o,a=(l,c)=>{for(let f of l??[]){if(o!==void 0)return;if(f.type==="group"){if(c&&f.id===t&&e==="option"){o=f;return}if(c&&f.prompt?.id===t&&f.prompt.kind===e){o=f.prompt;return}a(f.children??[],f.selector==="choice");continue}if(f.id===t&&e==="snippet"){o=f;return}let u=(f.beats??[]).find(h=>h.id===t);if(u!==void 0){u.kind===e&&(o=u);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 et(r){return{schema:Z,save:r.saveGame()}}function tt(r,e){if(!e||e.schema!==Z||!e.save)throw new Error(`loadState: not a ${Z} envelope`);r.loadGame(e.save)}function Oe(r){return JSON.stringify(et(r))}function Ne(r,e){tt(r,JSON.parse(e))}function an(r,e){return r.getProperty(e)}function ln(r,e,t){r.setProperty(e,t)}function cn(r,e){for(let[t,n]of Object.entries(e))r.setProperty(t,n)}function rt(r){let e={};for(let t of dn(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,pn(r)),e}function dn(r){return[...r.listBags(),...r.flows().flatMap(e=>e.listBags())]}function br(r){switch(r.type){case"line":return`line ${r.character??"?"}: ${JSON.stringify(r.text)}${nt(r.gameData)}`;case"text":return`text: ${JSON.stringify(r.text)}${nt(r.gameData)}`;case"gameEvent":return`game event ${r.id}${nt(r.gameData)}`;case"choice":return`choice (${r.options.length} option${r.options.length===1?"":"s"})`;case"end":return"end"}}var nt=r=>r?` gameData=${JSON.stringify(r)}`:"";function pn(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 un(r,e={}){let t=e.label?`[${e.label}] `:"",n=Ve({mounts:()=>dn(r),extra:()=>pn(r)},{sink:e.sink,label:t});return{snapshot:()=>rt(r),capture:()=>n.capture(),dispose:()=>n.dispose(),logStep(s){(e.sink??(i=>console.log(i)))(`${t}${br(s)}`)}}}function fn(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 u of s)try{i.send(u)}catch{}s=[]}},c=u=>{o||!i||i.readyState>1||(s.push(JSON.stringify(u)),l())};if(!t)return{flowOpened(){},observe(){},flowClosed(){},setBuild(){},close(){o=!0},state:"closed",build:a,url:e};let f=()=>{let u=JSON.stringify({t:"hello",v:1,build:a,project:r.project,flows:[...n]});try{i?.send(u)}catch{}};try{i=new t(e),i.addEventListener("open",()=>{f(),l()}),i.addEventListener("message",u=>{if(!(!r.onBundle||typeof u.data!="string"))try{let h=JSON.parse(u.data);h.t==="bundle"&&typeof h.build=="string"&&typeof h.data=="string"&&r.onBundle({build:h.build,data:h.data})}catch{}}),i.addEventListener("error",()=>{}),i.addEventListener("close",()=>{i=null,s=[]})}catch{i=null}return{flowOpened(u){n.add(u),c({t:"flowOpen",flow:u})},flowClosed(u){n.delete(u),c({t:"flowClose",flow:u})},observe(u,h,x,p,d){n.has(u)||(n.add(u),c({t:"flowOpen",flow:u})),c({t:"frame",flow:u,sceneId:h,beatId:x,type:p,choiceId:d})},setBuild(u){o||u===a||(a=u,i&&i.readyState===1&&f())},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 gn(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 Sr(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 ot=!1,hn=!1,yn,vr=350,st=6,xn=7,te=null,ne=0,Pe=null,Er=null;function bn(){if(te)return te;let r=document.createElement("div");return r.className="tooltip",r.setAttribute("role","tooltip"),r.hidden=!0,document.body.appendChild(r),te=r,r}var wr=r=>r instanceof HTMLElement?r.getBoundingClientRect():r;function kr(r){let e=bn(),t=wr(r),n=e.getBoundingClientRect(),s=t.top-n.height-xn;s<st&&(s=t.top+t.height+xn);let i=t.left+t.width/2-n.width/2;i=Math.max(st,Math.min(i,window.innerWidth-n.width-st)),e.style.left=`${Math.round(i)}px`,e.style.top=`${Math.round(s)}px`}function Cr(r){let e=r.dataset.tip;e&&Ar(r,e)}function Ar(r,e){if(yn?.())return;let t=bn(),n=(r instanceof HTMLElement?r.closest("dialog[open]"):null)??document.body;t.parentElement!==n&&n.appendChild(t),Pe=r instanceof HTMLElement?r:null,Sr(t,e),t.hidden=!1,t.classList.remove("show"),t.offsetWidth,kr(r),t.classList.add("show")}function ee(){ne&&(window.clearTimeout(ne),ne=0),Pe=null,Er=null,te&&(te.hidden=!0,te.classList.remove("show"))}function mn(r){r!==Pe&&(ne&&window.clearTimeout(ne),ne=window.setTimeout(()=>Cr(r),vr))}function Dr(){Ir()}function Fr(){hn||(hn=!0,setTimeout(()=>{ot||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 it=r=>r instanceof Element?r.closest("[data-tip]"):null;function Ir(r={}){r.suppressed!==void 0&&(yn=r.suppressed),!ot&&(ot=!0,document.addEventListener("pointerover",e=>{let t=it(e.target);t&&mn(t)}),document.addEventListener("pointerout",e=>{let t=it(e.target);if(!t)return;let n=e.relatedTarget;n instanceof Node&&t.contains(n)||ee()}),document.addEventListener("focusin",e=>{let t=it(e.target);t&&mn(t)}),document.addEventListener("focusout",()=>ee()),document.addEventListener("pointerdown",()=>ee(),!0),document.addEventListener("scroll",()=>{Pe&&ee()},!0),document.addEventListener("keydown",e=>{e.key==="Escape"&&ee()}),window.addEventListener("blur",()=>ee()))}function Sn(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),Dr()),s.onClick&&n.addEventListener("click",s.onClick);for(let i of t)i!=null&&n.append(i);return Fr(),n}function vn(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 En=r=>`default (${vn(r)})`;function at(r){let e=r.doc===void 0?Sn:(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:En(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,f=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(f)}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 wn="pp-inspector-style",Rr=`
|
|
1
|
+
"use strict";var Patterplay=(()=>{var $e=Object.defineProperty;var Bn=Object.getOwnPropertyDescriptor;var Ln=Object.getOwnPropertyNames;var On=Object.prototype.hasOwnProperty;var Nn=(r,e)=>{for(var t in e)$e(r,t,{get:e[t],enumerable:!0})},Pn=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Ln(e))!On.call(r,s)&&s!==t&&$e(r,s,{get:()=>e[s],enumerable:!(n=Bn(e,s))||n.enumerable});return r};var Tn=r=>Pn($e({},"__esModule",{value:!0}),r);var Tr={};Nn(Tr,{Checkpoint:()=>me,DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND:()=>de,DEFAULT_PAD_AFTER:()=>U,Engine:()=>Be,Flow:()=>K,Runner:()=>Te,SAVE_SCHEMA:()=>Z,applyLiveBundle:()=>hn,buildTagIndex:()=>Ie,compareStages:()=>z,countSyllables:()=>We,createAudioResolver:()=>Fn,createBundleInspector:()=>Dn,createDebugLink:()=>gn,createPropertyInspector:()=>Cn,createStateLogger:()=>fn,describeBundle:()=>Le,deserializeState:()=>Ne,diffState:()=>ae,effectiveGameData:()=>sn,estimateLineDuration:()=>Rt,extensionDecls:()=>on,extensionsOf:()=>an,gameDataFields:()=>rn,gameDataValue:()=>Ze,getProperty:()=>ln,loadState:()=>tt,nextStage:()=>Y,resolveSceneRef:()=>Ae,saveState:()=>et,sceneAddressIndex:()=>Ke,serializeState:()=>Oe,setProperties:()=>dn,setProperty:()=>cn,snapshotState:()=>rt,speechUnits:()=>X,stageIndex:()=>J});function se(r,e){return r!==void 0&&Object.prototype.hasOwnProperty.call(r,e)?r[e]:void 0}function H(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:H(r[2])};case"bin":return{kind:"binary",op:r[1],left:H(r[2]),right:H(r[3])};case"call":{let e=r.slice(2).map(H);return{kind:"call",name:r[1],args:e}}case"fd":return{kind:"flagdelta",sign:r[1],name:r[2]}}}var C=class extends Error{constructor(e){super(e),this.name="EvalError"}};function Se(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=se(e.scopes,i.scope);if(o===void 0)return!1;let a=typeof o.get=="function"?o.get(i.name):se(o,i.name);if(a===void 0){if(n.get(i.scope)==="throw")throw new C(`@${i.scope}.${i.name} is not declared on the current ${i.scope}.`);return!1}return a}case"call":{if(i.name==="advance"&&!se(t.functions,i.name)){let a=i.args[0];if(i.args.length!==1||a===void 0)throw new C(`advance() takes exactly 1 argument, got ${i.args.length}`);let l=Me(a,e);if(l===void 0)throw new C("advance() needs a quality reference (@scope.name of a quality property)");let c=T(s(a),l,"advance");return l[Math.min(c+1,l.length-1)]}let o=se(t.functions,i.name);if(!o)throw new C(`unknown function '${i.name}'`);return o.eval(i.args,{evaluate:s,ctx:e})}case"flagdelta":throw new C("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 C(`'not' requires a boolean operand, got ${typeof a}`);return!a}let o=s(i.operand);if(typeof o!="number")throw new C(`unary '-' requires a numeric operand, got ${typeof o}`);return-o}case"binary":{if(i.op==="and"){let u=s(i.left);if(typeof u!="boolean")throw new C(`'and' requires boolean operands, left is ${typeof u}`);if(!u)return!1;let h=s(i.right);if(typeof h!="boolean")throw new C(`'and' requires boolean operands, right is ${typeof h}`);return h}if(i.op==="or"){let u=s(i.left);if(typeof u!="boolean")throw new C(`'or' requires boolean operands, left is ${typeof u}`);if(u)return!0;let h=s(i.right);if(typeof h!="boolean")throw new C(`'or' requires boolean operands, right is ${typeof h}`);return h}let o=s(i.left),a=s(i.right),l=Me(i.left,e),c=Me(i.right,e),f=l??c;if(f!==void 0){if(l&&c&&!$n(l,c)&&(i.op===">"||i.op===">="||i.op==="<"||i.op==="<="))throw new C(`'${i.op}' compares two different qualities, whose stage orders are unrelated`);switch(i.op){case">":return T(o,f,">")>T(a,f,">");case">=":return T(o,f,">=")>=T(a,f,">=");case"<":return T(o,f,"<")<T(a,f,"<");case"<=":return T(o,f,"<=")<=T(a,f,"<=");case"+":case"-":case"*":case"/":throw new C(`'${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 ct(o,a);case"!=":return!ct(o,a);case">":return q(o,a,">"),o>a;case">=":return q(o,a,">="),o>=a;case"<":return q(o,a,"<"),o<a;case"<=":return q(o,a,"<="),o<=a;case"+":if(typeof o=="number"&&typeof a=="number"||typeof o=="string"&&typeof a=="string")return o+a;throw new C(`'+' requires two numbers or two strings, got ${typeof o} and ${typeof a}`);case"-":return q(o,a,"-"),o-a;case"*":return q(o,a,"*"),o*a;case"/":if(q(o,a,"/"),a===0)throw new C("division by zero");return o/a}}}};return s(r)}function ct(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 q(r,e,t){if(typeof r!="number"||typeof e!="number")throw new C(`'${t}' requires numeric operands, got ${typeof r} and ${typeof e}`)}function Me(r,e){if(!(r.kind!=="scopedvar"||e.qualities===void 0))return e.qualities(r.scope,r.name)}function T(r,e,t){if(typeof r!="string")throw new C(`'${t}' on a quality compares stages, got ${typeof r}`);let n=e.indexOf(r);if(n<0)throw new C(`"${r}" is not a stage of this quality (stages: ${e.join(", ")})`);return n}var $n=(r,e)=>r.length===e.length&&r.every((t,n)=>t===e[n]);function ie(r){if(Number.isNaN(r)||!Number.isFinite(r))return 0;let e=Math.trunc(r)%4294967296;return e<0?e+4294967296:e}function je(r){let e=ie(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 Ge=r=>Array.isArray(r)?r:r.stages??[],Mn=r=>Array.isArray(r)?"flags":r==null?"nothing":typeof r;function J(r,e){return typeof e=="string"?Ge(r).indexOf(e):-1}function _e(r,e){if(typeof e!="string")throw new C(`a stage is a name, got ${Mn(e)}`);let t=r.indexOf(e);if(t<0)throw new C(`"${e}" is not a stage of this quality (stages: ${r.join(", ")})`);return t}function z(r,e,t){let n=Ge(r),s=_e(n,e)-_e(n,t);return s<0?-1:s>0?1:0}function Y(r,e){let t=Ge(r);return t[Math.min(_e(t,e)+1,t.length-1)]}function oe(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 jn={name:"check_flags",count:r=>Math.max(1,r.args.length-1)},_n=[jn];function dt(r,e,t){let n=t?.countingCalls??_n;return ve(r,t?.want??!0,e,n)}function ve(r,e,t,n){if(r.kind==="binary"&&(r.op==="and"||r.op==="or")){let s=ve(r.left,e,t,n),i=ve(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 ve(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 ae(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 pt=r=>r===void 0?"<unset>":JSON.stringify(r),ut=r=>r.pathPrefix??r.bag.pathPrefix;function Ve(r,e={}){let t=e.sink??(u=>console.log(u)),n=e.label??"",s=u=>{t(`${n}${u.path}: ${pt(u.from)} -> ${pt(u.to)}`)},i=()=>{let u={};for(let h of r.mounts()){let x=ut(h);for(let[p,d]of Object.entries(h.bag.values))u[x+p]=d}return Object.assign(u,r.extra?.()??{}),structuredClone(u)},o=i(),a=[],l=[],c=(u,h)=>h.onAudit(x=>{let p=structuredClone({path:u+x.name,from:x.prev,to:x.next});s(p),a.push(p),o[p.path]=structuredClone(x.next)}),f=()=>{let u=r.mounts();if(!(l.length===u.length&&u.every((x,p)=>l[p].bag===x.bag))){for(let x of l)x.off();l=u.map(x=>({bag:x.bag,off:c(ut(x),x.bag)}))}};return f(),{snapshot:i,capture(){let u=i(),h=ae(o,u);for(let p of h)s(p);let x=[...a,...h];return a=[],o=u,f(),x},dispose(){for(let u of l)u.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??Q(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])=>gt(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);oe(o,a,{noneChosen:o.type==="enum"&&o.default===""})||(this.values[i]=structuredClone(Q(o)),s.push({name:i,value:a}))}return s}};function gt(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??Q(r),...r.values!==void 0?{values:r.values}:{},...r.stages!==void 0?{stages:r.stages}:{},writable:t??r.writable??!0}}var Gn=r=>r.toLowerCase(),He=1,Ee=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??Gn,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,...gt(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(Vn(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 ft(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=ft(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:He,scopes:this.save()}}loadFragment(e){if(e.version!==He)throw new Error(`unsupported owned-state fragment version ${e.version} (supported: ${He})`);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 ft(r){return r.kind==="foreign"?[...r.decls.entries()]:r.bag.declarations().map(e=>[r.bag.normalise(e.name),e])}function Vn(r){return r.kind==="foreign"?r.norm:e=>r.bag.normalise(e)}function Q(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 ht=[{token:"patter",engine:"Patterplay",means:"Patter's shared globals"},{token:"story",engine:"Storylet Engine",means:"the Storylet Engine's shared @story properties"}];function le(r){return r.ctx.host??{}}var qe={defaultScope:"patter",scopes:[{token:"patter"},{token:"scene"}],functions:{random:{minArgs:2,maxArgs:2,returnType:"number",eval(r,e){if(r.length!==2)throw new C("random(a, b) requires exactly 2 arguments");let t=le(e).nextRandom;if(!t)throw new C("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 C("random(a, b) arguments must be numbers");if(!Number.isInteger(n)||!Number.isInteger(s))throw new C("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:mt("check_flags"),eval(r,e){let t=xt(r[0],e,"check_flags");for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new C("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:mt("set_flags"),eval(r,e){let t=[...xt(r[0],e,"set_flags")];for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new C("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:ke("visits"),eval:(r,e)=>le(e).visits?.(we(r,e,"visits"))??0},seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:ke("seen"),eval:(r,e)=>(le(e).visits?.(we(r,e,"seen"))??0)>0},patter_visits:{minArgs:1,maxArgs:1,returnType:"number",validate:ke("patter_visits"),eval:(r,e)=>le(e).patterVisits?.(we(r,e,"patter_visits"))??0},patter_seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:ke("patter_seen"),eval:(r,e)=>(le(e).patterVisits?.(we(r,e,"patter_seen"))??0)>0}}},us=ht.map(r=>r.token).filter(r=>r!=="patter"&&r!=="scene");function yt(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 we(r,e,t){let n=e.evaluate(r[0]);if(typeof n!="string")throw new C(`${t}(id) requires a string node id`);return n}function ke(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 xt(r,e,t){if(!r)throw new C(`${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 C(`${t}() first argument must be a flags property`)}function mt(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 Hn=/^@[A-Za-z0-9_.]+$/;function*qn(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:Hn.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 Un(r){return Array.isArray(r)?r.join(", "):typeof r=="boolean"?r?"true":"false":String(r)}function Wn(r){return r===" "||r===" "||r===`
|
|
2
|
+
`||r==="\r"||r==="\f"||r==="\v"}function Kn(r){let e="",t=!1;for(let n of r){if(Wn(n)){t=!0;continue}t&&e.length>0&&(e+=" "),t=!1,e+=n}return e}function bt(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?Kn(n):r}function St(r,e){if(r.indexOf("{")<0)return r;let t="";for(let n of qn(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?"":Un(s)}return t}function vt(r){return r.toLowerCase().replace(/['’]/g,"").replace(/[^a-z0-9-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}var y={NONE:0,LATIN_VOWEL:1,LATIN_LETTER:2,CYRILLIC_VOWEL:3,CYRILLIC_LETTER:4,HAN:5,KANA:6,KANA_SMALL:7,KANA_SOKUON:8,KANA_LONG:9,HANGUL:10,ARABIC_LETTER:11,ARABIC_VOWEL:12,THAI_CONSONANT:13,THAI_LEAD:14,THAI_VOWEL:15,MARK:16,OTHER_LETTER:17,DIGIT:18,PAUSE_SHORT:19,PAUSE_LONG:20,JOINER:21,SPACE:22},ce=[9,13,22,32,32,22,33,33,20,39,39,21,44,44,19,46,46,20,48,57,18,58,59,19,63,63,20,65,65,1,66,68,2,69,69,1,70,72,2,73,73,1,74,78,2,79,79,1,80,84,2,85,85,1,86,88,2,89,89,1,90,90,2,97,97,1,98,100,2,101,101,1,102,104,2,105,105,1,106,110,2,111,111,1,112,116,2,117,117,1,118,120,2,121,121,1,122,122,2,133,133,22,160,160,22,170,170,2,173,173,21,181,181,17,186,186,2,192,198,1,199,199,2,200,207,1,208,209,2,210,214,1,216,221,1,222,223,2,224,230,1,231,231,2,232,239,1,240,241,2,242,246,1,248,253,1,254,254,2,255,261,1,262,273,2,274,283,1,284,295,2,296,305,1,306,331,2,332,339,1,340,359,2,360,371,1,372,373,2,374,376,1,377,415,2,416,417,1,418,430,2,431,432,1,433,460,2,461,476,1,477,477,2,478,483,1,484,489,2,490,493,1,494,505,2,506,527,1,528,531,2,532,535,1,536,549,2,550,563,1,564,696,2,697,699,17,700,700,21,701,705,17,710,721,17,736,740,2,748,748,17,750,750,17,768,879,16,880,884,17,886,893,17,895,895,17,902,902,17,904,1013,17,1015,1023,17,1024,1025,3,1026,1027,4,1028,1028,3,1029,1029,4,1030,1031,3,1032,1036,4,1037,1038,3,1039,1039,4,1040,1040,3,1041,1044,4,1045,1045,3,1046,1047,4,1048,1048,3,1049,1053,4,1054,1054,3,1055,1058,4,1059,1059,3,1060,1066,4,1067,1067,3,1068,1068,4,1069,1072,3,1073,1076,4,1077,1077,3,1078,1079,4,1080,1080,3,1081,1085,4,1086,1086,3,1087,1090,4,1091,1091,3,1092,1098,4,1099,1099,3,1100,1100,4,1101,1105,3,1106,1107,4,1108,1108,3,1109,1109,4,1110,1111,3,1112,1116,4,1117,1118,3,1119,1153,4,1155,1161,16,1162,1231,4,1232,1235,3,1236,1237,4,1238,1239,3,1240,1249,4,1250,1255,3,1256,1259,4,1260,1267,3,1268,1271,4,1272,1273,3,1274,1327,4,1329,1369,17,1376,1416,17,1425,1469,17,1471,1471,17,1473,1474,17,1476,1477,17,1479,1522,17,1548,1548,19,1552,1562,16,1563,1563,19,1567,1567,20,1568,1599,11,1600,1600,16,1601,1610,11,1611,1616,12,1617,1631,16,1632,1641,18,1646,1647,11,1648,1648,12,1649,1747,11,1748,1748,20,1749,1749,11,1750,1756,16,1759,1764,16,1765,1766,11,1767,1768,16,1770,1773,16,1774,1775,11,1776,1785,18,1786,1788,11,1791,1791,11,1808,1871,17,1872,1919,11,1920,2037,17,2042,2045,17,2048,2093,17,2112,2139,17,2144,2154,17,2160,2183,11,2185,2191,11,2199,2207,16,2208,2249,11,2250,2273,16,2275,2303,16,2304,2384,17,2385,2388,16,2389,2403,17,2404,2405,20,2406,2415,17,2417,2545,17,2556,2556,17,2558,2677,17,2689,2799,17,2809,2927,17,2929,2929,17,2946,3055,17,3072,3183,17,3200,3203,17,3205,3406,17,3412,3415,17,3423,3439,17,3450,3571,17,3585,3630,13,3631,3631,16,3632,3641,15,3642,3642,16,3648,3652,14,3653,3654,16,3655,3655,15,3656,3660,16,3661,3661,15,3662,3662,16,3664,3673,18,3713,3840,17,3864,3865,17,3872,3881,17,3893,3893,17,3895,3895,17,3897,3897,17,3902,3972,17,3974,4028,17,4038,4038,17,4096,4169,17,4176,4253,17,4256,4346,17,4348,4959,17,4992,5007,17,5024,5117,17,5121,5740,17,5743,5759,17,5760,5760,22,5761,5786,17,5792,5866,17,5873,5940,17,5952,6099,17,6103,6103,17,6108,6121,17,6155,6157,17,6159,6459,17,6470,6617,17,6656,6683,17,6688,6809,17,6823,6823,17,6832,6891,16,6912,6988,17,6992,7001,17,7019,7027,17,7040,7155,17,7168,7223,17,7232,7293,17,7296,7306,4,7312,7359,17,7376,7378,16,7380,7392,16,7393,7393,17,7394,7400,16,7401,7404,17,7405,7405,16,7406,7411,17,7412,7412,16,7413,7415,17,7416,7417,16,7418,7418,17,7424,7461,2,7462,7466,17,7467,7467,4,7468,7516,2,7517,7521,17,7522,7525,2,7526,7530,17,7531,7543,2,7544,7544,4,7545,7614,2,7615,7615,17,7616,7679,16,7680,7681,1,7682,7699,2,7700,7709,1,7710,7723,2,7724,7727,1,7728,7755,2,7756,7763,1,7764,7793,2,7794,7803,1,7804,7821,2,7822,7823,1,7824,7832,2,7833,7833,1,7834,7839,2,7840,7929,1,7930,7935,2,7936,8124,17,8126,8126,17,8130,8140,17,8144,8155,17,8160,8172,17,8178,8188,17,8192,8202,22,8204,8205,21,8211,8212,19,8217,8217,21,8230,8230,20,8232,8233,22,8239,8239,22,8253,8253,20,8263,8265,20,8287,8287,22,8305,8305,2,8319,8319,2,8336,8348,2,8400,8432,16,8450,8450,17,8455,8455,17,8458,8467,17,8469,8469,17,8473,8477,17,8484,8484,17,8486,8486,17,8488,8488,17,8490,8490,2,8491,8491,1,8492,8493,17,8495,8497,17,8498,8498,2,8499,8505,17,8508,8511,17,8517,8521,17,8526,8526,2,8579,8580,2,11264,11359,17,11360,11391,2,11392,11492,17,11499,11507,17,11520,11631,17,11647,11742,17,11744,11775,16,11823,11823,17,12288,12288,22,12289,12289,19,12290,12290,20,12293,12293,5,12294,12294,17,12330,12335,16,12337,12341,17,12347,12347,5,12348,12348,17,12353,12353,7,12354,12354,6,12355,12355,7,12356,12356,6,12357,12357,7,12358,12358,6,12359,12359,7,12360,12360,6,12361,12361,7,12362,12386,6,12387,12387,8,12388,12418,6,12419,12419,7,12420,12420,6,12421,12421,7,12422,12422,6,12423,12423,7,12424,12429,6,12430,12430,7,12431,12436,6,12437,12438,7,12441,12444,16,12445,12447,6,12449,12449,7,12450,12450,6,12451,12451,7,12452,12452,6,12453,12453,7,12454,12454,6,12455,12455,7,12456,12456,6,12457,12457,7,12458,12482,6,12483,12483,8,12484,12514,6,12515,12515,7,12516,12516,6,12517,12517,7,12518,12518,6,12519,12519,7,12520,12525,6,12526,12526,7,12527,12538,6,12540,12540,9,12541,12543,6,12549,12686,17,12704,12735,17,12784,12799,7,13312,19903,5,19968,40959,5,40960,42124,17,42192,42237,17,42240,42508,17,42512,42539,17,42560,42606,4,42607,42610,16,42612,42621,16,42623,42653,4,42654,42655,16,42656,42725,17,42736,42737,17,42775,42783,17,42786,42887,2,42888,42888,17,42891,43007,2,43008,43047,17,43052,43052,17,43072,43123,17,43136,43205,17,43216,43255,17,43259,43259,17,43261,43309,17,43312,43347,17,43360,43456,17,43471,43481,17,43488,43609,17,43616,43638,17,43642,43741,17,43744,43759,17,43762,43822,17,43824,43866,2,43868,43876,2,43877,43877,17,43878,43881,2,43888,44010,17,44012,44025,17,44032,55203,10,55216,55291,17,63744,64217,5,64256,64262,2,64275,64296,17,64298,64335,17,64336,64433,11,64467,64829,11,64848,64911,11,64914,64967,11,65008,65019,11,65024,65039,16,65056,65071,16,65104,65105,19,65136,65276,11,65281,65281,20,65292,65292,19,65294,65294,20,65296,65305,18,65306,65307,19,65311,65311,20,65313,65338,2,65345,65370,2,65377,65377,20,65380,65380,19,65382,65382,6,65383,65390,7,65391,65391,8,65392,65392,9,65393,65437,6,65438,65439,16,65440,65500,17,65536,65786,17,66045,66045,16,66176,66256,17,66272,66272,16,66304,66335,17,66349,66368,17,66370,66377,17,66384,66461,17,66464,66511,17,66560,66915,17,66928,67431,17,67456,67514,2,67584,67669,17,67680,67702,17,67712,67742,17,67808,67829,17,67840,67861,17,67872,67897,17,67904,68023,17,68030,68031,17,68096,68159,17,68192,68220,17,68224,68252,17,68288,68295,17,68297,68326,17,68352,68405,17,68416,68437,17,68448,68466,17,68480,68497,17,68608,68850,17,68864,68973,17,68975,68997,17,69248,69292,17,69296,69297,17,69314,69319,11,69370,69375,16,69376,69404,17,69415,69456,17,69488,69509,17,69552,69572,17,69600,69702,17,69734,69818,17,69826,69826,17,69840,69951,17,69956,70003,17,70006,70084,17,70089,70092,17,70094,70106,17,70108,70108,17,70144,70199,17,70206,70312,17,70320,70457,17,70459,70459,16,70460,70611,17,70625,70730,17,70736,70745,17,70750,70853,17,70855,71104,17,71128,71232,17,71236,71257,17,71296,71352,17,71360,71481,17,71488,71738,17,71840,71913,17,71935,72003,17,72016,72161,17,72163,72254,17,72263,72345,17,72349,72349,17,72368,72440,17,72544,72672,17,72688,72768,17,72784,72793,17,72818,73462,17,73472,73538,17,73552,73648,17,73728,74649,17,74880,77808,17,77824,78895,17,78912,92777,17,92784,92916,17,92928,92982,17,92992,92995,17,93008,93017,17,93027,93548,17,93552,93823,17,93856,94177,17,94179,94179,5,94180,94180,17,94192,94193,16,94194,94195,5,94208,101874,17,110576,110951,6,110960,113817,17,113821,113822,17,118e3,118009,17,118528,118598,16,119141,119142,17,119143,119145,16,119149,119154,17,119163,119170,16,119173,119179,16,119210,119213,16,119362,119364,17,119808,120512,17,120514,120538,17,120540,120570,17,120572,120596,17,120598,120628,17,120630,120654,17,120656,120686,17,120688,120712,17,120714,120744,17,120746,120770,17,120772,120831,17,121344,121398,17,121403,121452,17,121461,121461,17,121476,121476,17,121499,121519,17,122624,122666,2,122880,122922,17,122928,122989,4,123023,123023,16,123136,123214,17,123536,123641,17,124112,124410,17,124608,125124,17,125136,125273,17,126464,126651,11,130032,130041,17,131072,210041,5,917760,917999,16];var Dt=1.5,Ft=2,Ue=1,It=2,E=(r,e)=>r[e]??-1;function Jn(r){let e=0,t=ce.length/3-1;for(;e<=t;){let n=e+t>>1;if(r<E(ce,n*3))t=n-1;else if(r>E(ce,n*3+1))e=n+1;else return E(ce,n*3+2)}return y.NONE}function zn(r){return((r??"").split(/[-_]/)[0]??"").toLowerCase()}var Et=r=>r>=65&&r<=90||r>=97&&r<=122,Yn=r=>r>=48&&r<=57;function Qn(r,e){let t=n=>E(r,n);if(t(e)===60){let n=e+1;t(n)===47&&n++;let s=n;for(;Et(t(n));)n++;return n>s&&t(n)===62?n+1:e}if(t(e)===38){let n=e+1,s=t(n)===35;s&&n++;let i=n;for(;s?Yn(t(n)):Et(t(n));)n++;return n>i&&t(n)===59?n+1:e}return e}var wt=new Set([y.LATIN_VOWEL,y.LATIN_LETTER]),kt=new Set([y.CYRILLIC_VOWEL,y.CYRILLIC_LETTER]),Ct=new Set([y.ARABIC_LETTER,y.ARABIC_VOWEL]),Ce=new Set([y.THAI_CONSONANT,y.THAI_LEAD,y.THAI_VOWEL]),At=new Set([y.OTHER_LETTER]),Xn=new Set([y.KANA,y.KANA_SMALL,y.KANA_SOKUON,y.KANA_LONG]);function X(r,e){let t=Array.from(r??"",d=>d.codePointAt(0)),n=t.map(Jn),s=t.length,i=zn(e),o=i==="ja"||n.some(d=>Xn.has(d)),a=[],l=(d,w,g=1)=>{a.push({kind:"syllable",weight:g,start:d,end:w})},c=d=>d>=0&&d<s?E(n,d):y.NONE,f=d=>{for(;d<s&&E(n,d)===y.MARK;)d++;return d},u=(d,w)=>{let g=d+1;for(;g<s&&(w.has(E(n,g))||E(n,g)===y.MARK||E(n,g)===y.JOINER&&w.has(c(g+1)));)g++;return g},h=(d,w,g)=>{let b=[...new Set(g.map(v=>Math.min(f(v+1),w)-1))].sort((v,k)=>v-k);b.forEach((v,k)=>l(k===0?d:E(b,k-1)+1,k===b.length-1?w:v+1))},x=(d,w,g)=>Array.from({length:w},(b,v)=>E(d,Math.min(g*v+g-1,d.length-1))),p=0;for(;p<s;){let d=E(n,p),w=Qn(t,p);if(w>p){p=w;continue}if(wt.has(d)){let g=u(p,wt),b=[],v=[],k=!1;for(let I=p;I<g;I++)E(n,I)===y.LATIN_VOWEL?(k?(b[b.length-1]=I,v[v.length-1]=E(v,v.length-1)+1):(b.push(I),v.push(1)),k=!0):E(n,I)!==y.MARK&&(k=!1);b.length>=2&&E(v,v.length-1)===1&&er(t,n,p,g,E(b,b.length-1),i)&&b.pop(),h(p,g,b.length?b:[g-1]),p=g}else if(kt.has(d)){let g=u(p,kt),b=[];for(let v=p;v<g;v++)E(n,v)===y.CYRILLIC_VOWEL&&b.push(v);h(p,g,b.length?b:[g-1]),p=g}else if(Ct.has(d)){let g=u(p,Ct),b=[],v=[];for(let k=p;k<g;k++)E(n,k)===y.ARABIC_VOWEL?b.push(k):E(n,k)===y.ARABIC_LETTER&&v.push(k);h(p,g,b.length?b:x(v,Math.max(1,Math.ceil(v.length/2)),2)),p=g}else if(Ce.has(d)){let g=u(p,Ce);h(p,g,tr(n,p,g)),p=g}else if(At.has(d)){let g=u(p,At),b=[];for(let v=p;v<g;v++)E(n,v)===y.OTHER_LETTER&&b.push(v);h(p,g,x(b,Math.max(1,Math.ceil(b.length/3)),3)),p=g}else if(d===y.HAN){let g=f(p+1);l(p,g,o?Ft:1),p=g}else if(d===y.KANA||d===y.HANGUL){let g=f(p+1);l(p,g),p=g}else if(d===y.KANA_SMALL||d===y.KANA_LONG){let g=f(p+1),b=a[a.length-1];b&&b.kind==="syllable"&&b.end===p?(b.end=g,d===y.KANA_LONG&&(b.weight+=1)):d===y.KANA_SMALL&&l(p,g),p=g}else if(d===y.KANA_SOKUON){let g=f(p+1);a.push({kind:"closed",weight:1,start:p,end:g}),p=g}else if(d===y.DIGIT){let g=f(p+1);l(p,g,Dt),p=g}else if(d===y.PAUSE_SHORT||d===y.PAUSE_LONG)(E(t,p)===46||E(t,p)===44)&&c(p-1)===y.DIGIT&&c(p+1)===y.DIGIT||a.push({kind:"pause",weight:d===y.PAUSE_LONG?It:Ue,start:p,end:p+1}),p++;else if(d===y.SPACE){let g=p+1;for(;g<s&&E(n,g)===y.SPACE;)g++;Zn(n,p-1)&&Ce.has(c(g))&&a.push({kind:"pause",weight:Ue,start:p,end:g}),p=g}else p++}return nr(a)}function Zn(r,e){for(;e>=0&&E(r,e)===y.MARK;)e--;return e>=0&&Ce.has(E(r,e))}function er(r,e,t,n,s,i){if(i!=="en"&&i!=="fr"||E(r,s)!==101&&E(r,s)!==69)return!1;let o=s+1;return!(o<n&&E(e,o)===y.MARK||(i==="fr"&&o<n&&(E(r,o)===115||E(r,o)===83)&&o++,o!==n)||i==="en"&&s-2>=t&&(E(r,s-1)===108||E(r,s-1)===76)&&E(e,s-2)===y.LATIN_LETTER)}function tr(r,e,t){let n=[],s=[],i=!1,o=()=>{for(let a=0;a<Math.floor((s.length-1)/2);a++)n.push(E(s,2*a+1))};for(let a=e;a<t;a++){let l=E(r,a);if(l===y.THAI_CONSONANT)s.push(a);else if(l===y.THAI_LEAD)o(),n.push(a+1<t&&E(r,a+1)===y.THAI_CONSONANT?a+1:a),s=[],i=!0;else if(l===y.THAI_VOWEL){if(s.length===0)continue;if(i&&s.length<=2){i=!1,s=[];continue}o(),n.push(a),s=[],i=!1}}if(n.length===0){let a=Math.max(1,Math.ceil(s.length/2));for(let l=0;l<a;l++)n.push(s.length?E(s,Math.min(2*l+1,s.length-1)):t-1)}else o();return n}function nr(r){let e=[];for(let t of r){let n=e[e.length-1];t.kind==="pause"&&n?.kind==="pause"?(n.weight=Math.max(n.weight,t.weight),n.end=t.end):e.push({...t})}for(;e[0]?.kind==="pause";)e.shift();for(;e[e.length-1]?.kind==="pause";)e.pop();return e}function We(r,e){let t=0;for(let n of X(r,e))n.kind!=="pause"&&(t+=n.weight);return t}function G(r,e){for(let t of r){e(t);let n=t.children;n&&G(n,e)}}function R(r){let e=r.gameId?.trim();return e||vt(r.name)}function Ke(r){let e=new Map;for(let[t,n]of Object.entries(r))e.set(R(n),t);return e}function Ae(r,e,t){return(t??Ke(r)).get(e)??(Object.hasOwn(r,e)?e:void 0)}var U=.6;var de=4;var rr=1.5,sr=18;function Rt(r,e,t){let n=typeof t=="number"&&Number.isFinite(t)&&t>0?t:de,s=0;for(let i of X(r??"",e))s+=i.weight;return Math.min(Math.max(s/n,rr),sr)}function De(r){return`cast:${r}`}function Fe(r){return`qualifier:${r}`}function Bt(r,e){return`speaker:${r}:${e}`}var Lt="speaker:pattern",Ot="{name} ({qualifier})";function Nt(r,e,t){return r.split("{name}").map(n=>n.split("{qualifier}").join(t)).join(e)}var Je={open:"[",close:"]"},Pt="SFX",Z="patter/save@0",pe=4;function ue(r){let e=new Set,t=[];for(let n of r)e.has(n)||(e.add(n),t.push(n));return t}function Ie(r){let e=new Map,t=(n,s)=>{let i=ue([...s,...n.tags??[]]);if(e.set(n.id,i),n.type==="group"&&n.prompt&&e.set(n.prompt.id,ue([...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,ue([...i,...o.tags??[]]))};for(let n of Object.values(r.scenes)){let s=ue(n.tags??[]);e.set(n.id,s);for(let i of n.blocks){let o=ue([...s,...i.tags??[]]);e.set(i.id,o);for(let a of i.children)t(a,o)}}return e}var Tt=r=>r.kind==="line"||r.kind==="text",fe=r=>typeof r=="number"&&Number.isFinite(r)?r:void 0;function $t(r){let e=new Map,t=(i,o,a)=>{let l=i.kind==="gameEvent"?void 0:fe(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=fe(i.padAfterDefault)??o;if(i.type==="group"){i.prompt&&t(i.prompt,a,!1);for(let f of i.children)n(f,a);return}let l=i.beats??[],c=-1;l.forEach((f,u)=>{Tt(f)&&(c=u)}),l.forEach((f,u)=>{Tt(f)&&t(f,a,u===c)})},s=fe(r.padAfterDefault)??U;for(let i of Object.values(r.scenes)){let o=fe(i.padAfterDefault)??s;for(let a of i.blocks){let l=fe(a.padAfterDefault)??o;for(let c of a.children)n(c,l)}}return e}var Mt=new WeakMap,jt=new WeakMap;function ir(r){let e=jt.get(r);return e||(e=Ie(r),jt.set(r,e)),e}var _t=new WeakMap;function or(r){let e=_t.get(r);return e||(e=$t(r),_t.set(r,e)),e}var Gt=new WeakMap;function ar(r){let e=Gt.get(r);if(e)return e;e=new Map;for(let t of Object.values(r.scenes))for(let n of t.blocks)G(n.children,s=>{if(s.type==="group"&&s.selector==="choice")for(let i of s.children)e.set(i.id,s.id)});return Gt.set(r,e),e}var Vt=new WeakMap;function lr(r){let e=Vt.get(r);if(e)return e;e=new Map;for(let t of Object.values(r.scenes))for(let n of t.blocks)G(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 Vt.set(r,e),e}function N(r){if(r===void 0)return;let e={};for(let[t,n]of Object.entries(r))e[t]=Array.isArray(n)?[...n]:n;return e}function W(r,e){return r.tagIndex.get(e)?.slice()}var he="Patter",ge=r=>r.replace(/%/g,"%25").replace(/\//g,"%2F"),cr=r=>r.replace(/%2F/g,"/").replace(/%25/g,"%"),Ht=Symbol("ownsRegistry"),qt=Symbol("setupReported"),O={stage:r=>`patter/scene/${ge(r)}`,flow:r=>`patter/flow/${ge(r)}/`,flowGlobals:r=>`patter/flow/${ge(r)}/patter`,flowScene:(r,e)=>`patter/flow/${ge(r)}/scene/${ge(e)}`},me=class{constructor(e){this.journal=e}journal},Be=class r{host;defaultSeed;flowsById=new Map;allStrings;currentLocale;requestedLocale;sourceDebug;sceneGameIdToId=new Map;blockGameIdToId=new Map;creationOptions;engineLog=[];engineSeq=0;engineTraceHandlers=new Set;constructor(e,t={}){this.creationOptions=t;let n=[];for(let m of Object.keys(t))pr.has(m)||n.push({node:m,message:m==="world"?'the engine option "world" has gone: bind the scope as hostScopes: { world }':`"${m}" isn't an engine option, so it's ignored`});let s=e.strings;this.allStrings=s,this.requestedLocale=t.locale,this.currentLocale=ze(e,t.locale),this.currentLocale.problem&&n.push({node:t.locale,message:this.currentLocale.problem});let i=Yt(s,this.currentLocale),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 f=new Map;for(let m of e.qualifiers??[])m?.gameId&&f.set(m.gameId,m.name);let u=new Map;for(let m of e.cast??[])for(let[F,A]of Object.entries(m.qualifierLabels??{}))typeof A=="string"&&u.set(`${m.name}\0${F}`,A);let h=e.speakerPattern??Ot;this.defaultSeed=(t.seed??2654435769)>>>0;let x=new Map,p=new Map,d=new Map;for(let[m,F]of Object.entries(e.scenes)){this.sceneGameIdToId.set(R(F),m);let A=new Map;for(let L of F.blocks)p.set(L.id,{sceneId:m}),d.set(L.id,L),A.set(R(L),L.id),G(L.children,j=>x.set(j.id,j));this.blockGameIdToId.set(m,A)}let w=e.properties??[],g=w.filter(m=>m.shared??!0).map(Jt),b=w.filter(m=>!(m.shared??!0)).map(Jt),v=new Set(g.map(m=>m.name.toLowerCase())),k=t.registry??new Ee,I=!t.registry||t[Ht]===!0,$=new _(g,{pathPrefix:"@patter."}),M=[],S=[];try{k.mountOwned("patter",$,{owner:he}),S.push("patter");let m=new Set,F=e.scopeRegistry?.scopes??[];for(let[A,L]of Object.entries(t.hostScopes??{})){let j=F.find(be=>be.token===A);if(!j&&!(e.externalScopes??[]).includes(A)){let be=F.find(Rn=>Rn.token.toLowerCase()===A.toLowerCase());n.push({node:A,message:be?`hostScopes binds "${A}", which this bundle doesn't declare: it declares "${be.token}", and a scope's token is case-sensitive`:`hostScopes binds "${A}", which this bundle doesn't declare`})}let In=(j?.declarations??[]).map(tn);k.defineForeign(A,L,In,{writable:j?.writable??!0,owner:he}),S.push(A),m.add(A)}for(let A of I?e.scopeRegistry?.scopes??[]:[]){if(m.has(A.token)||k.has(A.token))continue;let L=(A.declarations??[]).map(j=>gr(j,A.writable));k.defineOwned(A.token,L,{owner:he}),S.push(A.token),M.push(A.token)}}catch(m){for(let F of S)k.remove(F,{keep:!0});throw m}let B=new Map;for(let[m,F]of Object.entries(e.scenes)){let A=new Set((F.sceneProps??[]).filter(L=>L.shared??!1).map(L=>L.name.toLowerCase()));B.set(m,A)}if(this.host={logEnabled:t.log??!1,tracing:t.log??!1,emitEngine:(m,F,A)=>this.emitEngine(m,F,A),bundle:e,emitIds:l,strings:i,defaultStrings:o,castDisplay:c,qualifierDisplay:f,speakerLabels:u,speakerPattern:h,nodeIndex:x,blockIndex:p,blockById:d,sceneGameIdToId:this.sceneGameIdToId,blockGameIdToId:this.blockGameIdToId,tagIndex:ir(e),padIndex:or(e),registry:k,ownsRegistry:I,patterBag:$,hostScopes:M,patterSharedDecls:g,patterLocalDecls:b,patterSharedNames:v,sceneSharedNames:B,sharedVisits:new Map,qualityLadders:new Map,sharedSelectors:new Map,stageBags:new Map,journal:null,customRng:t.rng,onDryChoice:t.onDryChoice,steer:zt(t.steer,n),onError:t.onError??(m=>console.warn(m.kind==="setup"?`Patterplay: ${m.message}`:m.kind==="save"?`Patterplay: flow '${m.flow}': ${m.message}`:`Patterplay: ${m.kind} on ${m.node} in flow '${m.flow}' failed, played through: ${m.message}`)),reportRefits:()=>{let m=k.takeMisfits(F=>F==="patter"||F.startsWith("patter/")||M.includes(F));if(m.length!==0)if(t.onRefit)t.onRefit(m);else for(let F of m)console.warn(`Patterplay: the save's ${F.scope}.${F.name} was ${JSON.stringify(F.value)}, which no longer fits its declaration; it is back at its default`)},replayPromptOnChoose:t.replayPromptOnChoose??!1,captionsOn:t.closedCaptions??!0,captionOpen:(e.closedCaptions??Je).open,captionClose:(e.closedCaptions??Je).close,captionCharacter:e.closedCaptions?.character||Pt,refSplitCache:new Map,refSplitRevision:k.revision},this.host.reportRefits(),t[qt]!==!0)for(let m of n)this.reportSetup(m.node,m.message)}reportSetup(e,t){this.host.onError({flow:"",kind:"setup",node:e,message:t}),this.host.tracing&&this.emitEngine("",{type:"diagnostic",kind:"setup",node:e,message:t})}get locale(){return this.currentLocale.locale}get locales(){let{default:e,included:t}=this.host.bundle.locales;return{default:e,included:[...t]}}get isSourceDebug(){return this.sourceDebug}get buildId(){return this.host.bundle.content?.hash??""}setLocale(e){this.requestedLocale=e,this.useLocale(ze(this.host.bundle,e)),this.currentLocale.problem&&this.reportSetup(e,this.currentLocale.problem)}useLocale(e){this.currentLocale=e,this.host.strings=Yt(this.allStrings,e)}replaceStrings(e){this.allStrings=e.strings;let t=this.currentLocale.problem;this.useLocale(ze(e,this.requestedLocale)),this.host.defaultStrings=this.allStrings[this.host.bundle.locales.default]??{};let n=this.currentLocale.problem;n&&n!==t&&this.reportSetup(this.requestedLocale,n)}hotSwap(e){this.refuseInCheckpoint("hotSwap");let t=this.saveGame(),n=c=>(c.setClosedCaptions(this.host.captionsOn),c),s=this.requestedLocale,i=(c=!1)=>new r(e,{...this.creationOptions,...s!==void 0?{locale:s}:{},steer:this.host.steer,registry:this.host.registry,[Ht]:this.host.ownsRegistry,[qt]:c}),o=new Set(["patter",...this.host.hostScopes]),a=this.host.ownsRegistry?void 0:Object.fromEntries(Object.entries(this.host.registry.save()).filter(([c])=>o.has(c)||c.startsWith("patter/")));this.release(!0),a&&this.host.registry.load(a,{keepParked:!0,refit:!0});let l=i();try{return l.loadGame(t),n(l)}catch{l.release(!0);let c=this.host.ownsRegistry?t.registry:a;c&&this.host.registry.load(c,{keepParked:!0,refit:!0});let f=i(!0);for(let[u,h]of Object.entries(t.flows)){let x=h.cursor.currentSceneId;try{f.openFlow(u,x!==null?{scene:x}:{})}catch{}}return n(f)}}get closedCaptions(){return this.host.captionsOn}setClosedCaptions(e){this.host.captionsOn=e}setSteer(e){if(e==null){this.host.steer=void 0;return}let t=[];this.host.steer=zt(e,t,"setSteer was given something that isn't a steerer (an object with gate and pick methods), so the engine is left unsteered");for(let{node:n,message:s}of t)this.reportSetup(n,s)}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 K(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=Ye(this.host,e);if(n===void 0)throw new Error(`unknown scene: ${e}`);if(t===void 0)return{sceneId:n};let s=Qe(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 Ye(this.host,e)??e}resolveBlockRef(e,t){if(t!=null)return e==null?t:Qe(this.host,e,t)}sceneAddress(e){let t=this.host.bundle.scenes[e];return t?R(t):void 0}blockAddress(e){let t=this.host.blockById.get(e);return t?R(t):void 0}tagsForBeat(e){return W(this.host,e)??[]}tagsForScene(e){let t=this.resolveSceneRef(e);return(t!=null?W(this.host,t):void 0)??[]}tagsForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t);return(s!=null?W(this.host,s):void 0)??[]}gameDataForScene(e){let t=this.resolveSceneRef(e),n=t!=null?this.host.bundle.scenes[t]:void 0;return N(n?.gameData)??{}}gameDataForBlock(e,t){let n=this.resolveBlockRef(this.resolveSceneRef(e),t),s=n!=null?this.host.blockById.get(n):void 0;return N(s?.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)Ut(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 Ut(i.children,o),[...o]}getOutline(){return Object.values(this.host.bundle.scenes).map(e=>({id:e.id,...R(e)?{gameId:R(e)}:{},name:e.name,...Wt(e.gameData),...V(e.extensions),...this.tagsField(e.id),blocks:e.blocks.map(t=>({id:t.id,...R(t)?{gameId:R(t)}:{},name:t.name,...Wt(t.gameData),...V(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)G(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=W(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[De(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[Fe(e.qualifier)]??this.host.qualifierDisplay.get(e.qualifier);i!==void 0&&(n.qualifierName=i)}let s=Re(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??U,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=N(e.gameData)),e.extensions&&Object.keys(e.extensions).length&&(n.extensions=e.extensions),t&&t.length&&(n.tags=t),n}tagsField(e){let t=W(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 me(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:pe,...t.snapshot(),...xr(e,this.host.registry.save())}}restoreFlow(e,t){this.refuseInCheckpoint("restoreFlow");let n=t.version;if(n!==3&&n!==pe)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=O.flow(e);this.host.registry.discardParked(i),this.host.registry.load(hr(e,t),{keepParked:!0,refit:!0});let o=new K(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(O.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(O.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(this.creationOptions.hostScopes??{}))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);en(this.host,n,s,t,null);let 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 J(this.ladderOf(e),t)}compareStages(e,t,n){return z(this.ladderOf(e),t,n)}nextStage(e,t){return Y(this.ladderOf(e),t)}ladderOf(e){let{scope:t,name:n}=this.splitShared(e),s=fr(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:Q(e),writable:e.writable??!0}))}splitShared(e){let t=nn(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}saveGame(){let e={};for(let[t,n]of this.flowsById)e[t]=n.snapshot();return{version:pe,...this.host.ownsRegistry?{registry:this.host.registry.save()}:{},sharedVisits:Object.fromEntries(this.host.sharedVisits),sharedSelectors:Xt(this.host.sharedSelectors),flows:e}}loadGame(e){this.refuseInCheckpoint("loadGame");let t=e.version;if(t!==3&&t!==pe)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(O.stage(o),{keep:!0});this.host.stageBags.clear();let i=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 Zt(e.sharedSelectors))this.host.sharedSelectors.set(o,a);for(let[o,a]of Object.entries(e.flows)){let l=new K(o,this.host,this.defaultSeed);l.restore(a),this.flowsById.set(o,l)}this.host.reportRefits()}},K=class{id;host;local;registered=new Set;rngState;started=!1;flowEnded=!1;dryChoice=null;ranDry=null;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=ie(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 xe(this.host,"patter",()=>[...this.host.patterSharedDecls,...this.host.patterLocalDecls]).get(n);if(e==="scene"){let s=this.currentSceneId;return s==null?void 0:xe(this.host,`scene/${s}`,()=>this.host.bundle.scenes[s]?.sceneProps).get(n)}return this.registryQualities?.(e,t)??xe(this.host,`host/${e}`,()=>this.host.bundle.scopeRegistry?.scopes.find(s=>s.token===e)?.declarations).get(n)}begin(e,t){let n=this.host.bundle.start;if(e===void 0&&t===void 0&&n&&this.host.bundle.scenes[n.scene]&&(e=n.scene,n.block!==void 0&&this.host.blockIndex.get(n.block)?.sceneId===n.scene&&(t=n.block)),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(O.flow(this.id)),this.mountLocal(),this.selectors.clear(),this.visitCounts.clear(),this.stack=[],this.currentSceneId=null,this.flowEnded=!1,this.dryChoice=null,this.ranDry=null,this.activeSnippet=null,this.beatIndex=0,this.clearPending(),this.started=!0,t){let s=this.host.blockIndex.get(t);if(!s)throw new Error(`unknown block: ${t}`);this.enterSceneSetup(s.sceneId),this.stack=[{sceneId:s.sceneId,containerId:t,index:0}],this.enter(t)}else{let s=e??Object.keys(this.host.bundle.scenes)[0],i=s?this.host.bundle.scenes[s]:void 0;if(!i)throw new Error(s?`unknown scene: ${s}`:"no scenes in bundle");this.enterSceneSetup(s);let o=i.blocks[0];o&&(this.stack=[{sceneId:s,containerId:o.id,index:0}],this.enter(o.id))}this.settle()}reset(e,t){this.begin(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=[],this.dryChoice=null,this.ranDry=null,!0;let n=Ye(this.host,e);if(n===void 0)return!1;let s;return t!==void 0&&(s=Qe(this.host,n,t),s===void 0)?!1:this.started?(this.clearPending(),this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!1,this.dryChoice=null,this.ranDry=null,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,dryChoice:i,ranDry:o,currentSceneId:a,activeSnippet:l,beatIndex:c,pendingChoice:f,pendingPrompt:u,pendingPromptOwnerId:h}=this,x=this.stack.map(p=>({...p}));e.undo.push(()=>{Object.assign(this,{rngState:t,started:n,flowEnded:s,dryChoice:i,ranDry:o,currentSceneId:a,activeSnippet:l,beatIndex:c,pendingChoice:f,pendingPrompt:u,pendingPromptOwnerId:h,stack:x})})}get isClosed(){return this.closed}get currentScene(){return this.currentSceneId}advance(){if(this.closed)return{type:"end",reason:"ended"};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&&!this.activeSnippet&&!this.pendingChoice&&(this.flowEnded=!0),this.flowEnded?this.endResult():(this.dryChoice=null,this.pendingChoice?{type:"choice",groupId:this.pendingChoice.groupId,options:this.offer(this.pendingChoice)}:this.beatResult(this.activeSnippet.beats[this.beatIndex++]))}endResult(){if(this.dryChoice!==null){let e=this.dryChoice;this.dryChoice=null,this.ranDry=e,this.report({flow:this.id,kind:"dry-choice",node:e,message:`choice '${e}' ran dry (no option left to take, and no fallback) with nothing after it, so the flow ended there`})}return{type:"end",reason:this.ranDry!==null?"ran-dry":"ended"}}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],"run");)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=lr(this.host.bundle).get(e);return t?this.beatResult(t):void 0}getChoices(){return this.pendingChoice?this.offer(this.pendingChoice):[]}offer(e){return e.options.map(t=>{let n=e.byId.get(t.id),s=this.promptFor(n);return e.shown.set(t.id,s),{id:t.id,prompt:s,eligible:t.eligible,gameData:N(t.gameData),...V(n.extensions)}})}choose(e){let t=this.pendingChoice;if(!t)throw new Error("no choice is pending");let n=t.options.find(a=>a.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,o=i?t.shown.has(e)?t.shown.get(e):this.promptFor(s):void 0;this.pendingPrompt=i&&o?{beat:i,shown:{...o}}: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 J(this.ladderOf(e),t)}compareStages(e,t,n){return z(this.ladderOf(e),t,n)}nextStage(e,t){return Y(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);if(n){if(s==="scene"&&this.currentSceneId===null)throw new Error(`'${e}': the flow has not entered a scene yet`);en(this.host,s,i,t,this.currentSceneId)}let 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(){let e=ar(this.host.bundle),t=this.activeSnippet?.beats?.[this.beatIndex]?.id;return{rngState:this.rngState,visits:Object.fromEntries(this.visitCounts),cursor:{flowEnded:this.flowEnded,...this.ranDry!==null?{ranDry:this.ranDry}:{},currentSceneId:this.currentSceneId,stack:this.stack.map(n=>{let s=this.childrenOf(n.containerId)?.[n.index],i=e.get(n.containerId);return{...n,...s?{nextId:s.id}:{},...i!==void 0?{choiceId:i}:{}}}),activeSnippetId:this.activeSnippet?.id??null,...t!==void 0?{beatId:t}:{},pendingChoice:this.pendingChoice?{groupId:this.pendingChoice.groupId,options:this.pendingChoice.options.map(n=>({id:n.id,eligible:n.eligible,...n.gameData!==void 0?{gameData:N(n.gameData)}:{}}))}:null,pendingPromptOwnerId:this.pendingPromptOwnerId,...this.pendingPrompt?.shown?{pendingPrompt:dr(this.pendingPrompt.shown)}:{},selectors:Xt(this.selectors)}}}restore(e){if(this.host.journal)throw new Error("a flow can't be restored while a checkpoint is open");let t=this.restoreCursor(e);this.releaseBags(!0),this.mountLocal();for(let n of new Set([this.currentSceneId,...this.stack.map(s=>s.sceneId)]))n!==null&&this.host.bundle.scenes[n]&&this.ensureSceneBags(n);t&&(this.report({flow:this.id,kind:"save",node:t.node,message:`the save's place has gone from this build: ${t.instead}`}),t.reoffer&&this.setupChoice(t.reoffer))}restoreCursor(e){this.rngState=ie(e.rngState),this.visitCounts=new Map(Object.entries(e.visits??{}));let t=e.cursor;this.started=!0,this.flowEnded=t.flowEnded,this.dryChoice=null,this.ranDry=t.flowEnded&&typeof t.ranDry=="string"?t.ranDry:null,this.currentSceneId=t.currentSceneId;let n=null;this.stack=[];for(let s of t.stack){let{nextId:i,choiceId:o,...a}=s,l=this.childrenOf(a.containerId),c=!l&&o!==void 0?this.host.nodeIndex.get(o):void 0;if(c?.type==="group"&&c.selector==="choice"){n={node:t.activeSnippetId??t.pendingChoice?.groupId??a.containerId,instead:`option ${a.containerId} has gone, so choice ${c.id} is offered again`,reoffer:c};break}let f=i!==void 0?l?.findIndex(u=>u.id===i)??-1:-1;this.stack.push(f>=0?{...a,index:f}:{...a})}if(this.activeSnippet=null,this.beatIndex=0,!n?.reoffer&&t.activeSnippetId!==null){let s=this.host.nodeIndex.get(t.activeSnippetId);if(s&&s.type==="snippet"){let i=s.beats??[];if(this.activeSnippet=s,t.beatId!==void 0){let o=i.findIndex(a=>a.id===t.beatId);this.beatIndex=o>=0?o:i.length,o<0&&(n={node:t.activeSnippetId,instead:`beat ${t.beatId} has gone from snippet ${t.activeSnippetId}, so the snippet ends there`})}else this.beatIndex=t.beatIndex??i.length}else n={node:t.activeSnippetId,instead:`snippet ${t.activeSnippetId} has gone, so play carries on after it`}}if(this.selectors=Zt(t.selectors),this.pendingChoice=null,!n?.reoffer&&t.pendingChoice!==null){let s=new Map,i=[];for(let o of t.pendingChoice.options){let a=this.host.nodeIndex.get(o.id);a&&(s.set(o.id,a),i.push({id:o.id,eligible:o.eligible,...o.gameData!==void 0?{gameData:o.gameData}:{}}))}if(i.length>0)this.pendingChoice={groupId:t.pendingChoice.groupId,options:i,byId:s,shown:new Map};else{let o=this.host.nodeIndex.get(t.pendingChoice.groupId);n=o?.type==="group"&&o.selector==="choice"?{node:t.pendingChoice.groupId,instead:`none of choice ${o.id}'s options is left, so it's offered again`,reoffer:o}:{node:t.pendingChoice.groupId,instead:`choice ${t.pendingChoice.groupId} has gone, so play carries on after it`}}}if(this.pendingPrompt=null,this.pendingPromptOwnerId=n?.reoffer?null:t.pendingPromptOwnerId??null,this.pendingPromptOwnerId){let s=this.host.nodeIndex.get(this.pendingPromptOwnerId),i=s?this.authoredPromptOf(s):void 0,o=t.pendingPrompt,a=o?.kind==="line"&&o.speakerLabel===void 0?Re(this.host,o.character,o.qualifier):void 0;i?this.pendingPrompt={beat:i,...o?{shown:{...o,padAfter:o.padAfter??this.padOf(i.id),...a!==void 0?{speakerLabel:a}:{}}}:{}}:this.pendingPromptOwnerId=null}return n}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,"option"),l=o.secretUntilEligible===!0;!a&&l||(t.push({id:o.id,eligible:a,...o.gameData!==void 0?{gameData:o.gameData}:{}}),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,shown:new Map};return}let i=s.find(o=>this.eligible(o,"fallback"));if(i){this.enterChild(i);return}this.host.tracing&&this.emit({type:"dry",group:e.id}),this.host.onDryChoice?.(e.id),this.dryChoice=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.holds(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),a=null;if(n.length>0){let l=this.selectorState(e);switch(e.selector){case"branch":a=n[0];break;case"sequence":a=s==="shuffle"?this.pickShuffle(n,i,l):s==="specificity"?this.pickSpecificity(n,i,l):this.pickSequential(n,i,l);break;default:return null}}return this.host.steer?.pick&&(e.selector==="branch"||e.selector==="sequence")&&(a=this.steerPick(e,e.selector,t,a)),o(a)}steerPick(e,t,n,s){let i=s?.id??"",o=this.host.steer.pick({flow:this.id,group:e.id,selector:t,children:n.map(l=>({...l})),default:i});if(typeof o!="string")throw new Error(`steer: pick for ${e.id} answered ${String(o)}, not a child id or ""`);if(o===i)return s;let a=o===""?null:e.children.find(l=>l.id===o);if(a===void 0)throw new Error(`steer: pick for ${e.id} answered "${o}", which isn't one of its children`);return this.host.tracing&&this.emit({type:"steered",node:e.id,kind:"pick",default:i,answer:o}),a}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(h=>h.id),a=new Set(e.map(h=>h.id));if(n.bag===void 0&&(n.bag=o()),!n.bag.some(h=>a.has(h))){if(t==="once")return null;if(i){let h=e[s-1];return n.last=h.id,h}if(n.bag=o(),n.bag.length===0)return null}let l=n.bag.filter(h=>a.has(h)),c=n.last!==void 0&&l.length>1?l.indexOf(n.last):-1,f=Math.floor(this.rng()*(c>=0?l.length-1:l.length));c>=0&&f>=c&&f++;let u=l[f];return n.bag.splice(n.bag.indexOf(u),1),n.last=u,e.find(h=>h.id===u)}pickSpecificity(e,t,n){let s=e;if(t!=="repeat"){n.bag===void 0&&(n.bag=e.map(f=>f.id));let c=new Set(n.bag);if(s=e.filter(f=>c.has(f.id)),s.length===0)return t==="stick"&&n.last!==void 0?e.find(f=>f.id===n.last)??null:null}let i=-1,a=s.map(c=>{let f=this.specScore(c);return f>i&&(i=f),{c,s:f}}).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(u=>u.id===n.last):-1,f=Math.floor(this.rng()*(c>=0?a.length-1:a.length));c>=0&&f>=c&&f++,l=a[f]}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 dt(e,i=>{try{return Qt(Se(i,this.context(),qe))}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)}}}holds(e){if(!e.condition)return!0;try{return Qt(this.evalExpr(e.condition))}catch(t){return this.reportError("condition",e.id,e.condition,t),!1}}eligible(e,t){let n=this.holds(e),s=this.host.steer?.gate;if(!s||!e.condition)return n;let i=s({flow:this.id,node:e.id,where:t,source:e.condition.src??"",default:n});if(typeof i!="boolean")throw new Error(`steer: gate for ${e.id} answered ${String(i)}, not true or false`);return i!==n&&this.host.tracing&&this.emit({type:"steered",node:e.id,kind:"gate",default:n,answer:i}),i}reportError(e,t,n,s){let i=s instanceof Error?s.message:String(s),o=n?.src;this.report({flow:this.id,kind:e,node:t,...o?{source:o}:{},message:i})}report(e){this.host.onError(e),this.host.tracing&&this.emit({type:"diagnostic",kind:e.kind,node:e.node,...e.source?{source:e.source}:{},message:e.message})}evalExpr(e){return Se(this.conditionAst(e),this.context(),qe)}conditionAst(e){let t=Mt.get(e);return t||(t=H(e.ast),Mt.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=je(this.rngState),t=e.next();return this.rngState=e.state(),t};beatResult(e){let t=W(this.host,e.id),n=t&&t.length?{tags:t}:{};switch(e.kind){case"gameEvent":return{type:"gameEvent",id:e.id,gameData:N(e.gameData),...V(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}:{},...this.spokenOf(e),gameData:N(e.gameData),...V(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:Re(this.host,e.character,e.qualifier),padAfter:this.padOf(e.id),...this.spokenOf(e),gameData:N(e.gameData),...V(e.extensions),...n}}}}interpolate(e){return St(e,t=>this.getProperty(t))}stripCaptions(e){return bt(e,this.host.captionOpen,this.host.captionClose)}captionLine(e){return this.host.captionsOn?e:this.stripCaptions(e)}spokenOf(e){let t=this.host.bundle.estimateSyllablesPerSecond??de,n=this.host.emitIds?void 0:this.host.defaultStrings[e.id];if(n===void 0)return{estimateRate:t};let s;return e.kind==="text"?s=this.interpolate(n):e.character===this.host.captionCharacter?s="":s=this.stripCaptions(this.host.bundle.voiced?n:this.interpolate(n)),{spokenText:s,spokenLocale:this.host.bundle.locales.default,estimateRate:t}}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:Re(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=W(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),...this.spokenOf(e),gameData:N(e.gameData),...V(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),...this.spokenOf(e),gameData:N(e.gameData),...V(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 G(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=De(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.castDisplay.get(e)}padOf(e){return this.host.padIndex.get(e)?.resolved??U}resolveQualifierName(e){if(e===void 0||this.host.emitIds)return;let t=Fe(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.qualifierDisplay.get(e)}splitRef(e){return nn(this.host,e)}newLocal(){return new _(this.host.patterLocalDecls,{pathPrefix:"@patter."})}mountLocal(){this.local=this.newLocal();let e=O.flowGlobals(this.id);this.host.registry.mountOwned(e,this.local,{owner:he}),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=O.flowScene(this.id,e),l=Kt(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=Kt(this.host.registry,O.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(O.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,Q(n))}}};function Ut(r,e){G(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 Re(r,e,t,n=!1){if(!e||r.emitIds)return;let s=l=>(n?void 0:r.strings[l])??r.defaultStrings[l],i=s(De(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(Bt(e,t))??o;let a=s(Fe(t))??r.qualifierDisplay.get(t)??t;return Nt(s(Lt)??r.speakerPattern,i,a)}function Wt(r){return r&&Object.keys(r).length?{gameData:N(r)}:{}}function V(r){return r&&Object.keys(r).length?{extensions:r}:{}}function dr(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 Xt(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 Zt(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 Kt(r,e,t,n){let s=n?JSON.stringify(t.save()):"";return r.mountOwned(e,t,{owner:he}),n&&JSON.stringify(t.save())!==s}function Jt(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default}}var pr=new Set(["rng","seed","locale","hostScopes","registry","replayPromptOnChoose","closedCaptions","onDryChoice","steer","onError","onRefit","log"]);function zt(r,e,t=`the engine option "steer" isn't a steerer (an object with gate and pick methods), so it's ignored`){if(r==null)return;let n=r;if(typeof r=="object"&&(n.gate===void 0||typeof n.gate=="function")&&(n.pick===void 0||typeof n.pick=="function"))return r;e.push({node:"steer",message:t})}function ze(r,e){let t=r.locales.default;if(e===void 0)return{locale:t,table:t};if(r.localisation?.mode==="ids")return{locale:e,table:e};let n=[...new Set([t,...r.locales.included,...Object.keys(r.strings)])];if(n.includes(e))return{locale:e,table:e};let s=l=>l.toLowerCase().replace(/_/g,"-"),i=n.find(l=>s(l)===s(e));if(i!==void 0)return{locale:i,table:i,problem:`the locale "${e}" is spelled "${i}" in this bundle, so it's using "${i}"`};let o=s(e).split("-")[0],a=n.find(l=>s(l)===o);return a!==void 0?{locale:a,table:a,problem:`this bundle has no locale "${e}", so it's using its language, "${a}"`}:{locale:t,problem:`this bundle has no locale "${e}", so it's using the default, "${t}", with every string marked untranslated`}}function Yt(r,e){return e.table!==void 0?r[e.table]??{}:{}}function en(r,e,t,n,s){let i=l=>l?.find(c=>c.name.toLowerCase()===t),o;if(e==="patter")o=i(r.bundle.properties);else if(e==="scene")o=i(s!==null?r.bundle.scenes[s]?.sceneProps:void 0);else{let l=r.bundle.scopeRegistry?.scopes.find(c=>c.token===e);if(!l||l.declarations===void 0)return;o=i(l.declarations)}let a=`@${e}.${t}`;if(o===void 0)throw new Error(`no property at "${a}": the content declares no ${a}`);if(!oe(o,n,{noneChosen:o.type==="enum"&&o.default===""}))throw new Error(`"${a}" takes ${ur(o)}; ${JSON.stringify(n)} doesn't fit`)}function ur(r){let e=t=>(t??[]).map(n=>JSON.stringify(n)).join(", ");switch(r.type){case"number":return"a number";case"boolean":return"true or false";case"enum":return`one of ${e(r.values)}`;case"flags":return r.values!==void 0&&r.values.length>0?`a list of flags from ${e(r.values)}`:"a list of flags";case"quality":return`one of its stages ${e(r.stages)}`;default:return"text"}}function xe(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 fr(r,e,t){let n=t.toLowerCase();return e==="patter"?xe(r,"patter",()=>[...r.patterSharedDecls,...r.patterLocalDecls]).get(n):r.registry.toEvalContext().qualities?.(e,t)??xe(r,`host/${e}`,()=>r.bundle.scopeRegistry?.scopes.find(s=>s.token===e)?.declarations).get(n)}function tn(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default,writable:r.writable}}function gr(r,e){let t=tn(r),n=r.writable??e;return n===void 0?t:{...t,writable:n}}function Ye(r,e){return Ae(r.bundle.scenes,e,r.sceneGameIdToId)}function Qe(r,e,t){return r.blockGameIdToId.get(e)?.get(t)??(r.blockIndex.get(t)?.sceneId===e?t:void 0)}function nn(r,e){r.refSplitRevision!==r.registry.revision&&(r.refSplitCache.clear(),r.refSplitRevision=r.registry.revision);let t=r.refSplitCache.get(e);return t||(t=yt(e,n=>n==="scene"||r.registry.has(n)||(r.bundle.externalScopes?.includes(n)??!1)),r.refSplitCache.set(e,t)),t}function hr(r,e){let t={};e.scopes?.patter&&(t[O.flowGlobals(r)]=e.scopes.patter);for(let[n,s]of Object.entries(e.sceneBags??{}))t[O.flowScene(r,n)]=s;return t}function xr(r,e){let t={scopes:{},sceneBags:{}},n=O.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[cr(o.slice(6))]=i)}return t}function Qt(r){return typeof r=="boolean"?r:typeof r=="number"?r!==0:typeof r=="string"?r!=="":r.length>0}var mr=(r,e)=>r.shared??e;function Xe(r,e){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.default!==void 0?{default:r.default}:{},shared:mr(r,e)}}function yr(r){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.values?{values:[...r.values]}:{},...r.purpose?{purpose:r.purpose}:{}}}function br(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 Le(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=R(o);t.push({gameId:a,name:o.name,blocks:o.blocks.map(l=>({gameId:R(l),name:l.name}))});for(let l of o.blocks)br(l,e);o.sceneProps?.length&&n.push({gameId:a,properties:o.sceneProps.map(l=>Xe(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=>Xe(a,!0))})),i=Object.entries(r.gameDataFields??{}).filter(([,o])=>(o?.length??0)>0).map(([o,a])=>({kind:o,fields:(a??[]).map(yr)}));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=>Xe(o,!0)),scene:n},gameData:i,counts:e}}var ye=(r,e)=>Object.prototype.hasOwnProperty.call(r,e);function rn(r,e){return r.gameDataFields?.[e]??[]}function Ze(r,e,t){return e&&ye(e,t)?e[t]:r.find(n=>n.name===t)?.default}function sn(r,e){let t={};for(let n of r){let s=Ze(r,e,n.name);s!==void 0&&(t[n.name]=s)}for(let[n,s]of Object.entries(e??{}))ye(t,n)||(t[n]=s);return t}function on(r,e,t){let n=r.extensions!==void 0&&ye(r.extensions,e)?r.extensions[e]:void 0;return n!==void 0&&ye(n.fields,t)?n.fields[t]??[]:[]}function an(r,e,t=""){let n=o=>({...o?.extensions??{}}),s=Object.values(r.scenes??{}),i=o=>(ye(r.scenes??{},o)?r.scenes[o]:void 0)??s.find(a=>R(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=>R(c)===l))}case"snippet":case"option":case"line":case"text":case"gameEvent":{let o,a=(l,c)=>{for(let f of l??[]){if(o!==void 0)return;if(f.type==="group"){if(c&&f.id===t&&e==="option"){o=f;return}if(c&&f.prompt?.id===t&&f.prompt.kind===e){o=f.prompt;return}a(f.children??[],f.selector==="choice");continue}if(f.id===t&&e==="snippet"){o=f;return}let u=(f.beats??[]).find(h=>h.id===t);if(u!==void 0){u.kind===e&&(o=u);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 et(r){return{schema:Z,save:r.saveGame()}}function tt(r,e){if(!e||e.schema!==Z||!e.save)throw new Error(`loadState: not a ${Z} envelope`);r.loadGame(e.save)}function Oe(r){return JSON.stringify(et(r))}function Ne(r,e){tt(r,JSON.parse(e))}function ln(r,e){return r.getProperty(e)}function cn(r,e,t){r.setProperty(e,t)}function dn(r,e){for(let[t,n]of Object.entries(e))r.setProperty(t,n)}function rt(r){let e={};for(let t of pn(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,un(r)),e}function pn(r){return[...r.listBags(),...r.flows().flatMap(e=>e.listBags())]}function Sr(r){switch(r.type){case"line":return`line ${r.character??"?"}: ${JSON.stringify(r.text)}${nt(r.gameData)}`;case"text":return`text: ${JSON.stringify(r.text)}${nt(r.gameData)}`;case"gameEvent":return`game event ${r.id}${nt(r.gameData)}`;case"choice":return`choice (${r.options.length} option${r.options.length===1?"":"s"})`;case"end":return"end"}}var nt=r=>r?` gameData=${JSON.stringify(r)}`:"";function un(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 fn(r,e={}){let t=e.label?`[${e.label}] `:"",n=Ve({mounts:()=>pn(r),extra:()=>un(r)},{sink:e.sink,label:t});return{snapshot:()=>rt(r),capture:()=>n.capture(),dispose:()=>n.dispose(),logStep(s){(e.sink??(i=>console.log(i)))(`${t}${Sr(s)}`)}}}function gn(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 u of s)try{i.send(u)}catch{}s=[]}},c=u=>{o||!i||i.readyState>1||(s.push(JSON.stringify(u)),l())};if(!t)return{flowOpened(){},observe(){},flowClosed(){},setBuild(){},close(){o=!0},state:"closed",build:a,url:e};let f=()=>{let u=JSON.stringify({t:"hello",v:1,build:a,project:r.project,flows:[...n]});try{i?.send(u)}catch{}};try{i=new t(e),i.addEventListener("open",()=>{f(),l()}),i.addEventListener("message",u=>{if(!(!r.onBundle||typeof u.data!="string"))try{let h=JSON.parse(u.data);h.t==="bundle"&&typeof h.build=="string"&&typeof h.data=="string"&&r.onBundle({build:h.build,data:h.data})}catch{}}),i.addEventListener("error",()=>{}),i.addEventListener("close",()=>{i=null,s=[]})}catch{i=null}return{flowOpened(u){n.add(u),c({t:"flowOpen",flow:u})},flowClosed(u){n.delete(u),c({t:"flowClose",flow:u})},observe(u,h,x,p,d){n.has(u)||(n.add(u),c({t:"flowOpen",flow:u})),c({t:"frame",flow:u,sceneId:h,beatId:x,type:p,choiceId:d})},setBuild(u){o||u===a||(a=u,i&&i.readyState===1&&f())},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 hn(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 vr(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 ot=!1,xn=!1,bn,Er=350,st=6,mn=7,te=null,ne=0,Pe=null,wr=null;function Sn(){if(te)return te;let r=document.createElement("div");return r.className="tooltip",r.setAttribute("role","tooltip"),r.hidden=!0,document.body.appendChild(r),te=r,r}var kr=r=>r instanceof HTMLElement?r.getBoundingClientRect():r;function Cr(r){let e=Sn(),t=kr(r),n=e.getBoundingClientRect(),s=t.top-n.height-mn;s<st&&(s=t.top+t.height+mn);let i=t.left+t.width/2-n.width/2;i=Math.max(st,Math.min(i,window.innerWidth-n.width-st)),e.style.left=`${Math.round(i)}px`,e.style.top=`${Math.round(s)}px`}function Ar(r){let e=r.dataset.tip;e&&Dr(r,e)}function Dr(r,e){if(bn?.())return;let t=Sn(),n=(r instanceof HTMLElement?r.closest("dialog[open]"):null)??document.body;t.parentElement!==n&&n.appendChild(t),Pe=r instanceof HTMLElement?r:null,vr(t,e),t.hidden=!1,t.classList.remove("show"),t.offsetWidth,Cr(r),t.classList.add("show")}function ee(){ne&&(window.clearTimeout(ne),ne=0),Pe=null,wr=null,te&&(te.hidden=!0,te.classList.remove("show"))}function yn(r){r!==Pe&&(ne&&window.clearTimeout(ne),ne=window.setTimeout(()=>Ar(r),Er))}function Fr(){Rr()}function Ir(){xn||(xn=!0,setTimeout(()=>{ot||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 it=r=>r instanceof Element?r.closest("[data-tip]"):null;function Rr(r={}){r.suppressed!==void 0&&(bn=r.suppressed),!ot&&(ot=!0,document.addEventListener("pointerover",e=>{let t=it(e.target);t&&yn(t)}),document.addEventListener("pointerout",e=>{let t=it(e.target);if(!t)return;let n=e.relatedTarget;n instanceof Node&&t.contains(n)||ee()}),document.addEventListener("focusin",e=>{let t=it(e.target);t&&yn(t)}),document.addEventListener("focusout",()=>ee()),document.addEventListener("pointerdown",()=>ee(),!0),document.addEventListener("scroll",()=>{Pe&&ee()},!0),document.addEventListener("keydown",e=>{e.key==="Escape"&&ee()}),window.addEventListener("blur",()=>ee()))}function vn(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),Fr()),s.onClick&&n.addEventListener("click",s.onClick);for(let i of t)i!=null&&n.append(i);return Ir(),n}function En(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 wn=r=>`default (${En(r)})`;function at(r){let e=r.doc===void 0?vn:(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:wn(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,f=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(f)}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 kn="pp-inspector-style",Br=`
|
|
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 Lr(r){if(r.getElementById(kn))return;let e=r.createElement("style");e.id=kn,e.textContent=Br,(r.head??r.documentElement).appendChild(e)}function Or(r,e){return Array.isArray(r)&&Array.isArray(e)?r.length===e.length&&r.every((t,n)=>t===e[n]):r===e}function Cn(r,e={}){let t=e.container?.ownerDocument??document;Lr(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 d=new Blob([Oe(r)],{type:"application/json"}),w=t.createElement("a");w.href=URL.createObjectURL(d),w.download="save.patterstate",w.click(),URL.revokeObjectURL(w.href)});let l=t.createElement("button");l.type="button",l.textContent="Load state\u2026",l.addEventListener("click",()=>{let d=t.createElement("input");d.type="file",d.accept=".patterstate,application/json",d.addEventListener("change",()=>{let w=d.files?.[0];w&&w.text().then(g=>{try{Ne(r,g),h()}catch(b){console.error("Load state failed:",b instanceof Error?b.message:b)}})}),d.click()}),o.append(a,l),n.append(s,o,i);let c=[],f=d=>{let w=t.createElement("div");w.className="pp-insp-row";let g=t.createElement("span");g.className="pp-insp-ref",g.textContent=d.path,g.title=d.path;let b=t.createElement("div");b.className="pp-insp-ctl";let v=t.createElement("button");v.className="pp-insp-reset",v.type="button",v.textContent="\u21BA",v.title="Reset to default",w.append(g,b,v),i.appendChild(w);let k,I=S=>{r.setProperty(d.path,S),M()},$=S=>t.activeElement===S;function M(){v.disabled=Or(r.getProperty(d.path),d.default)}if(v.addEventListener("click",()=>{r.setProperty(d.path,d.default),k(),M()}),d.type==="boolean"){let S=t.createElement("input");S.type="checkbox",S.addEventListener("change",()=>I(S.checked)),b.appendChild(S),k=()=>{$(S)||(S.checked=r.getProperty(d.path)===!0)}}else if(d.type==="number"){let S=t.createElement("input");S.type="number",S.addEventListener("change",()=>I(Number(S.value))),b.appendChild(S),k=()=>{$(S)||(S.value=String(r.getProperty(d.path)??""))}}else if(d.type==="quality"){let S=()=>{let B=r.getProperty(d.path);b.replaceChildren(at({stages:d.stages??[],value:typeof B=="string"?B:void 0,decl:d,onPick:m=>{I(m),S()},doc:t}))};k=S}else if(d.type==="enum"){let S=t.createElement("select");for(let B of d.values??[]){let m=t.createElement("option");m.value=B,m.textContent=B,S.appendChild(m)}S.addEventListener("change",()=>I(S.value)),b.appendChild(S),k=()=>{$(S)||(S.value=String(r.getProperty(d.path)??""))}}else if(d.type==="flags"){let S=t.createElement("input");S.type="text",S.placeholder="comma, separated, flags",S.addEventListener("change",()=>I(S.value.split(",").map(B=>B.trim()).filter(B=>B.length>0))),b.appendChild(S),k=()=>{if(!$(S)){let B=r.getProperty(d.path);S.value=Array.isArray(B)?B.join(", "):""}}}else{let S=t.createElement("input");S.type="text",S.addEventListener("change",()=>I(S.value)),b.appendChild(S),k=()=>{$(S)||(S.value=String(r.getProperty(d.path)??""))}}k(),M(),c.push(()=>{k(),M()})},u=r.listProperties();if(u.length===0){let d=t.createElement("div");d.className="pp-insp-empty",d.textContent="No @patter properties.",i.appendChild(d)}else for(let d of u)f(d);let h=()=>{for(let d of c)d()};e.container?.appendChild(n);let x=e.pollMs??250,p;return x>0&&(p=setInterval(h,x)),{el:n,refresh:h,destroy(){p!==void 0&&clearInterval(p),n.remove()}}}var An="pp-bundle-style",Nr=`
|
|
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 Pr(r){if(r.getElementById(An))return;let e=r.createElement("style");e.id=An,e.textContent=Nr,(r.head??r.documentElement).appendChild(e)}var D=(r,e,t,n)=>{let s=r.createElement(e);return t&&(s.className=t),n!==void 0&&(s.textContent=n),s};function P(r,e,t,n="pp-bundle-val"){let s=D(r,"div","pp-bundle-row");return s.append(D(r,"span","pp-bundle-key",e),D(r,"span",n,t)),s}function lt(r,e){let t=D(r,"div","pp-bundle-row");t.append(D(r,"span","pp-bundle-key pp-bundle-addr",e.name));let n=D(r,"span","pp-bundle-val",e.type);return e.hasDefault||n.append(D(r,"span","pp-bundle-tag","no default")),t.append(n),t}function re(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(D(r,"span","pp-bundle-count",` ${n}`)),i.append(o),i}function Dn(r,e={}){let t=e.container?.ownerDocument??document;Pr(t);let n=Le(r),s=new Set(e.open??["identity","addresses"]),i=D(t,"div","pp-bundle");i.append(D(t,"h4",void 0,e.title??"Bundle"));let o=re(t,"identity",n.identity.project||"(unnamed project)",null,s.has("identity"));n.identity.version&&o.append(P(t,"version",n.identity.version)),o.append(P(t,"schema",n.identity.schema)),o.append(P(t,"locales",`${n.identity.defaultLocale}${n.identity.locales.length>1?` (+${n.identity.locales.length-1})`:""}`)),o.append(P(t,"strings",n.identity.localisation)),n.identity.voiced&&o.append(P(t,"voiced","yes")),n.identity.hash&&o.append(P(t,"hash",n.identity.hash)),n.identity.structureHash&&o.append(P(t,"structure",n.identity.structureHash)),n.identity.sourceDebug&&o.append(P(t,"build","SOURCE DEBUG - not shippable","pp-bundle-val pp-bundle-warn")),i.append(o);let a=re(t,"addresses","Addresses",n.addresses.length,s.has("addresses"));n.addresses.length||a.append(D(t,"div","pp-bundle-empty","no scenes"));for(let x of n.addresses){let p=D(t,"div","pp-bundle-row");p.append(D(t,"span","pp-bundle-key pp-bundle-addr",x.gameId),D(t,"span","pp-bundle-val",x.name)),a.append(p);for(let d of x.blocks){let w=D(t,"div","pp-bundle-row pp-bundle-sub");w.append(D(t,"span","pp-bundle-key pp-bundle-addr",d.gameId),D(t,"span","pp-bundle-val",d.name)),a.append(w)}}i.append(a);let l=n.hostScopes.reduce((x,p)=>x+p.properties.length,0),c=re(t,"hostScopes","Host properties",l,s.has("hostScopes"));n.hostScopes.length||c.append(D(t,"div","pp-bundle-empty","the game supplies nothing"));for(let x of n.hostScopes){let p=D(t,"div","pp-bundle-row");p.append(D(t,"span","pp-bundle-key pp-bundle-addr",`@${x.token}`));let d=D(t,"span","pp-bundle-val",x.opaque?"any name, unchecked":`${x.properties.length} declared`);x.writable||d.append(D(t,"span","pp-bundle-tag","read-only")),p.append(d),c.append(p);for(let w of x.properties){let g=lt(t,w);g.classList.add("pp-bundle-sub"),c.append(g)}}i.append(c);let f=n.properties.patter.length+n.properties.scene.reduce((x,p)=>x+p.properties.length,0),u=re(t,"properties","Story properties",f,s.has("properties"));f||u.append(D(t,"div","pp-bundle-empty","none declared"));for(let x of n.properties.patter)u.append(lt(t,x));for(let x of n.properties.scene){u.append(P(t,"@scene",x.gameId,"pp-bundle-val pp-bundle-addr"));for(let p of x.properties){let d=lt(t,p);d.classList.add("pp-bundle-sub"),u.append(d)}}if(i.append(u),n.gameData.length){let x=re(t,"gameData","Game data",n.gameData.reduce((p,d)=>p+d.fields.length,0),s.has("gameData"));for(let p of n.gameData){x.append(P(t,"on",p.kind));for(let d of p.fields){let w=D(t,"div","pp-bundle-row pp-bundle-sub");w.append(D(t,"span","pp-bundle-key pp-bundle-addr",d.name),D(t,"span","pp-bundle-val",d.type)),x.append(w)}}i.append(x)}let h=re(t,"counts","Counts",null,s.has("counts"));for(let[x,p]of Object.entries(n.counts))h.append(P(t,x,String(p)));return i.append(h),e.container?.append(i),{el:i,description:n,destroy(){i.remove()}}}var Te=class{constructor(e,t="main"){this.engine=e;this.flowId=t}engine;flowId;handlers={line:new Set,text:new Set,gameEvent:new Set,choice:new Set,ended:new Set};queued=0;delivering=!1;get flow(){return this.engine.getFlow(this.flowId)}on(e,t){let n=this.handlers[e];return n.add(t),()=>{n.delete(t)}}begin(e,t){let n=this.flow;if(!n||n.isClosed)this.engine.openFlow(this.flowId,{scene:e,block:t});else if(e===void 0){if(t!==void 0)throw new Error("Runner.begin: a block needs its scene");n.reset()}else if(!n.goto(e,t))throw new Error(`Runner.begin: address not found: ${e}${t===void 0?"":` / ${t}`}`);this.queued=0,this.next()}next(){if(!this.flow)throw new Error(`Runner.next: flow '${this.flowId}' isn't open; call begin() first`);if(this.queued++,!this.delivering){this.delivering=!0;try{for(;this.queued>0;)this.queued--,this.deliver(this.flow.advance())}finally{this.delivering=!1,this.queued=0}}}choose(e){let t=this.flow;if(!t)throw new Error(`Runner.choose: flow '${this.flowId}' isn't open; call begin() first`);t.choose(e),this.next()}stop(){this.queued=0}rebind(e){this.engine=e}deliver(e){switch(e.type){case"line":return this.emit("line",e);case"text":return this.emit("text",e);case"gameEvent":return this.emit("gameEvent",e);case"choice":return this.emit("choice",{groupId:e.groupId,options:e.options});case"end":return this.emit("ended",e.reason)}}emit(e,t){for(let n of[...this.handlers[e]])n(t)}};function Fn(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 Tn(Tr);})();
|
|
37
37
|
//# sourceMappingURL=patterplay.min.js.map
|