@doodle-engine/core 0.0.1
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/conditions/index.d.ts +37 -0
- package/dist/conditions/index.d.ts.map +1 -0
- package/dist/core.cjs +2 -0
- package/dist/core.js +1192 -0
- package/dist/effects/index.d.ts +39 -0
- package/dist/effects/index.d.ts.map +1 -0
- package/dist/engine/index.d.ts +145 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/localization/index.d.ts +42 -0
- package/dist/localization/index.d.ts.map +1 -0
- package/dist/parser/index.d.ts +39 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/snapshot/index.d.ts +23 -0
- package/dist/snapshot/index.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/conditions.d.ts +155 -0
- package/dist/types/conditions.d.ts.map +1 -0
- package/dist/types/effects.d.ts +256 -0
- package/dist/types/effects.d.ts.map +1 -0
- package/dist/types/entities.d.ts +196 -0
- package/dist/types/entities.d.ts.map +1 -0
- package/dist/types/registry.d.ts +45 -0
- package/dist/types/registry.d.ts.map +1 -0
- package/dist/types/save.d.ts +18 -0
- package/dist/types/save.d.ts.map +1 -0
- package/dist/types/snapshot.d.ts +181 -0
- package/dist/types/snapshot.d.ts.map +1 -0
- package/dist/types/state.d.ts +85 -0
- package/dist/types/state.d.ts.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Condition evaluation system for the Doodle Engine.
|
|
3
|
+
*
|
|
4
|
+
* Conditions are pure functions that test game state and return true or false.
|
|
5
|
+
* They are used throughout the engine to:
|
|
6
|
+
* - Filter dialogue choices that should be visible
|
|
7
|
+
* - Determine which dialogue nodes to show
|
|
8
|
+
* - Decide if triggered dialogues should start
|
|
9
|
+
*
|
|
10
|
+
* All evaluators are pure functions with no side effects.
|
|
11
|
+
*/
|
|
12
|
+
import type { Condition } from '../types/conditions';
|
|
13
|
+
import type { GameState } from '../types/state';
|
|
14
|
+
/**
|
|
15
|
+
* Evaluate a single condition against the current game state.
|
|
16
|
+
*
|
|
17
|
+
* @param condition - The condition to evaluate
|
|
18
|
+
* @param state - Current game state
|
|
19
|
+
* @returns true if the condition passes, false otherwise
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const condition: Condition = { type: 'hasFlag', flag: 'metBartender' }
|
|
24
|
+
* const passes = evaluateCondition(condition, state) // true if flag is set
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function evaluateCondition(condition: Condition, state: GameState): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Evaluate multiple conditions with AND logic.
|
|
30
|
+
* All conditions must pass for this to return true.
|
|
31
|
+
*
|
|
32
|
+
* @param conditions - Array of conditions to evaluate
|
|
33
|
+
* @param state - Current game state
|
|
34
|
+
* @returns true if all conditions pass, false otherwise
|
|
35
|
+
*/
|
|
36
|
+
export declare function evaluateConditions(conditions: Condition[], state: GameState): boolean;
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conditions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAiDjF;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAErF"}
|
package/dist/core.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var O=Object.defineProperty;var V=(e,t,n)=>t in e?O(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var T=(e,t,n)=>V(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function N(e,t){switch(e.type){case"hasFlag":return R(e.flag,t);case"notFlag":return P(e.flag,t);case"hasItem":return D(e.itemId,t);case"variableEquals":return q(e.variable,e.value,t);case"variableGreaterThan":return W(e.variable,e.value,t);case"variableLessThan":return F(e.variable,e.value,t);case"atLocation":return M(e.locationId,t);case"questAtStage":return G(e.questId,e.stageId,t);case"characterAt":return $(e.characterId,e.locationId,t);case"characterInParty":return H(e.characterId,t);case"relationshipAbove":return U(e.characterId,e.value,t);case"relationshipBelow":return j(e.characterId,e.value,t);case"timeIs":return J(e.startHour,e.endHour,t);case"itemAt":return Q(e.itemId,e.locationId,t);default:return!1}}function E(e,t){return e.every(n=>N(n,t))}function R(e,t){return t.flags[e]===!0}function P(e,t){return t.flags[e]!==!0}function D(e,t){return t.inventory.includes(e)}function q(e,t,n){return n.variables[e]===t}function W(e,t,n){const r=n.variables[e];return typeof r=="number"&&r>t}function F(e,t,n){const r=n.variables[e];return typeof r=="number"&&r<t}function M(e,t){return t.currentLocation===e}function G(e,t,n){return n.questProgress[e]===t}function $(e,t,n){const r=n.characterState[e];return(r==null?void 0:r.location)===t}function H(e,t){const n=t.characterState[e];return(n==null?void 0:n.inParty)===!0}function U(e,t,n){const r=n.characterState[e];return r!==void 0&&r.relationship>t}function j(e,t,n){const r=n.characterState[e];return r!==void 0&&r.relationship<t}function J(e,t,n){const r=n.currentTime.hour;return e<t?r>=e&&r<t:r>=e||r<t}function Q(e,t,n){return n.itemLocations[e]===t}function C(e,t){switch(e.type){case"setFlag":return B(e.flag,t);case"clearFlag":return _(e.flag,t);case"setVariable":return z(e.variable,e.value,t);case"addVariable":return Y(e.variable,e.value,t);case"addItem":return K(e.itemId,t);case"removeItem":return X(e.itemId,t);case"moveItem":return Z(e.itemId,e.locationId,t);case"goToLocation":return tt(e.locationId,t);case"advanceTime":return et(e.hours,t);case"setQuestStage":return nt(e.questId,e.stageId,t);case"addJournalEntry":return rt(e.entryId,t);case"startDialogue":return at(e.dialogueId,t);case"endDialogue":return it(t);case"setCharacterLocation":return st(e.characterId,e.locationId,t);case"addToParty":return ot(e.characterId,t);case"removeFromParty":return ct(e.characterId,t);case"setRelationship":return ut(e.characterId,e.value,t);case"addRelationship":return lt(e.characterId,e.value,t);case"setCharacterStat":return dt(e.characterId,e.stat,e.value,t);case"addCharacterStat":return ht(e.characterId,e.stat,e.value,t);case"setMapEnabled":return pt(e.enabled,t);case"playMusic":return t;case"playSound":return mt(e.sound,t);case"notify":return ft(e.message,t);case"playVideo":return gt(e.file,t);default:return t}}function y(e,t){return e.reduce((n,r)=>C(r,n),t)}function B(e,t){return{...t,flags:{...t.flags,[e]:!0}}}function _(e,t){return{...t,flags:{...t.flags,[e]:!1}}}function z(e,t,n){return{...n,variables:{...n.variables,[e]:t}}}function Y(e,t,n){const r=n.variables[e],a=typeof r=="number"?r+t:t;return{...n,variables:{...n.variables,[e]:a}}}function K(e,t){return t.inventory.includes(e)?t:{...t,inventory:[...t.inventory,e],itemLocations:{...t.itemLocations,[e]:"inventory"}}}function X(e,t){return{...t,inventory:t.inventory.filter(n=>n!==e)}}function Z(e,t,n){return{...n,inventory:n.inventory.filter(r=>r!==e),itemLocations:{...n.itemLocations,[e]:t}}}function tt(e,t){return{...t,currentLocation:e}}function et(e,t){const n=t.currentTime.hour+e,r=Math.floor(n/24),a=n%24;return{...t,currentTime:{day:t.currentTime.day+r,hour:a}}}function nt(e,t,n){return{...n,questProgress:{...n.questProgress,[e]:t}}}function rt(e,t){return t.unlockedJournalEntries.includes(e)?t:{...t,unlockedJournalEntries:[...t.unlockedJournalEntries,e]}}function at(e,t){return{...t,dialogueState:{dialogueId:e,nodeId:""}}}function it(e){return{...e,dialogueState:null}}function st(e,t,n){const r=n.characterState[e];return r?{...n,characterState:{...n.characterState,[e]:{...r,location:t}}}:n}function ot(e,t){const n=t.characterState[e];return n?{...t,characterState:{...t.characterState,[e]:{...n,inParty:!0}}}:t}function ct(e,t){const n=t.characterState[e];return n?{...t,characterState:{...t.characterState,[e]:{...n,inParty:!1}}}:t}function ut(e,t,n){const r=n.characterState[e];return r?{...n,characterState:{...n.characterState,[e]:{...r,relationship:t}}}:n}function lt(e,t,n){const r=n.characterState[e];return r?{...n,characterState:{...n.characterState,[e]:{...r,relationship:r.relationship+t}}}:n}function dt(e,t,n,r){const a=r.characterState[e];return a?{...r,characterState:{...r.characterState,[e]:{...a,stats:{...a.stats,[t]:n}}}}:r}function ht(e,t,n,r){const a=r.characterState[e];if(!a)return r;const s=a.stats[t],i=typeof s=="number"?s+n:n;return{...r,characterState:{...r.characterState,[e]:{...a,stats:{...a.stats,[t]:i}}}}}function pt(e,t){return{...t,mapEnabled:e}}function ft(e,t){return{...t,notifications:[...t.notifications,e]}}function mt(e,t){return{...t,pendingSounds:[...t.pendingSounds,e]}}function gt(e,t){return{...t,pendingVideo:e}}function A(e,t){if(!e.startsWith("@"))return e;const n=e.slice(1);return t[n]??e}function bt(e){return t=>A(t,e)}function L(e,t){const n=t.locales[e.currentLocale]??{},r=x=>A(x,n),a=yt(e.currentLocation,t,r),s=St(e,t,r),i=vt(e,t,r),{dialogue:o,choices:c}=It(e,t,r),u=Tt(e,t,r),d=Et(e,t,r),m=At(e,t,r),g=wt(e,t,r),l=e.mapEnabled?Nt(e,t,r):null,f=t.locations[e.currentLocation],h=(f==null?void 0:f.music)??"",p=(f==null?void 0:f.ambient)??"",b=e.notifications.map(r),I=[...e.pendingSounds],k=e.pendingVideo;return{location:a,charactersHere:s,itemsHere:i,choices:c,dialogue:o,party:u,inventory:d,quests:m,journal:g,variables:{...e.variables},time:e.currentTime,map:l,music:h,ambient:p,notifications:b,pendingSounds:I,pendingVideo:k}}function yt(e,t,n){const r=t.locations[e];return r?{id:r.id,name:n(r.name),description:n(r.description),banner:r.banner}:{id:e,name:e,description:`Location not found: ${e}`,banner:""}}function St(e,t,n){const r=[];for(const[a,s]of Object.entries(e.characterState))if(s.location===e.currentLocation){const i=t.characters[a];i&&r.push({id:i.id,name:n(i.name),biography:n(i.biography),portrait:i.portrait,location:s.location,inParty:s.inParty,relationship:s.relationship,stats:s.stats})}return r}function vt(e,t,n){const r=[];for(const[a,s]of Object.entries(e.itemLocations))if(s===e.currentLocation){const i=t.items[a];i&&r.push({id:i.id,name:n(i.name),description:n(i.description),icon:i.icon,image:i.image,stats:i.stats})}return r}function It(e,t,n){var c,u;if(!e.dialogueState)return{dialogue:null,choices:[]};const r=t.dialogues[e.dialogueState.dialogueId];if(!r)return{dialogue:null,choices:[]};const a=r.nodes.find(d=>{var m;return d.id===((m=e.dialogueState)==null?void 0:m.nodeId)});if(!a)return{dialogue:null,choices:[]};const s=a.speaker?n(((c=t.characters[a.speaker])==null?void 0:c.name)??a.speaker):"Narrator",i={speaker:a.speaker,speakerName:s,text:n(a.text),portrait:a.portrait??((u=t.characters[a.speaker??""])==null?void 0:u.portrait),voice:a.voice},o=a.choices.filter(d=>!d.conditions||d.conditions.length===0?!0:E(d.conditions,e)).map(d=>({id:d.id,text:n(d.text)}));return{dialogue:i,choices:o}}function Tt(e,t,n){const r=[];for(const[a,s]of Object.entries(e.characterState))if(s.inParty){const i=t.characters[a];i&&r.push({id:i.id,name:n(i.name),biography:n(i.biography),portrait:i.portrait,location:s.location,inParty:s.inParty,relationship:s.relationship,stats:s.stats})}return r}function Et(e,t,n){return e.inventory.map(r=>{const a=t.items[r];return a?{id:a.id,name:n(a.name),description:n(a.description),icon:a.icon,image:a.image,stats:a.stats}:null}).filter(r=>r!==null)}function At(e,t,n){const r=[];for(const[a,s]of Object.entries(e.questProgress)){const i=t.quests[a];if(!i)continue;const o=i.stages.find(c=>c.id===s);o&&r.push({id:i.id,name:n(i.name),description:n(i.description),currentStage:o.id,currentStageDescription:n(o.description)})}return r}function wt(e,t,n){return e.unlockedJournalEntries.map(r=>{const a=t.journalEntries[r];return a?{id:a.id,title:n(a.title),text:n(a.text),category:a.category}:null}).filter(r=>r!==null)}function Nt(e,t,n){const r=Object.keys(t.maps);if(r.length===0)return null;const a=t.maps[r[0]];if(!a)return null;const s=a.locations.map(i=>{const o=t.locations[i.id];return{id:i.id,name:o?n(o.name):i.id,x:i.x,y:i.y,isCurrent:i.id===e.currentLocation}});return{id:a.id,name:n(a.name),image:a.image,scale:a.scale,locations:s}}class Ct{constructor(t,n){T(this,"registry");T(this,"state");this.registry=t,this.state=n}newGame(t){const n={};for(const[a,s]of Object.entries(this.registry.characters))n[a]={location:s.location,inParty:!1,relationship:0,stats:{...s.stats}};const r={};for(const[a,s]of Object.entries(this.registry.items))r[a]=s.location;return this.state={currentLocation:t.startLocation,currentTime:{...t.startTime},flags:{...t.startFlags},variables:{...t.startVariables},inventory:[...t.startInventory],questProgress:{},unlockedJournalEntries:[],playerNotes:[],dialogueState:null,characterState:n,itemLocations:r,mapEnabled:!0,notifications:[],pendingSounds:[],pendingVideo:null,currentLocale:"en"},this.checkTriggeredDialogues(),this.buildSnapshotAndClearTransients()}loadGame(t){return this.state={...t.state},this.buildSnapshotAndClearTransients()}saveGame(){return{version:"1.0",timestamp:new Date().toISOString(),state:{...this.state}}}selectChoice(t){if(!this.state.dialogueState)return this.buildSnapshotAndClearTransients();const n=this.registry.dialogues[this.state.dialogueState.dialogueId];if(!n)return this.buildSnapshotAndClearTransients();const r=n.nodes.find(i=>{var o;return i.id===((o=this.state.dialogueState)==null?void 0:o.nodeId)});if(!r)return this.buildSnapshotAndClearTransients();const a=r.choices.find(i=>i.id===t);if(!a)return this.buildSnapshotAndClearTransients();a.effects&&(this.state=y(a.effects,this.state));const s=n.nodes.find(i=>i.id===a.next);return s?(this.state={...this.state,dialogueState:{dialogueId:n.id,nodeId:s.id}},s.effects&&(this.state=y(s.effects,this.state))):this.state={...this.state,dialogueState:null},this.buildSnapshotAndClearTransients()}talkTo(t){const n=this.registry.characters[t];if(!n||!n.dialogue)return this.buildSnapshotAndClearTransients();const r=this.registry.dialogues[n.dialogue];if(!r)return this.buildSnapshotAndClearTransients();const a=r.nodes.find(s=>s.id===r.startNode);return a?(this.state={...this.state,dialogueState:{dialogueId:r.id,nodeId:a.id}},a.effects&&(this.state=y(a.effects,this.state)),this.buildSnapshotAndClearTransients()):this.buildSnapshotAndClearTransients()}takeItem(t){return this.state.itemLocations[t]!==this.state.currentLocation?this.buildSnapshotAndClearTransients():(this.state={...this.state,inventory:[...this.state.inventory,t],itemLocations:{...this.state.itemLocations,[t]:"inventory"}},this.buildSnapshotAndClearTransients())}travelTo(t){if(!this.state.mapEnabled)return this.buildSnapshotAndClearTransients();const n=Object.keys(this.registry.maps);if(n.length===0)return this.buildSnapshotAndClearTransients();const r=this.registry.maps[n[0]];if(!r)return this.buildSnapshotAndClearTransients();const a=r.locations.find(m=>m.id===this.state.currentLocation),s=r.locations.find(m=>m.id===t);if(!a||!s)return this.buildSnapshotAndClearTransients();const i=Math.sqrt(Math.pow(s.x-a.x,2)+Math.pow(s.y-a.y,2)),o=Math.round(i*r.scale),c=this.state.currentTime.hour+o,u=Math.floor(c/24),d=c%24;return this.state={...this.state,currentLocation:t,dialogueState:null,currentTime:{day:this.state.currentTime.day+u,hour:d}},this.checkTriggeredDialogues(),this.buildSnapshotAndClearTransients()}writeNote(t,n){const r={id:`note_${Date.now()}`,title:t,text:n};return this.state={...this.state,playerNotes:[...this.state.playerNotes,r]},this.buildSnapshotAndClearTransients()}deleteNote(t){return this.state={...this.state,playerNotes:this.state.playerNotes.filter(n=>n.id!==t)},this.buildSnapshotAndClearTransients()}setLocale(t){return this.state={...this.state,currentLocale:t},this.buildSnapshotAndClearTransients()}getSnapshot(){return this.buildSnapshotAndClearTransients()}buildSnapshotAndClearTransients(){const t=L(this.state,this.registry);return this.state={...this.state,notifications:[],pendingSounds:[],pendingVideo:null},t}checkTriggeredDialogues(){for(const t of Object.values(this.registry.dialogues)){if(t.triggerLocation!==this.state.currentLocation||t.conditions&&!E(t.conditions,this.state))continue;const n=t.nodes.find(r=>r.id===t.startNode);if(n){this.state={...this.state,dialogueState:{dialogueId:t.id,nodeId:n.id}},n.effects&&(this.state=y(n.effects,this.state));break}}}}function Lt(e){return e.split(`
|
|
2
|
+
`).map((t,n)=>({original:t,lineNumber:n+1})).map(({original:t,lineNumber:n})=>{let r=t;const a=t.indexOf("#");if(a===-1)r=t;else{const o=t.match(/"[^"]*"/);if(o){const c=t.indexOf(o[0]),u=c+o[0].length;a<c?r=t.substring(0,a):a>=c&&a<u?r=t.substring(0,u)+t.substring(u).split("#")[0]:r=t.substring(0,a)}else r=t.substring(0,a)}const s=r.length-r.trimStart().length;return{line:r.trim(),lineNumber:n,indent:s}}).filter(t=>t.line.length>0)}function w(e){const t=e.trim();return t.startsWith("@")?t:t.startsWith('"')&&t.endsWith('"')?t.substring(1,t.length-1):t}function S(e){const t=e.trim().split(/\s+/),n=t[0];switch(n){case"hasFlag":return{type:"hasFlag",flag:t[1]};case"notFlag":return{type:"notFlag",flag:t[1]};case"hasItem":return{type:"hasItem",itemId:t[1]};case"variableEquals":return{type:"variableEquals",variable:t[1],value:isNaN(Number(t[2]))?t[2]:Number(t[2])};case"variableGreaterThan":return{type:"variableGreaterThan",variable:t[1],value:Number(t[2])};case"variableLessThan":return{type:"variableLessThan",variable:t[1],value:Number(t[2])};case"atLocation":return{type:"atLocation",locationId:t[1]};case"questAtStage":return{type:"questAtStage",questId:t[1],stageId:t[2]};case"characterAt":return{type:"characterAt",characterId:t[1],locationId:t[2]};case"characterInParty":return{type:"characterInParty",characterId:t[1]};case"relationshipAbove":return{type:"relationshipAbove",characterId:t[1],value:Number(t[2])};case"relationshipBelow":return{type:"relationshipBelow",characterId:t[1],value:Number(t[2])};case"timeIs":return{type:"timeIs",startHour:Number(t[1]),endHour:Number(t[2])};case"itemAt":return{type:"itemAt",itemId:t[1],locationId:t[2]};default:throw new Error(`Unknown condition type: ${n}`)}}function v(e){const t=e.trim();if(t.startsWith("NOTIFY "))return{type:"notify",message:w(t.substring(7))};if(t.startsWith("MUSIC "))return{type:"playMusic",track:t.substring(6).trim()};if(t.startsWith("SOUND "))return{type:"playSound",sound:t.substring(6).trim()};if(t.startsWith("VIDEO "))return{type:"playVideo",file:t.substring(6).trim()};const n=t.split(/\s+/),r=n[0];switch(r){case"SET":if(n[1]==="flag")return{type:"setFlag",flag:n[2]};if(n[1]==="variable")return{type:"setVariable",variable:n[2],value:isNaN(Number(n[3]))?n[3]:Number(n[3])};if(n[1]==="questStage")return{type:"setQuestStage",questId:n[2],stageId:n[3]};if(n[1]==="characterLocation")return{type:"setCharacterLocation",characterId:n[2],locationId:n[3]};if(n[1]==="relationship")return{type:"setRelationship",characterId:n[2],value:Number(n[3])};if(n[1]==="characterStat")return{type:"setCharacterStat",characterId:n[2],stat:n[3],value:isNaN(Number(n[4]))?n[4]:Number(n[4])};if(n[1]==="mapEnabled")return{type:"setMapEnabled",enabled:n[2]==="true"};throw new Error(`Unknown SET effect: ${n[1]}`);case"CLEAR":if(n[1]==="flag")return{type:"clearFlag",flag:n[2]};throw new Error(`Unknown CLEAR effect: ${n[1]}`);case"ADD":if(n[1]==="variable")return{type:"addVariable",variable:n[2],value:Number(n[3])};if(n[1]==="item")return{type:"addItem",itemId:n[2]};if(n[1]==="journalEntry")return{type:"addJournalEntry",entryId:n[2]};if(n[1]==="toParty")return{type:"addToParty",characterId:n[2]};if(n[1]==="relationship")return{type:"addRelationship",characterId:n[2],value:Number(n[3])};if(n[1]==="characterStat")return{type:"addCharacterStat",characterId:n[2],stat:n[3],value:Number(n[4])};throw new Error(`Unknown ADD effect: ${n[1]}`);case"REMOVE":if(n[1]==="item")return{type:"removeItem",itemId:n[2]};if(n[1]==="fromParty")return{type:"removeFromParty",characterId:n[2]};throw new Error(`Unknown REMOVE effect: ${n[1]}`);case"MOVE":if(n[1]==="item")return{type:"moveItem",itemId:n[2],locationId:n[3]};throw new Error(`Unknown MOVE effect: ${n[1]}`);case"GOTO":if(n[1]==="location")return{type:"goToLocation",locationId:n[2]};throw new Error("GOTO should not be parsed as an effect");case"ADVANCE":if(n[1]==="time")return{type:"advanceTime",hours:Number(n[2])};throw new Error(`Unknown ADVANCE effect: ${n[1]}`);case"START":if(n[1]==="dialogue")return{type:"startDialogue",dialogueId:n[2]};throw new Error(`Unknown START effect: ${n[1]}`);case"END":if(n[1]==="dialogue")return{type:"endDialogue"};throw new Error("END should not be parsed as an effect");default:throw new Error(`Unknown effect keyword: ${r}`)}}function kt(e,t,n){const r=e[t],a=w(r.line.substring(7)),s=[],i=[];let o="",c=t+1;const u=r.indent;for(;c<e.length;){const l=e[c];if(l.line==="END"&&l.indent===u){c++;break}if(l.line.startsWith("REQUIRE ")){const f=l.line.substring(8).trim();s.push(S(f)),c++}else if(l.line.startsWith("GOTO ")){const f=l.line.substring(5).trim();if(f.startsWith("location ")){const h=f.substring(9).trim();i.push({type:"goToLocation",locationId:h}),i.push({type:"endDialogue"}),o=""}else o=f;c++}else l.line.includes(":")||i.push(v(l.line)),c++}const d=a.replace(/[@"]/g,"").replace(/[^a-z0-9]/gi,"_");return{choice:{id:`${n}_choice_${d.toLowerCase().substring(0,30)}`,text:a,conditions:s.length>0?s:void 0,effects:i.length>0?i:void 0,next:o||""},nextIndex:c}}function xt(e,t){const n=e[t],r=n.line.substring(3).trim(),a=S(r);let s;const i=[];let o=t+1;const c=n.indent;for(;o<e.length;){const u=e[o];if(u.line==="END"&&u.indent===c){o++;break}u.line.startsWith("GOTO ")?(s=u.line.substring(5).trim(),o++):(i.push(v(u.line)),o++)}return{condition:a,next:s,effects:i,nextIndex:o}}function Ot(e,t){const r=e[t].line.substring(5).trim();let a=null,s="",i,o;const c=[],u=[],d=[];let m;const g=[];let l=t+1;for(;l<e.length;){const h=e[l];if(h.line.startsWith("NODE "))break;if(h.line.includes(":")&&!h.line.startsWith("VOICE")){const p=h.line.indexOf(":"),b=h.line.substring(0,p).trim(),I=h.line.substring(p+1).trim();b==="NARRATOR"?a=null:a=b.toLowerCase(),s=w(I),l++}else if(h.line.startsWith("VOICE "))i=h.line.substring(6).trim(),l++;else if(h.line.startsWith("PORTRAIT "))o=h.line.substring(9).trim(),l++;else if(h.line.startsWith("CHOICE ")){const p=kt(e,l,r);u.push(p.choice),l=p.nextIndex}else if(h.line.startsWith("IF ")){const p=xt(e,l);p.next&&g.push({condition:p.condition,next:p.next}),d.push(...p.effects),l=p.nextIndex}else if(h.line.startsWith("GOTO ")){const p=h.line.substring(5).trim();if(p.startsWith("location ")){const b=p.substring(9).trim();d.push({type:"goToLocation",locationId:b}),d.push({type:"endDialogue"})}else m=p;l++}else d.push(v(h.line)),l++}const f={id:r,speaker:a,text:s,voice:i,portrait:o,conditions:c.length>0?c:void 0,choices:u,effects:d.length>0?d:void 0,next:m};return g.length>0&&(f.conditionalNext=g),{node:f,nextIndex:l}}function Vt(e,t){const n=Lt(e);let r;const a=[],s=[];let i="",o=0;for(;o<n.length;){const c=n[o];if(c.line.startsWith("TRIGGER "))r=c.line.substring(8).trim(),o++;else if(c.line.startsWith("REQUIRE ")){const u=c.line.substring(8).trim();a.push(S(u)),o++}else if(c.line.startsWith("NODE ")){const u=Ot(n,o);s.push(u.node),i||(i=u.node.id),o=u.nextIndex}else throw new Error(`Unexpected token at line ${c.lineNumber}: ${c.line}`)}return{id:t,triggerLocation:r,conditions:a.length>0?a:void 0,startNode:i,nodes:s}}const Rt="0.0.1";exports.Engine=Ct;exports.VERSION=Rt;exports.applyEffect=C;exports.applyEffects=y;exports.buildSnapshot=L;exports.createResolver=bt;exports.evaluateCondition=N;exports.evaluateConditions=E;exports.parseCondition=S;exports.parseDialogue=Vt;exports.parseEffect=v;exports.resolveText=A;
|